纯js 贪吃蛇游戏解析与源码

(一)贪吃蛇

1、  首先思考贪吃蛇游戏中的对象都有哪些,其属性和方法又是什么?

2、  通过什么媒介来实现蛇,显示界面,以及食物之间的对应关系?

3、  具体对象的具体属性、方法说明:

(1)   游戏界面(show)
属性:宽高背景颜色相对定位容纳自己div的对象
方法:显示游戏界面(创造div根据游戏界面属性设置界面样式)

(2)   蛇本身(snake)
属性:每节蛇身的宽高绝对定位移动方向,数组body[]初始存放三节蛇身的相对位置,颜色,以及每节蛇身对象(初始为null)
方法:
(i)显示蛇的方法 根据属性为body[i][3]为null的蛇身设置样式 ,因为蛇在不停移动,其他样式固定,但top,left在随时变,所以每次for循环都要根据其body[i][0],body[i][1]设置其位置.
(ii)接收按键值的方法用来时刻控制蛇的走向
(iii)蛇移动的方法 每次移动都让后面的蛇节跟着前面蛇节的路径行驶,所以用for逆向循环把前面的蛇节信息赋给后面的 蛇头每时每刻都在更新,判断是否有键按下,改变蛇头数组值,判断是否撞墙(蛇头定位是否大于或者小于显示界面宽高),若撞到墙提示板提示信息  判断是否吃到自己(for循环判断蛇头位置是否和其他蛇身位置重合),若吃到自己提示板提示信息 判断吃到食物(蛇头位置数组值与食物位置值相等)若吃到食物把蛇身数组增加,存储其位置,分数增加,随机再次产生食物的位置

(3)   食物(food)
属性:食物宽高颜色绝对定位存储食物自身的对象初始为null
方法:显示食物 判断若是初次显示食物(食物自身对象为null)先创建食物自身 并对根据属性设置相关样式,由于食物的位置也在每次变,则每次显示都要设置其top值和left值,所以将其放在判断之外,每次调方法必执行

(4)   提示栏(subInfo)
提示栏的值均固定,所以直接写一个显示方法,各种情况导致游戏结束都调用此方法就可以 主要提示栏有两个点击事件来选择重新游戏还是关闭游戏

4、界面,蛇身,以及食物之间的联系:
       给显示界面一个相对定位,之后的蛇身食物的绝对定位都会依据显示界面。蛇身用            一个数组来存储body[[x,y,颜色,其自身身体对象]]

5、注意事项以及难点

  (1)数组内存放的位置与显示的定位top,left不是完全对应的,因为蛇节尤其宽高,所以每次的定位应该给数组值乘每节蛇身的长度(步长)

  (2)数组之间的由后向前替换之后再移动之后,最后才进行蛇身位置的定位

6、代码的不足,以及优化

 (1)程序中依旧存在大量重复代码,可以继续优化代码。有的对象只有一个,可以考虑使用自定义对象的方法而不是构造函数

  (2)由于本代码使用纯js ,个人觉得将有些对象(提示对象)用HTML+CSS实现效果更佳,用户体验会更好

  (3)游戏中还可以设置更多操作,与样式如变换蛇捕食的环境,设置更多关卡等。

7、收获

   实现一个游戏最重要的还是要有自己的思路,思路就如1,没有思路其他均为0,逻辑一定要清晰,对每个对象,每个方法实现其功能都要做到心中有数。学到了一些实用性技能,数组+定位是游戏的常态。每次如果只创建一次显示多次时,可以加if条件判断,让只执行一次的就执行一次,之后改变其样式如位置变化等

代码实现

