“贪吃蛇”

Leo_wlCnBlogs Leo_wlCnBlogs     2022-08-20     673

关键词:

“贪吃蛇”小游戏

HTML5贪吃蛇游戏

页面结构

以保存对javascript的些许理解

复制代码
/****************/
/*****game.js****/
/****************/
Array.prototype.remove = function (obj) {
    for (var i = 0, l = this.length; i < l; i++) {

        if (this[i] == obj) {
            this.splice(i, 1);
            break;
        }
    }
}

var Game = {
    //循环ID
    timeId: -1,
    //context2d对象
    gamebg: null,
    //游戏背景信息
    gameinfo: {},
    //开始按钮
    btn: null,
    //初始化
    snake: null,
    food: null,
    init: function () {
        //获取游戏背景dom
        var game_dom = document.getElementById('gamebg'),
        This = this;
        //设置游戏背景信息
        this.gameinfo = {
            width: game_dom.clientWidth,
            height: game_dom.clientHeight,
            left: game_dom.offsetLeft,
            top: game_dom.offsetTop
        };
        //获取context2d对象
        this.gamebg = game_dom.getContext('2d');
        //绑定键盘按下事件
        document.onkeydown = function (e) { This.keyDown(e); };
        //创建小球
        this.snake = new Snake(7, this.gameinfo.width, this.gameinfo.height);
        this.food = new Food(100, 100, 4, 'red');
        //this.createFood();
    },

    keyDown: function (e) {
        var d = this.snake.direction;
        switch (e.keyCode) {
            case 37:
                d = 9;
                break;
            case 38:
                d = 12;
                break;
            case 39:
                d = 3;
                break;
            case 40:
                d = 6;
                break;
            case 32:
                this.pause(document.getElementById('Button2'));
                break;
        }
        if (Math.abs(this.snake.direction - d) != 6) {
            this.snake.oldDirection = this.snake.direction;
            this.snake.direction = d;
        }
        else {
            this.snake.back = 1;
        }
    },

    //btn:开始按钮dom
    start: function (btn) {

        if (this.btn) this.reset();

        this.btn = btn;
        this.btn.disabled = 'disabled';
        var This = this;
        this.init();
        //开始画画
        this.timeId = setInterval(function () {
            This.process();
        }, 80);
    },

    process: function () {
        //清除画面
        this.gamebg.clearRect(0, 0, this.gameinfo.width, this.gameinfo.height);
        this.snake.update(this.food);
        var body = this.snake.Body;
        Canvas.arc(this.gamebg, this.food.X, this.food.Y, this.food.Radius, this.food.Color);
        for (var i = 0; i < body.length; i++) {
            Canvas.arc(this.gamebg, body[i].X, body[i].Y, body[i].Radius, body[i].Color);
        }

        //判断游戏是否结束
        if (this.snake.Body.length == 0) {
            clearInterval(this.timeId);
            var score = document.getElementById("score");
            alert('您的分数是:' + score.innerHTML);
            this.btn.disabled = '';
        }
    },

    //重置游戏数据
    reset: function () {
        this.food = null;
        this.snake = null;
        this.timeId = -1;
        this.gamebg = null;
        this.gameinfo = {};
        var score = document.getElementById("score");
        score.innerHTML = 0;
    },

    pause: function (btn) {
        if (btn.value == 'Pause') {
            clearInterval(this.timeId);
            btn.value = 'Run';
        }
        else if (btn.value == 'Run') {
            btn.value = 'Pause';
            var This = this;
            this.timeId = setInterval(function () {
                This.process();
            }, 80);
        }
    }
复制代码

}

 

复制代码
/****************/
/*****food.js****/
/****************/
var Food = function (x, y, radius, color) {
    this.X = x;
    this.Y = y;
    this.Radius = radius;
    this.Color = color;
    this.fpt = 10000;
    this.lastUpdata = 0;
}

Food.prototype =
{
    update: function () {
        this.X = parseInt(Math.random() * 380 + 8, 10);
        this.Y = parseInt(Math.random() * 380 + 8, 10);
    }
复制代码

}

 

 

