JS实现的贪吃蛇游戏案例详解

JS实现的贪吃蛇游戏案例详解

游戏规则

贪吃蛇游戏是一种非常经典的游戏,规则如下:

  1. 贪吃蛇每次只能往上、下、左、右四个方向的其中一个方向走;
  2. 贪吃蛇的身体每增加一节长度,分数就会增加一分;
  3. 贪吃蛇在吃到“食物”时身体长度加一,可以得到分数;
  4. 贪吃蛇撞到边界或者自己的身体就会死亡,游戏结束;
  5. 游戏过程中,可以随时暂停或重新开始。

实现过程

创建游戏区域

首先,我们需要在HTML中创建一个canvas元素,用于绘制游戏界面:

<canvas id="game" width="400" height="400"></canvas>

然后,在JS中获取这个canvas元素:

const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');

绘制贪吃蛇

我们可以通过一个数组来表示贪吃蛇:

let snake = [
    {x: 3, y: 0},
    {x: 2, y: 0},
    {x: 1, y: 0},
    {x: 0, y: 0},
];

数组中的每个元素都表示贪吃蛇的一个“身体”位置,x表示横坐标,y表示纵坐标。数组的第一个元素表示贪吃蛇的脑袋,最后一个元素表示贪吃蛇的尾巴。

我们需要绘制出这个贪吃蛇。可以使用canvas来绘制:

const SNAKE_SIZE = 10;
const SNAKE_COLOR = '#333';

function drawSnake() {
    ctx.fillStyle = SNAKE_COLOR;
    for (let i = 0, len = snake.length; i < len; i++) {
        ctx.fillRect(snake[i].x * SNAKE_SIZE, snake[i].y * SNAKE_SIZE, SNAKE_SIZE, SNAKE_SIZE);
    }
}

移动贪吃蛇

接下来,我们需要让贪吃蛇能够移动起来。贪吃蛇的移动是根据当前贪吃蛇头的位置和方向来计算的。我们需要记录贪吃蛇方向,以便下一次移动的时候根据方向进行计算。

let direction = 'right';

document.addEventListener('keydown', function(event) {
    if (event.keyCode === 37 && direction !== 'right') {
        direction = 'left';
    } else if (event.keyCode === 38 && direction !== 'down') {
        direction = 'up';
    } else if (event.keyCode === 39 && direction !== 'left') {
        direction = 'right';
    } else if (event.keyCode === 40 && direction !== 'up') {
        direction = 'down';
    }
});

在键盘按下事件的回调函数中,我们根据按键的keyCode来判断用户输入的方向,并修改方向变量。

然后,我们需要在每个游戏循环中根据方向来计算蛇头的位置,并将位置添加到数组的头部。同时,我们需要将数组的尾部去掉,这样就实现了贪吃蛇的移动。

let intervalId;

function startGame() {
    intervalId = setInterval(() => {
        let {x, y} = snake[0];
        switch (direction) {
            case 'up':
                y--;
                break;
            case 'right':
                x++;
                break;
            case 'down':
                y++;
                break;
            case 'left':
                x--;
                break;
        }
        snake.unshift({x, y});
        snake.pop();
    }, 100);
}

注意,由于 setInterval 函数返回一个唯一的 ID,我们需要保存这个 ID,以便在需要停止游戏时能够清除时间循环:

function stopGame() {
    clearInterval(intervalId);
}

添加食物

贪吃蛇游戏中,蛇可以吃食物,这时蛇的身体长度会增加。我们需要在游戏区域内添加食物,并在贪吃蛇吃到食物时增加贪吃蛇的身体长度。

let food = {
    x: Math.floor(Math.random() * (canvas.width / SNAKE_SIZE)),
    y: Math.floor(Math.random() * (canvas.height / SNAKE_SIZE)),
};
const FOOD_COLOR = '#f00';

function drawFood() {
    ctx.fillStyle = FOOD_COLOR;
    ctx.fillRect(food.x * SNAKE_SIZE, food.y * SNAKE_SIZE, SNAKE_SIZE, SNAKE_SIZE);
}

我们可以在游戏开始时生成一个随机位置的食物,并在绘制游戏区域时绘制食物。当贪吃蛇的蛇头和食物位置相同时,就表示贪吃蛇已经吃到了食物,这时我们就需要在贪吃蛇的头部添加一个位置,表示身体长度增加了。

function eatFood() {
    const {x: headX, y: headY} = snake[0];
    if (headX === food.x && headY === food.y) {
        console.log('Eat food!');
        food = {
            x: Math.floor(Math.random() * (canvas.width / SNAKE_SIZE)),
            y: Math.floor(Math.random() * (canvas.height / SNAKE_SIZE)),
        };
        snake.unshift({x: headX, y: headY});
    }
}

游戏结束

当贪吃蛇撞到边界或者自己的身体,游戏就结束了。我们需要在游戏循环中判断游戏是否结束,并在结束时停止游戏循环。

