贪吃蛇小游戏基本简单布局

代码:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Layui贪吃蛇小游戏</title>
  <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/layui/2.5.7/css/layui.css">
</head>
<body>
  <div class="layui-container">
    <h1 class="layui-header">Layui贪吃蛇小游戏</h1>
    <div class="layui-row">
      <div class="layui-col-md8">
        <canvas id="gameCanvas" width="400" height="400"></canvas>
      </div>
      <div class="layui-col-md4">
        <div class="layui-card">
          <div class="layui-card-header">游戏控制</div>
          <div class="layui-card-body">
            <button id="startBtn" class="layui-btn">开始游戏</button>
            <button id="pauseBtn" class="layui-btn">暂停游戏</button>
            <button id="resetBtn" class="layui-btn">重置游戏</button>
          </div>
        </div>
      </div>
    </div>
  </div>

  <script src="https://cdn.bootcdn.net/ajax/libs/layui/2.5.7/layui.js"></script>
  <script>
    layui.use(['layer', 'form'], function(){
      var layer = layui.layer;
      var form = layui.form;

      // 游戏逻辑
      var canvas = document.getElementById('gameCanvas');
      var ctx = canvas.getContext('2d');
      var snakeSize = 10;
      var snake = [
        {x: 200, y: 200},
        {x: 190, y: 200},
        {x: 180, y: 200},
        {x: 170, y: 200},
        {x: 160, y: 200}
      ];
      var food = {x: 0, y: 0};
      var dx = 10;
      var dy = 0;

      function drawSnakePart(snakePart) {
        ctx.fillStyle = 'lightgreen';
        ctx.strokeStyle = 'darkgreen';
        ctx.fillRect(snakePart.x, snakePart.y, snakeSize, snakeSize);
        ctx.strokeRect(snakePart.x, snakePart.y, snakeSize, snakeSize);
      }

      function drawSnake() {
        snake.forEach(drawSnakePart);
      }

      function advanceSnake() {
        const head = {x: snake[0].x + dx, y: snake[0].y + dy};
        snake.unshift(head);
        const didEatFood = snake[0].x === food.x && snake[0].y === food.y;
        if (didEatFood) {
          createFood();
        } else {
          snake.pop();
        }
      }

      function clearCanvas() {
        ctx.fillStyle = 'white';
        ctx.strokeStyle = 'black';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.strokeRect(0, 0, canvas.width, canvas.height);
      }

      function createFood() {
        food.x = Math.floor(Math.random() * canvas.width / 10) * 10;
        food.y = Math.floor(Math.random() * canvas.height / 10) * 10;
        snake.forEach(function isFoodOnSnake(part) {
          const foodIsOnSnake = part.x === food.x && part.y === food.y;
          if (foodIsOnSnake) {
            createFood();
          }
        });
      }

      function drawFood() {
        ctx.fillStyle = 'red';
        ctx.strokeStyle = 'darkred';
        ctx.fillRect(food.x, food.y, snakeSize, snakeSize);
        ctx.strokeRect(food.x, food.y, snakeSize, snakeSize);
      }

      function main() {
        if (didGameEnd()) return;
        setTimeout(function onTick() {
          changingDirection = false;
          clearCanvas();
          drawFood();
          advanceSnake();
          drawSnake();
          main();
        }, 100)
      }

      function didGameEnd() {
        for (let i = 4; i < snake.length; i++) {
          if (snake[i].x === snake[0].x && snake[i].y === snake[0].y) return true;
        }
        const hitLeftWall = snake[0].x < 0;
        const hitRightWall = snake[0].x > canvas.width - 10;
        const hitTopWall = snake[0].y < 0;
        const hitBottomWall = snake[0].y > canvas.height - 10;
        return hitLeftWall || hitRightWall || hitTopWall || hitBottomWall;
      }

      function resetGame() {
        snake = [
          {x: 200, y: 200},
          {x: 190, y: 200},
          {x: 180, y: 200},
          {x: 170, y: 200},
          {x: 160, y: 200}
        ];
        dx = 10;
        dy = 0;
        createFood();
      }

      createFood();
      main();

      document.addEventListener('keydown', changeDirection);

      function changeDirection(event) {
        const LEFT_KEY = 37;
        const RIGHT_KEY = 39;
        const UP_KEY = 38;
        const DOWN_KEY = 40;

        if (changingDirection) return;
        changingDirection = true;

        const keyPressed = event.keyCode;
        const goingUp = dy === -10;
        const goingDown = dy === 10;
        const goingRight = dx === 10;
        const goingLeft = dx === -10;

        if (keyPressed === LEFT_KEY && !goingRight) {
          dx = -10;
          dy = 0;
        }

        if (keyPressed === UP_KEY && !goingDown) {
          dx = 0;
          dy = -10;
        }

        if (keyPressed === RIGHT_KEY && !goingLeft) {
          dx = 10;
          dy = 0;
        }

        if (keyPressed === DOWN_KEY && !goingUp) {
          dx = 0;
          dy = 10;
        }
      }

      // 游戏控制
      var startBtn = document.getElementById('startBtn');
      var pauseBtn = document.getElementById('pauseBtn');
      var resetBtn = document.getElementById('resetBtn');

      startBtn.onclick = function() {
        main();
      }

      pauseBtn.onclick = function() {
        clearTimeout(main);
      }

      resetBtn.onclick = function() {
        resetGame();
      }
    });
  </script>
