web端使用HTML5开发《贪吃蛇》小游戏教程【附源码】

news2024/12/22 18:35:35

 自制游戏列表 

1植物大战僵尸自制HTML5游戏《植物大战僵尸》
2开心消消乐自制HTML5游戏《开心消消乐》
3贪吃蛇自制HTML5游戏《贪吃蛇》
4捕鱼达人自制HTML5游戏《捕鱼达人》
   

一、游戏简介

        贪吃蛇是一款经典的电子游戏,最早在1976年由Gremlin公司推出,名为"Blockade"。游戏的玩法简单却富有挑战性,玩家控制一条蛇在封闭的场地内移动,通过吃食物增长身体,同时避免撞到自己的身体或场地边界。随着时间的推移,贪吃蛇游戏经历了多次演变,但其核心玩法依然受到玩家的喜爱。

二、为什么选择贪吃蛇游戏

  1. 经典性:贪吃蛇是一款历史悠久的游戏,其经典性使得它成为学习编程和游戏开发的理想选择。

  2. 简单性:游戏规则简单,易于理解,适合初学者作为编程练习项目。

  3. 互动性:贪吃蛇游戏具有高度的互动性,玩家需要快速反应和策略思考。

  4. 可扩展性:基础游戏可以扩展多种功能,如增加难度级别、特殊道具等,为学习者提供更多实践机会。

 

三、游戏目标

        贪吃蛇游戏的主要目标是控制蛇头吃到随机出现在游戏场地的苹果,每吃到一个苹果,蛇的身体就会增长一段。玩家需要避免蛇头撞到自己的身体或游戏场地的边界。游戏的难度会随着蛇身的增长而增加,玩家的目标是尽可能获得更高的分数。

四、游戏界面设计

游戏界面通常由以下几个部分组成:

  1. 游戏画布:一个矩形区域,作为蛇移动和吃苹果的场所。

  2. :由多个小方块组成,每个方块代表蛇的身体部分,蛇头通常有特殊的标识。

  3. 苹果:一个单独的方块,随机出现在游戏画布上,作为蛇的食物。

  4. 得分板:显示玩家当前的得分和游戏等级。

 

五、游戏逻辑概述

游戏逻辑主要包括以下几个方面:

  1. 初始化:设置游戏初始状态,包括蛇的位置、长度和方向,苹果的位置,以及得分和等级。

  2. 键盘控制:监听键盘按键,根据玩家的输入改变蛇的移动方向。

  3. 移动逻辑:更新蛇的位置,使其按照指定方向移动。

  4. 碰撞检测:检查蛇头是否撞到自己、边界或苹果。

  5. 吃苹果:如果蛇头碰到苹果,更新苹果的位置,增长蛇的身体,并增加得分。

  6. 游戏结束:如果蛇撞到自己或边界,显示游戏结束的提示,并结束游戏循环。

  7. 得分和等级:根据吃到的苹果数量增加得分,并根据得分调整游戏难度。

 

六、创建基本的HTML5文档结构

        在创建贪吃蛇游戏之前,首先需要构建一个基本的HTML5文档结构。这个结构包括了文档的头部(head)和主体(body),其中头部用于引入CSS样式和JavaScript脚本,而主体则包含了游戏的所有元素。

源代码示例 - HTML5文档结构

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>贪吃蛇游戏</title>
    <link rel="stylesheet" href="styles/base.css">
    <link rel="stylesheet" href="styles/snake.css">
</head>
<body>
    <!-- 游戏画布和元素将在此处添加 -->
    <script src="scripts/snake.js"></script>
</body>
</html>

设定游戏画布 (<div id="box">)

游戏画布是一个<div>元素,它作为游戏的容器,包含了蛇、苹果和得分板。这个<div>具有固定的宽度和高度,并且使用CSS样式来设置其位置和外观。

源代码示例 - HTML中的游戏画布

<div id="box">
    <!-- 蛇的身体由列表项组成,苹果是一个div,得分板将在JavaScript中动态添加 -->
    <ul id="snake"></ul>
    <div id="apple"></div>
</div>
<div id="score">得分: <span id="score-value">0</span> 等级: <span id="level-value">1</span></div>

