打造你的贪吃蛇游戏:HTML、CSS与JavaScript的完美结合

🌟 前言

欢迎来到我的技术小宇宙!🌌 这里不仅是我记录技术点滴的后花园,也是我分享学习心得和项目经验的乐园。📚 无论你是技术小白还是资深大牛,这里总有一些内容能触动你的好奇心。🔍

  • 🤖 洛可可白:个人主页

  • 🔥 个人专栏:✅前端技术 ✅后端技术

  • 🏠 个人博客:洛可可白博客

  • 🐱 代码获取:bestwishes0203

  • 📷 封面壁纸:洛可可白wallpaper

在这里插入图片描述

文章目录

  • 打造你的贪吃蛇游戏:HTML、CSS与JavaScript的完美结合
    • 摘要
    • 体验地址
    • 1. 创建游戏的基本结构
    • 2. 设计游戏界面
    • 3. 初始化游戏变量
    • 4. 食物位置的随机化
    • 5. 更新等级和分数
    • 6. 蛇的移动逻辑
    • 7. 键盘事件处理
    • 8. 初始化游戏
    • 9. 全部代码
    • 结论

打造你的贪吃蛇游戏:HTML、CSS与JavaScript的完美结合

摘要

在本教程中,我们将通过一个简单的贪吃蛇游戏来学习如何使用HTML、CSS和JavaScript创建一个有趣的网页游戏。我们将逐步解读代码,了解游戏的构建过程,并提供必要的注释来帮助理解每个部分的功能。

体验地址

PC端体验地址: 洛可可白⚡️贪吃蛇

(暂时只支持键盘输入操作)

在这里插入图片描述

1. 创建游戏的基本结构

首先,我们需要创建一个HTML页面,它将包含游戏的所有元素,如游戏区域、分数和等级显示。

<!DOCTYPE html>
<html lang="en">
<head>
  <!-- ... 其他头部代码 ... -->
  <title>洛可可白⚡️贪吃蛇</title>
  <style>
    /* ... 样式代码 ... */
  </style>
</head>
<body>
  <!-- ... 页面内容 ... -->
  <script>
    // ... JavaScript 代码 ...
  </script>
</body>
</html>

2. 设计游戏界面

使用CSS来设计游戏的界面,包括游戏区域的样式、蛇和食物的外观。

/* ... 样式代码 ... */
.gamBox {
  /* ... 游戏盒子样式 ... */
        width: 500px;
        height: 500px;
        border: 10px solid #393c1b;
        margin: 20px auto;
        background-color: #b6b327;
        border-radius: 20px;
        display: flex;
        flex-direction: column;
        justify-content: space-around;
        align-items: center;
}
.screen {
  /* ... 屏幕样式 ... */
        width: 400px;
        height: 400px;
        border: 1px solid #000;
        position: relative;
}
  /* ... 蛇的样式 ... */
      .snake .snake-head {
        width: 20px;
        height: 20px;
        border: 1px solid #4d7d2b;
        background-color: #000;
        position: absolute;
        top: 0;
        left: 0;
      }

      .snake span {
        font-size: 17px;
        position: absolute;
        left: -2.7px;
        top: -3px;
      }

      .snake-body > div {
        position: absolute;
        top: 0;
        left: 0;
        width: 20px;
        height: 20px;
        border: 1px solid #4d7d2b;
        background-color: #000;
      }

  /* ... 食物的样式 ... */
 .food {
        width: 20px;
        height: 20px;
        font-size: 8px;
        text-align: left;
        position: absolute;
        top: 10px;
        left: 0;
      }

      .food span {
        font-size: 17px;
        position: absolute;
        left: -1.7px;
        top: -2px;
      }

3. 初始化游戏变量

在JavaScript中,我们定义了一些变量来控制游戏的逻辑,如基础倍数、最大等级、食物位置、等级和分数。

const foundationNumber = 20;
const maxGrade = 10;
let foodSeat = { top. 20, left. 20 };
let register = { score. 0, grade. 1 };

4. 食物位置的随机化

创建一个函数来随机生成食物的位置,并在游戏开始时调用它。

const changeFoodSeat = () => {
  // ... 随机位置代码 ...
          foodSeat.top = randomNumber(0, 20) * foundationNumber;
      foodSeat.left = randomNumber(0, 20) * foundationNumber;

      document.querySelector(".food").style.cssText =
        "left:" + foodSeat.left + "px;top:" + foodSeat.top + "px";
};