var show;
var snake;
var food;
var timer;
var sum = 0;
var sub;
//显示类
function Show() {
this.width = 800;
this.height = 400;
this.backgroundColor = "#e3e4e5";
this.position = "absolute";
this.showBody = "null";
this.showMap = function() {
this.showBody = document.createElement("div");
this.showBody.style.width = this.width + "px";
this.showBody.style.height = this.height + "px";
this.showBody.style.position = this.position;
this.showBody.style.backgroundColor = this.backgroundColor;
document.body.appendChild(this.showBody);
};
}
//提示信息栏
function Subinfo() {
this.width = 300;
this.height = 50;
this.border = "2px solid green";
this.shadw = "0 0 3px red";
this.backgroundColor = "red";
this.position = "absolute";
this.left = 50;
this.top = 20;
this.subBody = null;
this.score = null;
this.level1 = null;
this.level2 = null;
this.showSubinfo = function() {
if(this.subBody == null) {
this.subBody = document.createElement("div");
this.subBody.style.width = this.width+"px";
this.subBody.style.height = this.height+"px";
//this.subbody.style.border = this.border;
this.subBody.style.boxShadow = this.shadw;
this.subBody.style.backgroundColor = this.backgroundColor;
this.subBody.style.position = this.position;
this.subBody.style.right = this.left+"px";
this.subBody.style.top = this.top+"px";


this.score = document.createElement("div");
this.score.style.width = "150px";
this.score.style.height = "30px";
this.score.style.margin = "10px 5px 0px 5px";
this.score.style.fontSize = "18px";
this.score.style.lineHeight = "30px";
this.score.style.textAlign = "center";
this.score.style.color = "white";
this.score.style.float="left";
this.score.innerHTML = "分数:" + sum+"&nbsp蛇速:";
this.subBody.appendChild(this.score);
this.level1 = document.createElement("button");
this.level2 = document.createElement("button");
this.level1.style.width = "50px";
this.level1.style.height = "30px";
this.level1.style.fontSize="12px";
this.level1.style.margin = "10px 5px";
this.level1.style.float="left";
this.level1.innerHTML="中速";
this.level1.style.lineHeight = "30px";
this.level1.style.color = "black";
this.level1.οnclick=function(){
clearInterval(timer);
timer = setInterval('snake.move()', 500);
}
this.level2.style.width = "50px";
this.level2.style.height = "30px";
this.level2.style.margin = "10px 5px";
this.level2.style.float="left";
this.level2.style.fontSize="12px";
this.level2.style.lineHeight = "30px";
this.level2.innerHTML="高速";
this.level1.style.color = "black";
this.level2.οnclick=function(){
//alert("1");
clearInterval(timer)
timer = setInterval('snake.move()', 200);
}
this.level2.style.lineHeight = "20px";
this.level2.style.color = "black";
this.level2.style.textAlign = "center";
this.subBody.appendChild(this.level1);
this.subBody.appendChild(this.level2);
show.showBody.appendChild(this.subBody);


}

}
}
//食物类
function Food() {
this.width = 20;
this.height = 20;
this.backgroundColor = "green";
this.position = "absolute";
this.radius = 5;
this.x = 0;
this.y = 0;
this.foodBody = null;
this.showFood = function() {
if(this.foodBody == null) {
this.foodBody = document.createElement("div");
this.foodBody.style.width = this.width + "px";
this.foodBody.style.height = this.height + "px";
this.foodBody.style.position = this.position;
this.foodBody.style.borderRadius = this.radius + "px";
this.foodBody.style.backgroundColor = this.backgroundColor;
show.showBody.appendChild(this.foodBody);
}
this.x = Math.floor(Math.random() * 40);
this.y = Math.floor(Math.random() * 20);
console.log(this.x + "------" + this.y);
this.foodBody.style.left = this.x * this.width + "px";
this.foodBody.style.top = this.y * this.height + "px";
};
}
//蛇类
function Snake() {
this.width = 20;
this.height = 20;
this.position = "absolute";
this.diret = '';
this.snakebody = null;
this.radius = 5;
this.border = "1px solid black";
this.body = [
[3, 2, "blue", null],
[2, 2, "green", null],
[1, 2, "green", null]
];
this.setDiret = function(code) {
switch(code) {
case 37:
this.diret = "left";
break;
case 38:
this.diret = "up";
break;
case 39:
this.diret = "right";
break;
case 40:
this.diret = "down";
break;


}
}
this.showSnake = function() {
for(var i = 0; i < this.body.length; i++) {
if(this.body[i][3] == null) {
this.body[i][3] = document.createElement("div");
this.body[i][3].style.width = this.width + "px";
this.body[i][3].style.height = this.height + "px";
this.body[i][3].style.position = this.position;
this.body[i][3].style.borderRadius = this.radius + "px";
this.body[i][3].style.border = this.border;
this.body[i][3].style.backgroundColor = this.body[i][2];
show.showBody.appendChild(this.body[i][3]); //把蛇身加到蛇最后
}
this.body[i][3].style.left = this.body[i][0] * this.width + "px";
this.body[i][3].style.top = this.body[i][1] * this.height + "px";
}
}
this.move = function() {
//先让后面节点等于前面节点和前面节点步调一致
for(var i = this.body.length - 1; i > 0; i--) {
this.body[i][0] = this.body[i - 1][0];
this.body[i][1] = this.body[i - 1][1];
}
//判断按键 让蛇头移动 后面跟着蛇头移动
switch(this.diret) {
case "left":
this.body[0][0] -= 1;
break;
case "up":
this.body[0][1] -= 1;
break;
case "right":
this.body[0][0] += 1;
break;
case "down":
this.body[0][1] += 1;
break;
default:
return;
}
console.log(this.body[0][0] + "-----" + this.body[0][1]);
//吃到食物
if(this.body[0][0] == food.x && this.body[0][1] == food.y) {
//显示加5分
subInfo.showscore();
setTimeout('subInfo.subDisappear()',1000);
var x = this.body[this.body.length - 1][0];
var y = this.body[this.body.length - 1][1];
//console.log(x+"------"+y);
sum += 5;
sub.score.innerHTML = "分数:" + sum+"&nbsp蛇速:";
this.body.push([x, y, "green", null]);
food.showFood();

}

//判断是否吃到自己
for(var i = 1; i < this.body.length; i++) {
//console.log(this.body[i][1]+"---"+this.body[0][1]);


if(this.body[0][0] == this.body[i][0] && this.body[0][1] == this.body[i][1]) {
//显示一个动态框
subInfo.subBox.innerHTML = "吃到自己啦!";
subInfo.subShow();
clearInterval(timer);
}
}
//判断撞墙
if(this.body[0][0] < 0 || this.body[0][0] > 39 || this.body[0][1] < 0 || this.body[0][1] > 19) {
//显示动态框
subInfo.subBox.innerHTML = "撞到墙啦!";
subInfo.subShow();
clearInterval(timer);
}
this.showSnake();
}
}
//显示信息
var subInfo = {
width: 200,
height: 150,
subBox: document.createElement("div"),
subok: document.createElement("div"),
subno: document.createElement("div"),
subscore:null,
showscore:function(){
this.subscore=document.createElement("div");
this.subscore.style.width="100px";
this.subscore.style.height="100px";
this.subscore.innerHTML="+5";
this.subscore.style.fontSize="28px";
this.subscore.style.color="#ffffff";
this.subscore.style.fontWeight=900;
this.subscore.style.position="absolute";
this.subscore.style.top="15px";
this.subscore.style.right="185px";
//this.subscore.style.visibility="hidden";
show.showBody.appendChild(this.subscore);
},
subShow: function() {
this.subBox.style.width = this.width + "px";
this.subBox.style.height = this.height + "px";
this.subBox.style.backgroundColor = "blue";
this.subBox.style.position = "relative";
this.subBox.style.fontSize = "20px";
this.subBox.style.fontWeight = 700;
this.subBox.style.margin = "150px auto";
this.subBox.style.textAlign = "center";
this.subBox.style.lineHeight = "100px";
this.subBox.style.color = "#ffffff";
this.subok.style.width = "70px";
this.subok.style.height = "25px";
this.subok.style.position = "absolute";
this.subok.style.left = "20px";
this.subok.style.bottom = "30px";
this.subok.style.backgroundColor = "red";
this.subok.style.color = "#ffffff";
this.subok.style.fontSize = "8px";
this.subok.innerHTML = "再来一次";
this.subok.style.lineHeight = "25px";
this.subno.style.width = "70px";
this.subno.style.height = "25px";
this.subno.style.position = "absolute";
this.subno.style.left = "100px";
this.subno.style.bottom = "30px";
this.subno.style.backgroundColor = "red";
this.subno.style.fontSize = "8px";
this.subno.style.color = "#ffffff";
this.subno.innerHTML = "关闭游戏";
this.subno.style.lineHeight = "25px";
this.subBox.appendChild(this.subok);
this.subBox.appendChild(this.subno);
show.showBody.appendChild(this.subBox);
this.subok.onclick = function() {
window.location.reload();
};
this.subno.onclick = function() {
window.close();
};
},
subDisappear:function(){
if(this.subscore!=null){
this.subscore.remove();
}

}
}
//显示在界面
window.onload = function() {
    sum=0;
show = new Show();
show.showMap();
sub=new Subinfo();
sub.showSubinfo();
food = new Food();
food.showFood();
snake = new Snake();
snake.showSnake();
timer = setInterval('snake.move()', 1000);

document.onkeydown = function() {
var code;
if(window.event) {
code = window.event.keyCode;
} else {
code = event.keyCode;
}
snake.setDiret(code);
}
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值