添加游戏元素(蛇头、蛇身、苹果、得分板)

  1. 蛇头:通常用一个带有图片的<li>元素表示,这个<li><ul id="snake">的第一个子元素。

  2. 蛇身:由多个<li>元素组成,这些元素将通过JavaScript动态添加到蛇的列表中。

  3. 苹果:用一个<div id="apple">表示,它的位置将通过JavaScript动态设置。

  4. 得分板:一个包含得分和等级的<div>元素,位于游戏画布之外。

源代码示例 - JavaScript中添加蛇头和蛇身

window.onload = function() {
    var snakeList = document.getElementById('snake');
    var snakeHead = document.createElement('li');
    snakeHead.innerHTML = '<img src="head.png" alt="蛇头">'; // 假设有一个蛇头图片
    snakeList.appendChild(snakeHead);
​
    // 初始蛇身长度,例如5个单位
    for (var i = 0; i < 5; i++) {
        var snakeBodyPart = document.createElement('li');
        snakeList.appendChild(snakeBodyPart);
    }
​
    var apple = document.getElementById('apple');
    // 设置苹果的初始位置
    apple.style.left = '100px';
    apple.style.top = '100px';
};

七、效果图

        91a18701a04d49d1964c4118d70d7401.gif

八、完整代码

        HTML

<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" href="base.css" />
    <link rel="stylesheet" href="snake.css" />
    <script src="snake.js"></script>
</head>

<body>
    <div id="score">
        得分: <span>0</span>
        等级: <span>1</span>
    </div>
    <div id="box">
        <ul id="snake">
            <li class="heihei" id="head"><img src="right.png" alt="" /></li>
            <li class="heihei"></li>
            <li class="heihei"></li>
            <li class="heihei"></li>
            <li class="heihei"></li>
            <li class="heihei"></li>
            <li class="heihei"></li>
            <li class="heihei"></li>
        </ul>
        <div id="apple"></div>
    </div>
    <script>
    </script>
</body>

</html>

        snake.css

#box{
    width: 800px;
    height: 600px;
    position: relative;
    background-color: #d5e3bd;
    border: 1px solid #000;
    margin: 30px auto;
}
#snake{
    /*position: absolute;*/
    /*top: 200px;*/
    /*left: 350px;*/
}
.heihei{
    width: 20px;
    height: 20px;
    /*border: 1px solid #000;*/
    border-radius: 10px;
    background-color: rgb(13, 113, 85);
    position: absolute;
    text-align: center;
    line-height: 20px;
    position: absolute;
    top: 200px;
    left: 350px;
    color: white;
}
#head img{
    width: 20px;
}
#apple{
    width: 20px;
    height: 20px;
    background-color: darkred;
    position: absolute;
    top: 140px;
    left: 400px;
}
#score{
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    position: absolute;
    text-align: center;
    line-height: 100px;
    left: 1100px;
    z-index: 1;
}

        base.css

@charset "UTF-8";
/*css 初始化 */
html, body, ul, li, ol, dl, dd, dt, p, h1, h2, h3, h4, h5, h6, form, fieldset, legend, img {
    margin: 0;
    padding: 0;
}

/*各浏览器显示不同,去掉蓝色边框*/
fieldset, img, input, button {
    border: none;
    padding: 0;
    margin: 0;
    outline-style: none;
}

ul, ol {
    list-style: none;
}

/*统一组合框的默认样式*/
input {
    padding-top: 0;
    padding-bottom: 0;
    font-family: "sums-song", "宋体";
}

select, input, button {
    vertical-align: middle;
}

select, input, textarea {
    font-size: 12px;
    margin: 0;
}

/*防止拖动 影响布局*/
textarea {
    resize: none;
}

/*去掉行内替换元素空白缝隙*/
img {
    border: 0;
    vertical-align: middle;
}

table {
    border-collapse: collapse;
}

body {
    font: 12px/150% Arial, Verdana, "\5b8b\4f53"; /*宋体 unicode */
    color: #666;
    background: #fff;
}

/*清除浮动*/
.clearfix:before, .clearfix:after {
    content: "";
    display: table;
}

.clearfix:after {
    clear: both;
}

.clearfix {
    *zoom: 1; /*IE/7/6*/
}

a {
    color: #666;
    text-decoration: none;
}

a:hover {
    color: #C81623;
}

h1, h2, h3, h4, h5, h6 {
    text-decoration: none;
    font-weight: normal;
    font-size: 100%;
}