复制代码
/****************/
/*****Canvas.js****/
/****************/
var Canvas = {
    //画圆
    //ctx:context2d对象,x:圆心x坐标,y:圆心y坐标,radius:半径,color:颜色
    arc: function (cxt, x, y, radius, color) {
        cxt.fillStyle = color;
        cxt.beginPath();
        cxt.arc(x, y, radius, 0, Math.PI * 2, true);
        cxt.closePath();
        cxt.fill();
    }
复制代码

}

 

 

复制代码
/****************/
/*****Bone.js****/
/****************/
var Bone = function (x, y, radius, color) {
    this.X = x;
    this.Y = y;
    this.Radius = radius;
    this.Color = color;
复制代码

}

 

复制代码
/****************/
/*****Snake.js****/
/****************/
var Snake = function (length, width, height) {
    this.fpt = 40;
    this.Body = [];
    this.lastUpdata = 0;
    this.speed = 8;
    this.oldDirection = 6;
    this.direction = 6;
    var centerX = parseInt(width / 2, 10);
    var centerY = parseInt(height / 2, 10);

    var bone = new Bone(centerX, centerY, 4, 'blue');
    this.Body.push(bone);

    for (var i = 0; i < length - 1; i++) {
        var bone = new Bone(centerX, centerY - (8 * (i + 1)), 4, 'blue');
        this.Body.push(bone);
    }

    this.cornerX = centerX;
    this.cornerY = centerY;
    this.back = 0;
}