function isGameOver() {
    const {x: headX, y: headY} = snake[0];
    for (let i = 1, len = snake.length; i < len; i++) {
        if (snake[i].x === headX && snake[i].y === headY) {
            return true;
        }
    }
    if (headX < 0 || headX >= canvas.width / SNAKE_SIZE || headY < 0 || headY >= canvas.height / SNAKE_SIZE) {
        return true;
    }
    return false;
}

function checkGameOver() {
    if (isGameOver()) {
        console.log('Game over!');
        stopGame();
    }
}

示例说明

示例1

以下是一个简单的示例代码:https://codepen.io/happycoder01/pen/rNwdYjV

该示例实现了一个基本的贪吃蛇游戏,但没有进行模块化和优化,代码难以理解和维护。

示例2

以下是一个较为完整的示例代码:https://codepen.io/happycoder01/pen/QWvqyMa

该示例对代码进行了模块化和优化,将游戏逻辑和绘制逻辑分开,减少了代码的耦合性,同时使用了ES6的语法和面向对象编程的思想,代码更加简洁和易于维护。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JS实现的贪吃蛇游戏案例详解 - Python技术站

(0)
上一篇 2023年6月8日
下一篇 2023年6月8日

相关文章

  • NodeJS学习笔记之Module的简介

    下面是我对于“NodeJS学习笔记之Module的简介”的攻略说明: 什么是Module 在NodeJS中,Module(模块)是一个独立的文件作用域,可以包含代码、函数、变量等内容。Module 具备了封装性、重用性和依赖性,让我们能够更好地组织有意义的代码。 模块的导入和导出 要使用一个模块内容,我们需要先了解如何导入它。在 NodeJS 中,采用 re…

    node js 2023年6月8日
    00
  • webstorm建立vue-cli脚手架的傻瓜式教程

    下面是详细讲解“WebStorm建立Vue CLI脚手架的傻瓜式教程”的完整攻略。 步骤1:安装Node.js和Vue CLI 首先,需要在本地安装Node.js和Vue CLI。Node.js是JavaScript的运行环境,而Vue CLI是用于生成Vue.js项目的命令行工具。 安装Node.js:从官网https://nodejs.org/en/do…

    node js 2023年6月9日
    00
  • 解决vue cli4升级sass-loader(v8)后报错问题

    针对“解决vue cli4升级sass-loader(v8)后报错问题”,我会提供以下完整攻略: 问题背景 在升级 sass-loader 到 v8 版本之后,如果项目依赖了 node-sass,就会在启动 npm run serve 命令时遇到下面的错误: Module build failed (from ./node_modules/sass-load…

    node js 2023年6月8日
    00
  • 使用npm安装最新版本nodejs

    安装最新版本的Node.js,一种可行的方式是使用npm,下面是完整攻略: 步骤 1:安装n模块 n模块是一个Node.js版本管理器,它可以让你轻松地在系统中安装和使用多个版本的Node.js,包括最新版本。首先,我们需要使用以下命令安装n模块: sudo npm install -g n 步骤 2:使用n模块安装最新版本的Node.js n模块安装之后,…

    node js 2023年6月7日
    00
  • nodejs 的 session 简单使用

    当使用 Node.js 的 Express 框架进行 Web 开发时,我们通常需要使用 session 来存储用户登录状态等信息。这里是一个 Node.js session 的简单使用攻略。 安装相关依赖 Session 是通过中间件实现的,我们需要安装 session 相关依赖: npm install express-session 引入 session…

    node js 2023年6月8日
    00
  • 跟我学Nodejs(三)— Node.js模块

    下面我来讲解一下“跟我学Nodejs(三)— Node.js模块”的完整攻略。 什么是Node.js模块? Node.js是一个支持模块化的平台,它提供一种可以在不同脚本之间共享代码的机制。Node.js在启动时自动加载并编译保存在指定位置的模块。 模块可以是单个文件、文件夹(包含index.js文件)或者是一个core module。Node.js有很…

    node js 2023年6月8日
    00
  • node.js中的fs.open方法使用说明

    Node.js中的fs.open方法使用说明 简介 fs.open() 方法用于异步地打开文件。 与 fs.openSync() 方法类似,但 fs.open() 方法不会立即将文件打开。 而是返回文件描述符。 这个方法可以被用来打开新的文件,也可以被用来修改一个已打开的文件。 语法 fs.open(path[, flags[, mode]], callba…

    node js 2023年6月8日
    00
  • Node.js通过身份证号验证年龄、出生日期与性别方法示例

    下面是关于“Node.js通过身份证号验证年龄、出生日期与性别方法示例”的完整攻略: 1. 需求分析 首先我们需要明确我们的需求,就是通过身份证号获取到对应的年龄、出生日期和性别这几个信息。身份证号通常有15位和18位两种格式,我们需要对这两种格式都进行处理。具体的需求分析可以如下: 输入参数:身份证号(String类型) 输出结果:年龄、出生日期和性别(O…

    node js 2023年6月8日
    00
合作推广
合作推广
分享本页
返回顶部