s, i, em {
    font-style: normal;
    text-decoration: none;
}

/*京东色*/
.col-red {
    color: #C81623 !important;
}

/*公共类*/
.w {
    /*版心 提取 */
    width: 1210px;
    margin: 0 auto;
}

.fl {
    float: left;
}

.fr {
    float: right;
}

.al {
    text-align: left;
}

.ac {
    text-align: center;
}

.ar {
    text-align: right;
}

.hide {
    display: none;
}

        js代码

window.onload = function() {
    var ul = document.getElementById("snake");
    var lis = ul.children;
    var head = lis[0];
    var img = head.getElementsByTagName("img")[0];
    var box = document.getElementById("box");
    var apple = document.getElementById("apple");
    var score = document.getElementById("score").getElementsByTagName("span")[0];
    var level = document.getElementById("score").getElementsByTagName("span")[1];
    var gameOver;
    var square = 20;
    var dirArr = {
        left: { name: "left", key: 65, point: { x: -1, y: 0 }, img: "left.png" },
        right: { name: "right", key: 68, point: { x: 1, y: 0 }, img: "right.png" },
        up: { name: "up", key: 87, point: { x: 0, y: -1 }, img: "up.png" },
        down: { name: "down", key: 83, point: { x: 0, y: 1 }, img: "down.png" }
    };
    var dirList = [];
    var currentDir = dirArr["right"];
    document.onkeydown = function(event) {
        var event = event || window.event;
        addDirection(event.keyCode);
    }

    function addDirection(key) {
        var dir;
        // 获取方向
        for (k in dirArr) {
            if (dirArr[k].key == key) {
                dir = dirArr[k];
            }
        }
        if (!dir) {
            return;
        }
        //获取上一次的方向
        var lastDirection = dirList[dirList.length - 1];
        if (!lastDirection) { lastDirection = currentDir }
        if (lastDirection.name == dir.name) {
            return;
        } else if (lastDirection.point.x + dir.point.x == 0 && lastDirection.point.y + dir.point.y == 0) {
            return;
        }
        if (dirList.length > 3) {
            return;
        }
        dirList.push(dir);
    }

    function getDirection(arr) {
        if (arr.length != 0) {
            currentDir = arr.shift();
        }
        return currentDir;
    }

    function point(x, y) {
        this.x = x;
        this.y = y;
    }

    function move() {
        //处理按键队列
        var d = getDirection(dirList);
        img.src = d.img;
        //下一个要走的点
        var pre = new point(head.offsetLeft + d.point.x * square, head.offsetTop + d.point.y * square);
        //死亡判定机制
        if (die(pre)) {
            clearInterval(timer)
            alert("GAME_OVER");
            return;
        }
        //吃的机制
        if (eat(pre)) {
            console.log("eat");
        }
        //移动身子
        for (var i = lis.length - 1; i > 0; i--) {
            lis[i].style.left = lis[i - 1].offsetLeft + "px";
            lis[i].style.top = lis[i - 1].offsetTop + "px";
        }
        head.style.left = pre.x + "px";
        head.style.top = pre.y + "px";
    }
    var timer = setInterval(move, 300);

    function die(p) {
        var left = p.x;
        var right = p.x + head.offsetWidth;
        var toper = p.y;
        var bottom = p.y + head.offsetHeight;
        for (var i = 1; i < lis.length - 1; i++) {
            if (left == lis[i].offsetLeft && toper == lis[i].offsetTop)
                return 1;
        }
        if (left < 0 || toper < 0 || right > box.offsetWidth || bottom > box.offsetHeight) {
            console.log(1)
            return 1;
        }
    }
    //初始化
    for (var i = 0; i < lis.length; i++) {
        lis[i].idx = i;
        lis[i].style.left = -square * i + "px";
        var backgroundColor = parseInt(255 * 255 * 255 * Math.random());
        lis[i].style.backgroundColor = "#" + backgroundColor.toString(16);
    }

    //吃
    function eat(p) {
        if (p.x == apple.offsetLeft && p.y == apple.offsetTop) {
            apple.style.left = 20 * Math.floor(Math.random() * 39) + "px";
            apple.style.top = 20 * Math.floor(Math.random() * 29) + "px";
            var li = document.createElement("li");
            li.className = "heihei";
            var backgroundColor = parseInt(255 * 255 * 255 * Math.random());
            li.style.backgroundColor = "#" + backgroundColor.toString(16);
            ul.appendChild(li);
            score.innerHTML++;
            clearInterval(timer);
            var scoreLevel = Math.floor(score.innerHTML / 4);
            level.innerHTML = scoreLevel + 1;
            var timeLevel = scoreLevel > 7 ? 7 : scoreLevel;
            timer = setInterval(move, 250 - timeLevel * 25);
        }
    }
}

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