Snake.prototype =
{
    update: function (food) {
        if (this.lastUpdata % this.fpt == 0) {

            if (this.back == 1) {
                this.back = 0;
                var last = this.Body[this.Body.length - 1];
                var secondLast = this.Body[this.Body.length - 2];

                if (last.Y - secondLast.Y > 0) {
                    this.direction = 6;
                }
                else if (last.Y - secondLast.Y < 0) {
                    this.direction = 12;
                }
                else if (last.X - secondLast.X < 0) {
                    this.direction = 9;
                }
                else if (last.X - secondLast.X > 0) {
                    this.direction = 3;
                }
                this.Body.reverse();
            }


            //记录蛇头的原始坐标
            this.cornerX = this.Body[0].X;
            this.cornerY = this.Body[0].Y;

            //定义蛇头的新位置
            switch (this.direction) {
                case 12:
                    this.Body[0].Y -= this.speed;
                    break;
                case 6:
                    this.Body[0].Y += this.speed;
                    break;
                case 3:
                    this.Body[0].X += this.speed;
                    break;
                case 9:
                    this.Body[0].X -= this.speed;
                    break;
                default:
                    break;
            }
            //蛇身的新位置为前一个节点的位置
            for (var i = this.Body.length - 1; i > 1; i--) {
                this.Body[i].X = this.Body[i - 1].X;
                this.Body[i].Y = this.Body[i - 1].Y;
            }

            //定义蛇尾的新位置
            this.Body[1].X = this.cornerX;
            this.Body[1].Y = this.cornerY;

            this.eatFood(food);
            var over = false;
            for (var j = 0; j < this.Body.length; j++) {
                var bone = this.Body[j];
                if (bone.X < 0 || bone.Y < 0 || bone.X > 400 || bone.Y > 400) {
                    over = true;
                    break;
                }
            }

            if (over) {
                this.Body.length = 0;
            }
        }

        //时间累加
        this.lastUpdata += 10;
    },

    eatFood: function (food) {
        var i, l, bone, isTouch = false;
        //遍历蛇身体
        for (i = 0, l = this.Body.length; i < l; i++) {
            var bone = this.Body[i];
            //判断蛇身与食物的圆心距
            if (Math.sqrt(Math.pow(bone.X - food.X, 2) + Math.pow(bone.Y - food.Y, 2)) <= bone.Radius + food.Radius) {
                isTouch = true;
                break;
            }
        }

        //给蛇增加一节
        if (isTouch) {
            var head = this.Body[0];
            var x = head.X;
            var y = head.Y;
            switch (this.direction) {
                case 12:
                    y = y - head.Radius * 2;
                    break;
                case 3:
                    x = x + head.Radius * 2;
                    break;
                case 6:
                    y = y + head.Radius * 2;
                    break;
                case 9:
                    x = x - head.Radius * 2;
                    break;
            }
            var newBone = new Bone(x, y, head.Radius, head.Color);
            this.Body.push(newBone);

            //随机改变食物的位置
            food.X = -100;
            food.Y = -100;
            setTimeout(function () {
                food.update();
            }, 800);
            var score = document.getElementById("score");
            score.innerHTML = parseInt(score.innerHTML) + 1;
            if (this.fpt > 10) {
                this.fpt -= 10;
            }
        }
    }
复制代码

 

复制代码
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="game.js" type="text/javascript"></script>
    <script src="Bone.js" type="text/javascript"></script>
    <script src="Canvas.js" type="text/javascript"></script>
    <script src="Snake.js" type="text/javascript"></script>
    <script src="food.js" type="text/javascript"></script>
</head>
<body>
    <canvas id="gamebg" width="400" height="400" style="background: Black;">您的浏览器不支持html5,请使用chrome或者ff</canvas>
    <input id="Button1" type="button" value="Start" onclick="Game.start(this)" />
    <input id="Button2" type="button" value="Pause" onclick="Game.pause(this)" />
    <br />
<div id="score">0</div>
</body>
复制代码

</html> 

简单的21x21的方块,页面结构

id为container的div包含所21个class名为row的div,每个row代表贪吃蛇的一整行,每个row中又包含21个div,代表这一行的每一个div方格,如果这个方格是空的话,div的类名为blank,如果这一个方格表示“贪吃蛇”的“食物”,div的类名为food,如果这一个方格表示“蛇”,div的类名为snake。

CSS

JS

然后我们思考下一个贪吃蛇游戏需要那些参数,

首先,界面中可见的元素无非就是空方格,“蛇”还有“食物”,所以需要一个二维数组,用来表示每个方格的状态0表示方格为空,1表示方格为“食物”,2表示方格为“蛇”,然后是一个数组,存放“蛇”在方格中所占位子的坐标,再然后是一个存放“食物坐标”,由于需要确定“蛇”移动的方向,所以需要个存放方向的变量,还需要一个定时器,控制蛇每秒钟的移动,最后是需要统计用户的得分,所以有

我们需要创建游戏界面,所以在Game中添加函数createDOM,根据我们上文所说的页面结构,我们有

有了createDOM之后,在Game初始化的时候调用,初始化函数名为init

所以有

首先调用上文的createDOM方法生成页面

然后初始化data,data为一个长度21的二维数组,二维数组的每一个子元素又是一个数组,数组中的每个元素值都为0,

然后初始化蛇的坐标,这里默认为方格的9,10,11行的第10列,

然后是遍历snake数组,讲snake数组中每个元素表示的data中的位置的值改为2,即在data中表示蛇的位置,

接着需要生成食物的坐标,由于之后还要多次生成食物坐标,所以写了一个create_food方法,方便之后调用,

蛇的初始移动方向默认为“上”,

如果是用户第二次开始,先清除上一次游戏设置的定时器

初始化玩家得分为0

调用key_action方法,设置键盘事件,控制蛇的移动方向

然后是调用display方法,刷新游戏页面

create_food方法

先随机生成一个x,y的坐标,由于“食物”的生成位置只能在空位置,即data中值为0的位置,所以如果data[x][y]的值不为0的话,一直重新生成,直到生成的位置为空,将生成位置对应data中的值改为1,

key_action方法

读取键盘事件,并根据情况设置“贪吃蛇”的移动方向,

display方法

遍历data二维数组,数组中的值0,1,2对应空,“食物”,“蛇”,讲页面中所对应的标签的类名分别改写为“blank”,“food”,“snake”,

最为关键的是需要让蛇能动起来,我们写了一个snake_move方法,

思考一波,比如说snake现在的元素有[{x:9,y:10},{x:10,y:10},{x:11,y:10}],当前的direction的值是“up”向上移动,所以下一个状态的snake的元素应该是[{x:8,y:10},{x:9,y:10},{x:10,y:10}],也就是说,原来的snake将最后一个元素{x:11,y:10}舍弃,然后根据direction的值,计算出一个新的坐标,并snake数组的头部加入

所以有

last变量存放原来snake数组的最后一个元素,obj存放下一个时刻的snake头部的元素

如果direction的值为“up”那么下一个时刻snake头部元素,应该为原来的snake首个元素snake[0]的x值减1,snake[0]的y值不变,

direction为其他值的时候类推

但这样还不够,贪吃蛇存在碰到“墙壁”或者碰到“蛇”自己身体的情况,

还是拿direction的值为“up”类比,当原snake[0]的x值为0的时候,即已经到达了游戏框的顶部,如果继续向上移动,那么下一个x值应该为-1,显然是不合理的,所以有

还有“蛇”撞到自己身体的情况,上面说到obj存放的是下一个时刻snake头部的坐标,如果在data数组中所对应位置的值为2即“蛇”的身体,表示“蛇”撞到了自己的身体

所以有

上面说到obj存放的是下一个时刻snake头部的坐标,但是实际上snake这个数组并没有被重新赋值,所以我们还需要一个add_snake方法,每次数组变化的时候更新snake数组

并在snake_move中调用,调用后结果改变了snake数组变味了下一个状态,但是这个时候data数组所表示的原来的snake数组的最后一个元素,应该为空(蛇移动之后,尾部重新变为空)所以我们将之前保存下来的原snake的最后一个元素在data中对应的值变为0,

 

最后重新遍历新生成的snake数组,讲snake数组在data数组所对应的位置的值设为2

完整的snake_move方法

最后需要一个start方法,设置一个定时器,不断调用snake_move方法让蛇移动

在init的末尾调用start方法,大功告成

最后Game.init();初始化游戏,试玩下

一条贪吃蛇的使命——零基础入门贪吃蛇游戏(附演示地址)(代码片段)

零基础入门贪吃蛇游戏贪吃蛇是一款最常见、最经典、最受欢迎的小游戏之一。本篇文章带你零基础实现贪吃蛇游戏,一条蛇的使命从这里开始。演示地址:贪吃蛇演示,可能会提示危险操作,请忽略,放心访问。1、游戏描述??... 查看详情

“贪吃蛇”

“贪吃蛇”小游戏HTML5贪吃蛇游戏页面结构以保存对javascript的些许理解/****************//*****game.js****//****************/Array.prototype.remove = function (obj) {    for (var i 查看详情

贪吃蛇

  无聊发现自己没写过贪吃蛇,于是做了一个简单的贪吃蛇,并不打算做完整版的(只能看到贪吃蛇不断的从上往下移动)。。  效果(截图软件的问题,会有前一帧的印记):  代码:#include<iostream>#include<windows.h... 查看详情

我也来写一个贪吃蛇

...作量好大,好忙,趁周末练练手,花了近3小时写了一个贪吃蛇。  实现贪吃蛇的功能很简单。  我就分享一下我实现贪吃蛇看起来在界面上移动并且吃食物长大的原理。  我建了一个数组list_arr[]来保存贪吃蛇所在的每个... 查看详情

结对-贪吃蛇游戏-测试过程

贪吃蛇游戏托管平台地址:https://gitee.com/a540816440/codes/kuizlv3wfc5eyx8gopmhd70功能测试:移动功能,测试方法:使用键盘上的,方向键,是否贪吃蛇可以移动。  功能测试:分数功能测试方法:当贪吃蛇吃掉食物是否分数会有增加 ... 查看详情

结对-贪吃蛇游戏-需求分析

结对编程--贪吃蛇需要安装pythonpygame需求分析:玩家用键盘“WASD”来控制贪吃蛇的方向,          贪吃蛇碰壁结束游戏,主要完成游戏的开始按钮,暂停按钮,退出按钮等功能 查看详情

结对-贪吃蛇游戏-需求分析

结对编程--贪吃蛇需要安装pythonpygame需求分析:玩家用键盘“WASD”来控制贪吃蛇的方向,          贪吃蛇碰壁结束游戏,主要完成游戏的开始按钮,暂停按钮,退出按钮等功能 查看详情

hdu4302贪吃蛇

贪吃蛇Holedoxisasmallanimalwhichcanbeconsideredasonepoint.ItlivesinastraightpipewhoselengthisL.Holedoxcanonlymovealongthepipe.Cakesmayappearanywhereinthepipe,fromtimetotime.WhenHoledoxwantstoeatcakes,ita 查看详情

经典游戏还原之:贪吃蛇

...nitymaker)您可以自由转载,但必须加入完整的版权声明!贪吃蛇与方块主要玩法:贪吃蛇吃食物,吃到食物后根据相应数值增加身体长度,如果贪吃蛇碰到方块后,根据方块的数值逐渐减少贪吃蛇 查看详情

《结对-贪吃蛇-设计文档》

项目:贪吃蛇游戏,所用软件,eclipse成员:孙晨旭,高云鹏贪吃蛇游戏设计文档:搭建环境:AndroidStudio,eclipse“贪吃蛇”游戏是一个经典的游戏,它操作简单、界面美观、功能较齐全的“贪吃蛇”游戏。整个游戏程序分为二个... 查看详情

自制贪吃蛇游戏中的几个“大坑”(代码片段)

  贪吃蛇游戏已经告一段落了,在完成这个游戏的过程中,我遭遇了许多“坎坷”和“挫折”,下面就几个让我印象深刻的“挫折”做一个具体的讲解,以此来为这个贪吃蛇项目画上一个完整句号。(包括打包这个游戏时遇到... 查看详情

javascrip写的贪吃蛇

原生JavaScript写的贪吃蛇这个游戏好像就如同helloworld一样,简单又有代表性,以前我学习c语言的时候,第一个做的趣味小游戏也是贪吃蛇---------------------------------1//贪吃蛇的食物模块2(function(){3varelements=[]4//创建一个食物的构造... 查看详情

贪吃蛇需求分析

Partone项目题目 贪吃蛇游戏(单词版)Parttwo选题背景和意义 作为一个经典的游戏,贪吃蛇设计简单,实用和娱乐性高,是90后的我们童年的美好回忆。对于贪吃蛇传统的玩法,大家众所周知,即:玩家通过控制游戏手柄... 查看详情

gui简单实战——贪吃蛇(代码片段)

将前面学到的GUI基础知识完成实战,完成一个简单的贪吃蛇项目项目功能用键盘上下左右实现贪吃蛇的自动移动贪吃蛇吃到食物后,长度加一,分数加一贪吃蛇吃到自己的身体,则游戏结束按空格键实现游戏的暂停和继续效果截... 查看详情

结对-结对编项目贪吃蛇-设计文档

项目名称:贪吃蛇成员:张立新、李根使用工具:python目标:1.使用pygame模块,开发制作贪吃蛇游戏。   蛇头碰到食物时加长蛇身,蛇头碰到蛇身或者边界GOMEOVER(GG)。   2.每吃到一个食物加一分。游戏控制:1.暂停。... 查看详情

贪吃蛇版本1.0

学号(2017197);姓名:王浩铭我的码云贪吃蛇项目仓库:https://gitee.com/wojiubufu/projects今天尝试了给贪吃蛇添加背景音乐,预计时间十五分钟,结果花费的时间比预计多了好多,感受到了自己的不足,还有很长的路要走 查看详情

结对-贪吃蛇-开发过程

贪吃蛇又名贪食蛇,是一款经典的小游戏。玩家使用方向键操控一条长长的蛇不断吞下豆子,同时蛇身随着吞下的豆子不断变长,当蛇头撞到蛇身或障壁时游戏结束。贪吃蛇最初为人们所知的是诺基亚手机附带的一个小游戏,它... 查看详情

e-贪吃蛇

Holedoxisasmallanimalwhichcanbeconsideredasonepoint.ItlivesinastraightpipewhoselengthisL.Holedoxcanonlymovealongthepipe.Cakesmayappearanywhereinthepipe,fromtimetotime.WhenHoledoxwantstoeatcakes,italwa 查看详情