</body>
</html>

结果图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/195743.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Intel FPGA】D5005 使用笔记

项目总目标&#xff0c;在AFU中实现xx算法DDR 1.FPGA device &#xff1a;1SX280HN2F43E2VG 2 .硬件架构图 3.DDR信息 4.FIM &#xff08;FPAG Interface Manager&#xff09; The FIM contains the FPGA logic to support the accelerators, including the PCIe IP core, …

【解决视觉引导多个位置需要标定多个位置的问题】

** 以下只针对2D定位&#xff0c;就是只有X、Y、Rz三个自由度的情况。** 假设一种情况&#xff0c;当视觉给机器人做引导任务时&#xff0c;零件有多个&#xff0c;分布在料框里&#xff0c;视觉需要走多个位置去拍&#xff0c;那么只需要对第一个位置确定拍照位&#xff0c;确…

【Flutter】graphic图表的快速上手

简介 graphic是一个数据可视化语法和Flutter图表库。 官方github示例 网上可用资源很少,只有作者的几篇文章,并且没有特别详细的文档,使用的话还是需要一定的时间去调研,在此简单记录。 示例 以折线图为例(因为我只用到了折线图,但其他的图大差不差) 创建一个两个文…

运行时错误/缺陷到底是什么缺陷

运行时错误(Run-time Error)是一种跟程序运行状态相关的缺陷。这类缺陷不能通过直接禁用相关特性来屏蔽&#xff0c;而是需要通过分析变量的数值状态来发现可能的异常。简单来说&#xff0c;这些缺陷通常只有当程序执行起来以后&#xff0c;才能逐渐暴露出的缺陷&#xff0c;一…

Buzz库python代码示例

Buzz库来编写一个下载器程序。 php <?php require_once vendor/autoload.php; // 引入Buzz库 use Buzz\Browser; use Buzz\Message\Response; $browser new Browser(); // 设置 $browser->setHttpClient(new HttpClientProxy([ host > , port > , ])…

企业员工为什么不喜欢使用MES管理系统

随着科技的进步和数字化转型的趋势&#xff0c;越来越多的企业开始引入MES管理系统解决方案以提升生产效率和质量。然而&#xff0c;尽管MES管理系统的潜在优势众所周知&#xff0c;但其在企业内部的推广和应用却常常面临员工的抵触和反感。本文将从多个角度探讨企业员工为什么…

DBeaver连接MySQL提示“Public Key Retrieval is not allowed“问题解决方式

更新时间&#xff1a;2023年10月31日 11:37:53 作者&#xff1a;产品人小柒 dbeaver数据库连接工具,可以支持几乎所有的主流数据库.mysql,oracle.sqlserver,db2 等等,这篇文章主要给大家介绍了关于DBeaver连接MySQL提示"Public Key Retrieval is not allowed"问…

IDEA删除的文件怎么找回更新

一、 查找本地历史记录IDEA在进行代码版本管理时&#xff0c;会自动创建本地历史记录&#xff0c;如果我们误删了文件&#xff0c;可以通过查找本地历史记录来找回文件。 1.在项目中&#xff0c;选中被删文件的父级目录&#xff0c;“File”->“Local History”->“Show…

『VUE3后台—大事件管理系统』