牛筋面,一口难忘的劲道滋味

在众多的平凉美食中&#xff0c;牛筋面以其独特的口感和丰富的口味&#xff0c;赢得了无数食客的喜爱。牛筋面&#xff0c;这一名字就给人一种坚韧、有嚼劲的印象。它并非由牛筋制成&#xff0c;而是因其面条的口感如牛筋般劲道而得名。牛筋面的制作过程颇具巧思。选用优质的面…

Unity免费领高级可视化编程自定义节点工具AI行为UI流程对话树状态机逻辑等FlowReactor价值50刀high level20240627

刚发现一款类似虚幻蓝图的可视化编程工具&#xff0c;原价50刀&#xff0c;现在免费领取了。赶紧去领取入库&#xff0c;防止作者涨价。 高级可视化编程自定义节点工具&#xff1a;https://prf.hn/l/BJbdvnD 作者其他资产&#xff1a;https://prf.hn/l/YLAYznV Unity免费领高级…

电脑提示msvcr120.dll丢失怎样修复

文件功能与重要性&#xff1a;msvcr120.dll 文件的功能和重要性体现在多个方面&#xff0c;以下是对其核心功能的详细分析&#xff1a; 运行时支持 msvcr120.dll 提供了运行时环境&#xff0c;使得使用 Microsoft Visual C 2013 编译的程序能够调用必要的运行时函数。这些函数…

MySQL高级-索引-使用规则-覆盖索引回表查询

文章目录 1、覆盖索引1.1、查看索引1.2、删除单列索引 idx_user_pro1.3、查询 profession软件工程 and age31 and status01.4、执行计划 profession软件工程 and age31 and status01.5、执行计划 select id,profession,age,status1.6、执行计划 select id,profession,age,statu…

step7:“模拟量界面”逻辑

文章目录 文章介绍效果图AnalogPage.qml结构图调用 SerialPortHandler.sendData(message); serialporthandler.cpp 文章介绍 之前的6步实现了案例MF的界面设计和串口界面的逻辑设计&#xff0c;本文将实现模拟量界面的逻辑设计 新增功能&#xff1a; 1&#xff09;弹出提示框 …

Mac14.1.2 M1芯片免费读写ntfs硬盘-亲测有效,免费!!!

1. 安装homebrew 打开终端&#xff0c;使用以下命令 /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 根据提示逐步完成即可&#xff0c;镜像选择我这里都是保持1的选项。 2. 重启终端 安装完成homebrew后&#xff0c;需…

Java线程池及面试题

1.线程池介绍 顾名思义&#xff0c;线程池就是管理一系列线程的资源池&#xff0c;其提供了一种限制和管理线程资源的方式。每个线程池还维护一些基本统计信息&#xff0c;例如已完成任务的数量。 总结一下使用线程池的好处&#xff1a; 降低资源消耗。通过重复利用已创建的…

第 1 章SwiftUI 简介

在 2019 年的 WWDC 上,Apple 宣布推出一款名为 SwiftUI 的全新框架,令开发者们大吃一惊。该框架不仅改变了开发 iOS 应用的方式,还代表了自 Swift 首次亮相以来 Apple 开发者生态系统最重大的转变。SwiftUI 适用于所有 Apple 平台,包括 iPadOS、macOS、tvOS 和 watchOS,这…

ZSWatch 开源项目介绍

前言 因为时不时逛 GitHub 会发现一些比较不错的开源项目&#xff0c;突发奇想想做一个专题&#xff0c;专门记录开源项目&#xff0c;内容不限于组件、框架以及 DIY 作品&#xff0c;希望能坚持下去&#xff0c;与此同时&#xff0c;也会选取其中的开源项目做专题分析。希望这…

【GD32】08 - IIC(以SHT20为例)

