使用js和canvas实现简单的网页贪吃蛇小游戏

玩法介绍

点击开始游戏后,使用键盘上的↑↓←→控制移动,吃到食物增加长度,碰到墙壁或碰到自身就游戏结束

代码实现

代码比较简单,直接阅读注释即可,复制即用

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Snake Game</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }
        canvas {
            display: block;
            position: absolute;
            top: 0;
            left: 0;
            z-index: 1;
            background-color: #000;
        }
        .start-screen {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.8);
            color: white;
            text-align: center;
            z-index: 2;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 24px;
        }
        button {
            font-size: 24px;
            padding: 10px 20px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div class="start-screen">
        <h1>Snake Game</h1>
        <button id="startButton">Start Game</button>
    </div>
    <canvas id="gameCanvas" width="800" height="600"></canvas>
    <script>
        const canvas = document.getElementById('gameCanvas');
        const ctx = canvas.getContext('2d');

        // 设置 Canvas 为全屏
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;

        // 方块大小
        const blockSize = 20;

        // 游戏状态
        let snake = [{ x: 100, y: 100 }];
        let food = { x: 200, y: 200 };
        let direction = 'right';
        let score = 0;
        let isRunning = false;

        // 游戏速度
        const speed = 100;

        // 绘制蛇
        function drawSnake() {
            ctx.fillStyle = '#0f0';
            snake.forEach(segment => {
                ctx.fillRect(segment.x, segment.y, blockSize, blockSize);
            });
        }

        // 绘制食物
        function drawFood() {
            ctx.fillStyle = '#f00';
            ctx.fillRect(food.x, food.y, blockSize, blockSize);
        }

        // 检查碰撞
        function checkCollision() {
            // 检查蛇是否撞墙
            if (snake[0].x < 0 || snake[0].x >= canvas.width || snake[0].y < 0 || snake[0].y >= canvas.height) {
                alert('Game Over!');
                isRunning = false;
                return;
            }

            // 检查蛇是否撞到自己
            for (let i = 1; i < snake.length; i++) {
                if (snake[0].x === snake[i].x && snake[0].y === snake[i].y) {
                    alert('Game Over!');
                    isRunning = false;
                    return;
                }
            }

            // 检查蛇是否吃到食物
            if (snake[0].x === food.x && snake[0].y === food.y) {
                score++;
                placeFood();
            } else {
                snake.pop();
            }
        }

        // 放置新的食物
        function placeFood() {
            food = {
                x: Math.floor(Math.random() * (canvas.width / blockSize)) * blockSize,
                y: Math.floor(Math.random() * (canvas.height / blockSize)) * blockSize
            };
        }

        // 更新游戏状态
        function update() {
            if (!isRunning) return;

            let newX = snake[0].x;
            let newY = snake[0].y;

            if (direction === 'left') newX -= blockSize;
            if (direction === 'right') newX += blockSize;
            if (direction === 'up') newY -= blockSize;
            if (direction === 'down') newY += blockSize;

            snake.unshift({ x: newX, y: newY });

            checkCollision();
        }

        // 渲染游戏画面
        function draw() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            drawSnake();
            drawFood();
        }

        // 游戏主循环
        function gameLoop() {
            update();
            draw();
            setTimeout(gameLoop, speed);
        }

        // 键盘事件
        function handleKeyPress(event) {
            if (event.key === 'ArrowLeft' && direction !== 'right') direction = 'left';
            if (event.key === 'ArrowRight' && direction !== 'left') direction = 'right';
            if (event.key === 'ArrowUp' && direction !== 'down') direction = 'up';
            if (event.key === 'ArrowDown' && direction !== 'up') direction = 'down';
        }

        // 开始按钮事件
        document.getElementById('startButton').addEventListener('click', () => {
            const startScreen = document.querySelector('.start-screen');
            startScreen.style.display = 'none';

            // 添加键盘事件监听
            document.addEventListener('keydown', handleKeyPress);

            isRunning = true;
            placeFood();
            gameLoop();
        });

        // 游戏结束时移除键盘事件监听
        window.addEventListener('beforeunload', () => {
            document.removeEventListener('keydown', handleKeyPress);
        });
    </script>
</body>
</html>
相关推荐
t***D264几秒前
前端构建工具缓存策略,contenthash与chunkhash
前端·缓存
倚肆5 分钟前
HTMLElement 与MouseEvent 事件对象属性详解
前端·javascript
青衫码上行24 分钟前
【Java Web学习 | 第12篇】JavaScript(6)DOM
java·开发语言·前端·javascript·学习
毕设十刻1 小时前
基于Vue的鲜花销售系统33n62(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
前端·数据库·vue.js
IT_陈寒1 小时前
Spring Boot 3.2震撼发布:5个必知的新特性让你开发效率提升50%
前端·人工智能·后端
San30.1 小时前
JavaScript 深度解析:从 map 陷阱到字符串奥秘
开发语言·javascript·ecmascript
初遇你时动了情1 小时前
前端使用TensorFlow.js reactjs调用本地模型 实现图像、文本、音频/声音、视频相关识别
前端·javascript·tensorflow
广州华水科技1 小时前
单北斗GNSS变形监测系统安装与应用解析,提升位移监测精度
前端
J***Q2921 小时前
前端微前端框架原理,qiankun源码分析
前端·前端框架
十一.3661 小时前
66-69 原型对象,toString(),垃圾回收
开发语言·javascript·原型模式