项目地址&#xff1a;https://gitee.com/csheng-gitee/vue3-big-event-admin 技术栈&#xff1a;VUE3 Pinia Pnpm&#xff08;本项目暂不用 typescript&#xff09; 一、前期准备工作 1、创建项目 npm install -g pnpm pnpm create vue2、ESLint 配置 (1) 禁用 prettier 插…

java第二十章总结多线程

20.2创建线程 20.2.1继承Thread类 Thread类是Java.lang包中的一个类&#xff0c;从这个类中实例化的对象代表线程&#xff0c;程序员启动一个新线程需要建议Thread实例。 public class ThreadTest extedns Thread{} run方法格式&#xff1a; public void run(){} 20.1让线程…

C语言--根据成绩判断等级

一.题目描述 如果学生的成绩小于60分&#xff0c;那么输出不及格 如果学生的成绩大于60分小于85分&#xff0c;那么输出良好 如果学生的成绩大于85分&#xff0c;那么输出优秀 二.代码实现 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> //根据成绩打印等级 //scor…

06-学成在线添加课程,包含课程基本信息,营销信息,课程计划信息,师资信息

添加课程基本/营销/计划信息 界面原型 第一步: 用户进入课程查询列表,点击添加课程按钮,选择课程类型是直播还是录播,课程类型不同那么授课方式也不同 添加的课程和教学机构是一对一的关系 第二步: 用户选完课程形式后,点击下一步填写课程的基本信息和营销信息(两张表) 用户…

在Visual Studio Code中安装加速TypeScript程序开发的插件

在Visual Studio Code中安装加速TypeScript程序开发的插件 Install Extensions on Visual Studio Code for TypeScript Application Development By Jackson 2023-11-28 众所周知&#xff0c;微软的Visual Studio Code是一款轻量级、功能强大的集成开发环境。它支持各种编程语…

ESXi 添加虚拟闪存 无可选设备问题排查

虚拟内存是计算机系统中的一种技术&#xff0c;它可以将计算机硬盘的一部分空间作为临时存储器来使用。当计算机的物理内存&#xff08;RAM&#xff09;不足时&#xff0c;操作系统可以将部分数据从内存移至硬盘的虚拟内存空间中&#xff0c;以释放内存供其他程序使用。虚拟内存…

双通道 12V 直流电机驱动芯片GC8548,可替代LV8548/LV8549/ONSEMI,内置 LDO,不需要逻辑电源,输入 兼容 3.3V 与 5V

GC8548 是一款双通道 12V 直流电机驱动芯 片&#xff0c;为摄像机、消费类产品、玩具和其他低压或 者电池供电的运动控制类应用提供了集成的电机 驱动解决方案。芯片一般用来驱动两个直流电机 或者驱动一个步进电机。 它可以工作在 3.8~12V 的电源电压上&#xff0c; 每通道能提…

全能音乐制作环境——水果编曲软件FL Studio 21.1版本下载安装配置

目录 前言一、FL Studio 安装二、使用配置总结 前言 FL Studio是一款流行的图像线软件制作和编辑音频文件。作为一款领先的创新产品&#xff0c;该软件能够满足在创作音乐方面的需求。有了这个产品&#xff0c;可以完成制作音乐的整个过程。可以使用这个软件进行写作&#xff…

Ubuntu新手使用教程

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Net6.0或Net7.0项目升级到Net8.0 并 消除.Net8中SqlSugar的警告

本文基于NetCore3.1或Net6.0项目升级到Net7.0&#xff0c;参考连接&#xff1a;NetCore3.1或Net6.0项目升级到Net7.0-CSDN博客 所有项目按照此步骤操作一遍&#xff0c;完成后再将所有引用的包&#xff08;即 *.dll&#xff09;更新升级到最新版&#xff08;注意&#xff1a;有…

【软件测试面试】项目经验回答+面试技巧和方法汇总...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、测试面试时问你…

如何设置带有密码的excel只读模式?

Excel只读模式大家都不陌生&#xff0c;那大家知道带有密码的只读模式吗&#xff1f;今天给大家分享如何设置带有密码的只读模式。 打开excel文件&#xff0c;将文件进行【另存为】设置&#xff0c;然后停留在保存路径的界面中&#xff0c;我们点击下面的工具 – 常规选项 在常…
最新文章