GD32中的IIC 今天来了解一下GD32中的硬件IIC&#xff0c;其实我个人是觉得软件IIC比较方便的&#xff0c;不过之前文章里用的都是软件IIC&#xff0c;今天就算是走出自己的舒适圈&#xff0c;我们来了解了解GD32中的硬件IIC。 我这里用的型号是GD32F407&#xff0c;不同型号的…

多路h265监控录放开发-(14)通过PaintCell自定义日历控件继承QCalendarWidget的XCalendar类

首先创建一个新类XCalendar继承QCalendarWidget类&#xff0c;然后在UI视图设计器中把日历提升为XCalendar&#xff0c;通过这个函数自己设置日历的样式 xcalendar.h #pragma once #include <QCalendarWidget> class XCalendar :public QCalendarWidget { public:XCal…

Java基础(四)——字符串、StringBuffer、StringBuilder、StringJoiner

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 ⚡开源项目&#xff1a; rich-vue3 &#xff08;基于 Vue3 TS Pinia Element Plus Spring全家桶 MySQL&#xff09; &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1…

C++编程(四)this指针 常函数 常对象 静态成员

文章目录 一、this指针&#xff08;一&#xff09;概念&#xff08;二&#xff09;显式使用this指针的场景1. 当形参和成员变量名一致时2. 返回对象自身的时候必须要使用this指针3. 在类中销毁一个对象 二、常函数和常对象&#xff08;一&#xff09;常函数1. 概念2. 语法格式 …

Linux Static calls机制

文章目录 前言一、简介二、Background: indirect calls, Spectre, and retpolines2.1 Indirect calls2.2 Spectre (v2)2.3 RetpolinesConsequences 2.4 Static callsHow it works 三、其他参考资料 前言 Linux内核5.10内核版本引入新特性&#xff1a;Static calls。 Static c…

关于摄像头模组中滤光片的介绍

1、问题背景 红外截止滤光片&#xff08;IR CUT Filter&#xff09;是应用在摄像头模组中非常重要的一个器件&#xff0c;因人眼与 coms sensor 对光线各波长的响应不同&#xff0c; 人眼看不到红外光&#xff0c;但 sensor 能感应到&#xff08;如下图是某sensor在各波长下的…

【设计模式-04】原型模式

【设计模式-04】原型模式 1. 概述2. 结构3. 实现4. 案例5. 使用场景6. 优缺点6.1 原型模式的优点6.2 原型模式的缺点 7. 实现深克隆(深拷贝) 1. 概述 原型模式: 用一个已经创建的实例作为原型&#xff0c;通过复制该原型对象来创建一个和原型对象相同的新对象。 2. 结构 原型…

策略模式和状态模式

策略模式 在上下文中携带策略接口作为成员变量&#xff0c;在使用上下文之前需要设置策略setStrategy&#xff08;&#xff09;&#xff0c;然后使用策略接口成员变量来进行策略的执行。 步骤1&#xff1a;定义策略接口 // 策略接口 public interface Strategy {int execut…

面试突击:ArrayList源码详解

本文已收录于&#xff1a;https://github.com/danmuking/all-in-one&#xff08;持续更新&#xff09; 前言 哈喽&#xff0c;大家好&#xff0c;我是 DanMu。ArrayList 是我们日常开发中不可避免要使用到的一个类&#xff0c;并且在面试过程中也是一个非常高频的知识点&#…

酷睿Ultra 200V系CPU全阵容规格、跑分出炉:拉了坨大的

从最近几个月 12 代酷睿 CPU 大面积降价清库存&#xff0c;到 13、14 代高端 U 大范围翻车问题迟迟得不到解决。 这就很难不让人生出一种 Intel 似乎真无暇顾及老款 U&#xff0c;而是将有限精力通通放在了接下来酷睿 Ultra 处理器上的感觉。 当然&#xff0c;作为新工艺、新架…

【编译原理必考大题】 推导构建语法树,写出语法树的短语,简单短语和句柄

写在最前 本文为编译原理重点考察大题之一&#xff0c;理论基础见专栏文章&#xff0c;0基础直接使用也可食用 文章目录 推导构造语法树1.语法树的概念2. 子树&#xff0c;短语&#xff0c;简单短语&#xff0c;句柄2.1 子树2.2 短语2.3 简单短语与句柄2.4 真题实战 推导构造语…