5. 更新等级和分数

每当蛇吃到食物时,我们需要更新等级和分数,并在页面上显示。

const changeScore = () => {
  // ... 更新分数和等级代码 ...
          register.score++;
      if (register.grade < 10) {
        register.grade = Math.ceil(register.score / 10);
      }

      document.querySelector(".grade").innerText = register.grade;
      document.querySelector(".score").innerText = register.score;
};

6. 蛇的移动逻辑

编写蛇的移动逻辑,包括方向控制、身体部分的移动以及检测碰撞。

const handleWatchEnter = (e) => {
  // ... 蛇的移动逻辑 ...
    let previousTop = snakeSeat.top;
      let previousLeft = snakeSeat.left;
      //通过便利每个身体部分来进行移动
      snakeLength.forEach((ele, index) => {
        let temporaryTop = ele.top;
        let temporaryLeft = ele.left;
        ele.top = previousTop;
        ele.left = previousLeft;
        previousTop = temporaryTop;
        previousLeft = temporaryLeft;
        document.querySelectorAll(".snake-body>div")[index].style.cssText =
          "left:" + ele.left + "px;top:" + ele.top + "px";
};

7. 键盘事件处理

监听键盘事件来控制蛇的移动方向。

document.addEventListener("keydown", (e) => {
  // ... 键盘事件处理代码 ...
});

8. 初始化游戏

最后,我们初始化游戏,设置初始位置和分数,并开始游戏循环。

const init = () => {
  // ... 初始化游戏代码 ...
          document.querySelector(".snake-head").style.cssText =
        "left:" + 0 + "px;top:" + 0 + "px";
      document.querySelector(".snake-body").innerHTML = "";
      document.querySelector(".grade").innerText = register.grade;
      document.querySelector(".score").innerText = register.score;
      changeFoodSeat();
      handleWatchEnter();
    };

    document.addEventListener("keydown", (e) => {
      if (
        (e.code == "ArrowUp" && direction != "ArrowDown") ||
        (e.code == "ArrowLeft" && direction != "ArrowRight") ||
        (e.code == "ArrowRight" && direction != "ArrowLeft") ||
        (e.code == "ArrowDown" && direction != "ArrowUp")
      ) {
        direction = e.code;
      }
};
init();

9. 全部代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>洛可可白⚡️贪吃蛇</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }

      p {
        text-align: center;
        font-size: 23px;
        font-weight: 600;
      }

      .gamBox {
        width: 500px;
        height: 500px;
        border: 10px solid #393c1b;
        margin: 20px auto;
        background-color: #b6b327;
        border-radius: 20px;
        display: flex;
        flex-direction: column;
        justify-content: space-around;
        align-items: center;
      }

      /* //下方等级、得分盒子/ */
      .integral {
        width: 398px;
        height: 25px;
        display: flex;
        justify-content: space-between;
        font-size: 16px;
        font-family: "Trebuchet MS", "Lucida Sans Unicode", "Lucida Grande",
          "Lucida Sans", Arial, sans-serif;
        font-weight: 700;
      }

      /* //屏幕样式 */
      .screen {
        width: 400px;
        height: 400px;
        border: 1px solid #000;
        position: relative;
      }

      /* //蛇的样式 */
      .snake .snake-head {
        width: 20px;
        height: 20px;
        border: 1px solid #4d7d2b;
        background-color: #000;
        position: absolute;
        top: 0;
        left: 0;
      }

      .snake span {
        font-size: 17px;
        position: absolute;
        left: -2.7px;
        top: -3px;
      }

      .snake-body > div {
        position: absolute;
        top: 0;
        left: 0;
        width: 20px;
        height: 20px;
        border: 1px solid #4d7d2b;
        background-color: #000;
      }

      /* //食物的样式 */

      .food {
        width: 20px;
        height: 20px;
        font-size: 8px;
        text-align: left;
        position: absolute;
        top: 10px;
        left: 0;
      }

      .food span {
        font-size: 17px;
        position: absolute;
        left: -1.7px;
        top: -2px;
      }
    </style>
  </head>

  <body>
    <p>贪吃蛇</p>
    <div class="gamBox">
      <div class="screen">
        <div class="snake">
          <div class="snake-head">
            <span>😁</span>
          </div>
          <div class="snake-body"></div>
        </div>

        <div class="food">
          <span>🐷</span>
        </div>
      </div>
      <div class="integral">
        <div>等级(grade)<span class="grade"></span></div>
        <div>分数(score)<span class="score"></span></div>
      </div>
    </div>
  </body>

  <script>
    /***
     * 公用变量
     * @foundationNumber 基础倍数:移动、食物随机位置量的倍数
     * @maxGrade 最大的等级
     */

    const foundationNumber = 20;
    const maxGrade = 10;

    /***
     * 食物相关
     */
    const randomNumber = (min, max) => {
      return Math.floor(Math.random() * (max - min)) + min;
    };
    let foodSeat = {
      top: 20,
      left: 20,
    };
    const changeFoodSeat = () => {
      foodSeat.top = randomNumber(0, 20) * foundationNumber;
      foodSeat.left = randomNumber(0, 20) * foundationNumber;

      document.querySelector(".food").style.cssText =
        "left:" + foodSeat.left + "px;top:" + foodSeat.top + "px";
    };

    /***
     * 等级、分数相关
     */
    let register = {
      score: 0,
      grade: 1,
    };
    const changeScore = () => {
      register.score++;
      if (register.grade < 10) {
        register.grade = Math.ceil(register.score / 10);
      }

      document.querySelector(".grade").innerText = register.grade;
      document.querySelector(".score").innerText = register.score;
    };

    /***
     * 蛇相关
     */

    let direction = ""; //移动方向
    let snakeLength = [];
    let snakeSeat = {
      top: 0,
      left: 0,
    };
    const handleWatchEnter = (e) => {
      let previousTop = snakeSeat.top;
      let previousLeft = snakeSeat.left;
      //通过便利每个身体部分来进行移动
      snakeLength.forEach((ele, index) => {
        let temporaryTop = ele.top;
        let temporaryLeft = ele.left;
        ele.top = previousTop;
        ele.left = previousLeft;
        previousTop = temporaryTop;
        previousLeft = temporaryLeft;
        document.querySelectorAll(".snake-body>div")[index].style.cssText =
          "left:" + ele.left + "px;top:" + ele.top + "px";
      });

      switch (direction) {
        case "ArrowUp":
          snakeSeat.top -= 20;
          break;
        case "ArrowLeft":
          snakeSeat.left -= 20;
          break;
        case "ArrowRight":
          snakeSeat.left += 20;
          break;
        case "ArrowDown":
          snakeSeat.top += 20;
          break;
      }

      if (snakeSeat.top == foodSeat.top && snakeSeat.left == foodSeat.left) {
        changeScore();
        changeFoodSeat();
        snakeLength.push({
          top: previousTop,
          left: previousLeft,
        });

        var div = document.createElement("div");
        div.style.left = previousLeft + "px";
        div.style.top = previousTop + "px";
        div.class = "bodyItem";

        document.querySelector(".snake-body").appendChild(div);
      }

      if (
        snakeSeat.top < 0 ||
        snakeSeat.left < 0 ||
        snakeSeat.left > 380 ||
        snakeSeat.top > 380
      ) {
        alert("撞墙身亡");
        snakeSeat.top = 0;
        snakeSeat.left = 0;
        direction = "";
        snakeLength = [];
        init();

        return;
      }

      let bodySeats = snakeLength.map((item) => JSON.stringify(item));

      if (
        bodySeats.indexOf(
          JSON.stringify({ top: snakeSeat.top, left: snakeSeat.left })
        ) != -1
      ) {
        alert("把自己撞死了");
        snakeSeat.top = 0;
        snakeSeat.left = 0;
        snakeLength = [];
        direction = "";
        init();
        return;
      }
      document.querySelector(".snake-head").style.cssText =
        "left:" + snakeSeat.left + "px;top:" + snakeSeat.top + "px";
      setTimeout(() => {
        handleWatchEnter();
      }, 400 - (register.grade - 1) * 15);
    };

    //函数节流
    const throttle = (fn, wait) => {
      var timer = null;
      return function () {
        var _this = this;
        var args = arguments;
        if (!timer) {
          timer = setTimeout(function () {
            fn.apply(_this, args);
            timer = null;
          }, wait);
        }
      };
    };

    const init = () => {
      document.querySelector(".snake-head").style.cssText =
        "left:" + 0 + "px;top:" + 0 + "px";
      document.querySelector(".snake-body").innerHTML = "";
      document.querySelector(".grade").innerText = register.grade;
      document.querySelector(".score").innerText = register.score;
      changeFoodSeat();
      handleWatchEnter();
    };

    document.addEventListener("keydown", (e) => {
      if (
        (e.code == "ArrowUp" && direction != "ArrowDown") ||
        (e.code == "ArrowLeft" && direction != "ArrowRight") ||
        (e.code == "ArrowRight" && direction != "ArrowLeft") ||
        (e.code == "ArrowDown" && direction != "ArrowUp")
      ) {
        direction = e.code;
      }
    });
    init();
  </script>
</html>

结论

通过本教程,我们学习了如何使用HTML、CSS和JavaScript创建一个简单的贪吃蛇游戏。这个过程不仅涉及到前端开发的基础知识,还包括了游戏逻辑的设计。现在,你可以根据自己的需求扩展和优化这个游戏,或者尝试创建其他类型的网页游戏。祝你编程愉快!

感谢你的访问,期待与你在技术的道路上相遇!👋🌟🚀

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

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

相关文章

IPSEC VPPN实验

实验背景&#xff1a;FW1和FW2是双机热备的状态。 实验要求&#xff1a;在FW和FW3之间建立一条IPSEC通道&#xff0c;保证10.0.2.0/24网段可以正常访问到192.168.1.0/24 IPSEC VPPN实验配置&#xff08;由于是双机热备状态&#xff0c;所以FW1和FW2只需要配置FW1主设备即可&…

portainer管理远程docker和docker-swarm集群

使用前请先安装docker和docker-compose&#xff0c;同时完成docker-swarm集群初始化 一、portainer-ce部署 部署portainer-ce实时管理本机docker&#xff0c;使用docker-compose一键拉起 docker-compose.yml version: 3 services:portainer:container_name: portainer#imag…

Java高频面试之消息队列与分布式篇

有需要互关的小伙伴,关注一下,有关必回关,争取今年认证早日拿到博客专家 消息队列的基本作用&#xff1f; 异步通信&#xff1a;消息队列提供了异步通信的能力&#xff0c;发送方可以将消息发送到队列中&#xff0c;而无需等待接收方立即处理。发送方和接收方可以解耦&#x…

【数据结构】单链表的层层实现!! !

关注小庄 顿顿解馋(●’◡’●) 上篇回顾 我们上篇学习了本质为数组的数据结构—顺序表&#xff0c;顺序表支持下标随机访问而且高速缓存命中率高&#xff0c;然而可能造成空间的浪费&#xff0c;同时增加数据时多次移动会造成效率低下&#xff0c;那有什么解决之法呢&#xff…

Matlab|2机5节点牛拉法(含报告)

目录 主要内容 下载链接 主要内容 采用牛拉法计算2机5节点的潮流计算程序&#xff0c;程序迭代稳定&#xff0c;运行可靠&#xff0c;含报告资料。 下载链接

pytorch的梯度图与autograd.grad和二阶求导

前向与反向 这里我们从 一次计算 开始比如 zf(x,y) 讨论若我们把任意对于tensor的计算都看为函数&#xff08;如将 a*b&#xff08;数值&#xff09; 看为 mul(a,b)&#xff09;&#xff0c;那么都可以将其看为2个过程&#xff1a;forward-前向&#xff0c;backward-反向在pyto…

【Web】浅聊Java反序列化之C3P0——JNDI注入利用

目录 简介 原理分析 EXP 前文&#xff1a;【Web】浅聊Java反序列化之C3P0——URLClassLoader利用 【Web】浅聊Java反序列化之C3P0——不出网Hex字节码加载利用 简介 出网的情况下&#xff0c;这个C3P0的Gadget可以和fastjson&#xff0c;Snake YAML , JYAML,Yamlbeans , …

【Javascript编程实操05】1、小明买洗发水、香皂、牙刷组合 2、利用循环写出100以内的奇数的和及偶数的和

前言 1、小明买洗发水、香皂、牙刷组合 代码&#xff1a; 实现效果&#xff1a; 2、利用循环写出100以内的奇数的和及偶数的和 代码&#xff1a; 实现效果&#xff1a; 总结 前言 本次主要是继续针对Javascript阶段的for循环的实操练习&#xff0c;共有2个实操&#xff…

vscode setting.json 全局设置 工作区设置 位置 优先级

vscode中setting.json有两种配置权限 一、全局配置&#xff1a;setting.json文件位于C:\Users\Administrator\AppData\Roaming\Code\User\settings.json 二、工作区配置&#xff1a;setting.json文件位于工作区的.vscode\settings.json 当两种配置同时存在时&#xff0c;工作区…

单链表详解(如何实现单链表)

文章目录 前言 一、单链表是什么&#xff1f;二、单链表的实现总结 顺序表的缺点 1.中间/头部的插入删除&#xff0c;时间复杂度为O (N) 2.realloc 扩容&#xff08;特别是异地扩&#xff0c;需要申请新空间&#xff0c;拷贝数据&#xff0c;释放旧空间&#xff09;会有不小的…

【开源】JAVA+Vue.js实现高校宿舍调配管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能需求2.1 学生端2.2 宿管2.3 老师端 三、系统展示四、核心代码4.1 查询单条个人习惯4.2 查询我的室友4.3 查询宿舍4.4 查询指定性别全部宿舍4.5 初次分配宿舍 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的…

Day24:安全开发-PHP应用文件管理模块显示上传黑白名单类型过滤访问控制

目录 文件管理模块-上传-过滤机制 文件管理模块-显示-过滤机制 思维导图 PHP知识点 功能&#xff1a;新闻列表&#xff0c;会员中心&#xff0c;资源下载&#xff0c;留言版&#xff0c;后台模块&#xff0c;模版引用&#xff0c;框架开发等 技术&#xff1a;输入输出&#…

泛微OA服务器获取 token

泛微OA服务器获取 token 文章目录 泛微OA服务器获取 token一、泛微官方方法1 ecology 系统配置2 发放/生成许可证(appid)3 限制许可证使用ip地址&#xff08;该步骤也可以跳过&#xff09;4 使用 postman 注册5 获取 token6 访问业务系统接口 二、java 代码获取 token三、封装到…

【Redis项目实战】使用Springcloud整合Redis分布式锁+RabbitMQ技术实现高并发预约管理处理系统

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《Redis实战与进阶》 本专栏带你Redis从入门到入魔 这是苏泽的个…

一次生产环境上的dockerd启动失败原因分析

今夜原计划对 生产环境 上的 SDN 组件进行一次紧急扩容操作的&#xff0c;但业务基础环境中的 Docker-Engine 启动不起来了、原定计划也就无法继续进行了。 尽管查清了基础业务环境中的故障原因&#xff0c;但金主DD说今天先不干了&#xff0c;那就整理整理思路写篇流水账吧 。…

Linux环境下使用线程方式操作UART读写功能

目录 概述 1 Linux环境下UART设备 2 轮询方式操作UART功能实现 2.1 打开串口函数&#xff1a;usr_serial_open 2.2 关闭串口函数&#xff1a; usr_serial_close 2.3 发送数据函数&#xff1a; usr_serial_sendbytes 2.4 接收数据函数&#xff1a; thread_uart_readbytes …

波卡 Alpha 计划启动,呼唤先锋创新者重新定义 Web3 开发

原文&#xff1a;https://polkadot.network/blog/the-polkadot-alpha-program-a-new-era-for-decentralized-building-collaboration/ 编译&#xff1a;OneBlock 区块链领域不断发展&#xff0c;随之而来的是发展和创新机会的增加。而最新里程碑是令人振奋的 Polkadot Alpha …

生态,带给用友新机会? | ToB产业观察

ITValue 近年来&#xff0c;不少厂商都将生态调整到战略级别&#xff0c;但做生态往往需要实打实、接地气的生态策略。 作者&#xff5c;杨丽 首发&#xff5c;钛媒体APP ITValue 3月初&#xff0c;用友召开了新一年的首场生态发布会&#xff0c;为接下来一年动作定调&#xff…

17、电源管理入门之Power supply子系统

目录 1. Power supply框架都做些什么 2. 相关数据结构和接口 2.1 数据结构 2.2 接口 3. 充电驱动 3.1 Charger Manager 3.2 Fuel Gauge 3.3 Charger IC 4. 怎样基于power supply class编写PSY driver 参考资料: 对于便携设备来说,电源管理更加的重要,因为电池电量…

数据库系统概念(第一周)

⚽前言 &#x1f3d0;四个基本概念 一、数据 定义 种类 特点 二、数据库 三、数据库管理系统&#xff08;DBMS&#xff09; 四、 数据库系统&#xff08;DBS&#xff09; &#x1f3c0;数据库系统和文件系统对比 文件系统的弊端 &#x1f94e;数据视图 数据抽象 …