效果图片
实现思想:
分析:
贪吃蛇游戏总体分三个部分:分别为头,背景,和蛇,只要把这三个部分组合起来,再加一些限制条件就是贪吃蛇游戏了,接下来咱们就分步骤去做贪吃蛇
第一步背景
背景就是HTML的描绘,单纯的利用HTML和css去描绘背景
<!DOCTYPE html>
<html>
<head>
<title>贪吃蛇</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
.map{
width: 800px;
height: 600px;
background-color: #7ca8d5;
position: relative;
border: 8px solid blue;
}
</style>
</head>
<body>
<div class="map" id ="demo"></div>
</body>
</html>
像上面这样一块背景图就做好了,接下来,我们在背景图内添加食物,切记,不能让食物跑出游戏边框外。
食物
食物这里用到了JavaScript和jQuery,jQuery需要自行到网站上下载,然后链接到本文件,像这样
<script src="jquery.js"></script>
这样你可以用jQuery了。
我们在创造食物的时候,只创造一个食物对象即可,通过不断更新去随机食物的坐标,当创建食物的时候需要初始化一些参数
var Food=function(color){
this.ele=null; //这个是保存上一个的食物div,方便更新食物时删除
this.x=0;
this.y=0;
this.width=20;
this.height=20;
this.color=color||"white";
}
这样食物的对象和一些初始化数据就设定好了,写下来我们要做的是要写一个更新函数,当蛇吃到食物时候,食物要更新,并且把之前的食物残留要删除。
//随机生成食物的颜色;
var colors=["yellow","red","blue","pink","purple","green"];
var pos = parseInt( Math.random()*colors.length);
Food.prototype.init = function() {
pos=parseInt( Math.random()*colors.length);
this.color=colors[pos];
this.remove();
var $div = $("<div></div>"); //通过jQuery去创建一个食物节点
var $map = $(".map");
$(".map").append($div); //在背景图上添加这个食物
$div.width(this.width); //通过jQuery去设置食物的样式
$div.attr("id","delete")
$div.height(this.height);
$div.css("background-color",this.color);
//下面是随机食物的坐标位置
this.x=parseInt(Math.random()*($map.width()/this.width))*this.width+8;
this.y=parseInt(Math.random()*($map.height()/this.height))*this.height+8;
$div.offset({left:this.x,top:this.y});
};
Food.prototype.remove=function(){
$("div").remove("#delete");
}
随后我们去创建食物这个对象,需要传入一个颜色参数
var food = new Food(colors[pos]);
food.init();
向上面这样即可随机位置创建随机颜色的食物,接下来我们创造一条蛇
蛇
在创建蛇的时候我们考虑一下蛇都可以做什么:首先,蛇可以移动,并且会有一个默认方向,蛇还会移动,蛇会在移动的过程中去吃掉食物,蛇吃掉食物之后身体会增长,蛇不能吃到自己的身体,蛇不能撞墙,食物不能出现在蛇的身体上,蛇在移动时候不能反方向移动,蛇在移动一个方向时候不能在同一频率内向其他方向移动
考虑以上的一些性质之后我们就去创造蛇
var OperationSet=[];
function snake(direction){
this.ele=[]; //存储蛇的移动上一次路径,方便删除其路径
this.width=20;
this.height=20;
this.body=[
{x:3,y:2,color:"white"},
{x:2,y:2,color:"red"},
{x:1,y:2,color:"red"}];
OperationSet.push("right");
}
创造蛇对象时候要初始化一些必要数据,并且给蛇一定长度,接下来去描绘蛇
Snake.prototype.init = function() {
this.remove(); //描绘之前,需要清除上一次蛇的位置,这样蛇才能动起来
for (var i = 0; i < this.body.length; i++) {
var obj = this.body[i];
var $div=$("<div></div>");
var $map = $(".map");
$map.append($div);
$div.width(this.width);
$div.height(this.height);
$div.attr("position","absolute");
$div.attr("id","bd");
$div.css("left",obj.x*this.width+'px');
$div.css("position","absolute");
$div.css("top",obj.y*this.height+'px');
$div.css("background-color",obj.color);
this.ele.push($div);
}
};
这部分是对蛇的初始化和描绘,接下来是蛇的动作和性质
Snake.prototype.move = function(food,event) {
var i = this.body.length-1;
for( ; i>0 ; i--){
this.body[i].x=this.body[i-1].x;
this.body[i].y=this.body[i-1].y;
}
switch(this.direction){
case "right":
this.body[0].x += 1;
break;
case "left":
this.body[0].x -= 1;
break;
case "top":
this.body[0].y -= 1;
break;
case "down":
this.body[0].y += 1;
break;
}
this.eat();
};
Snake.prototype.eat=function(){
var snakex = this.body[0].x*this.width+8;
var snakey = this.body[0].y*this.height+8;
var foodx=food.x;
var foody=food.y;
if(snakex==foodx&&snakey==foody){
var last = this.body[this.body.length-1];
this.body.push({x:last.x,y:last.y,color:food.color}); //蛇吃到食物后身体增长
food.init();
for(var i=0;i<this.body.length;i++){
//食物不能出现在蛇的身体上
while(food.x==this.body[i].x&&food.y==this.body[i].y){
food.init();
}
}
}
for(var i=1;i<this.body.length;i++){
var snakeheadx=this.body[0].x;
var snakeheady=this.body[0].y;
if(snakeheadx==this.body[i].x && snakeheady==this.body[i].y){
alert('over');
clearInterval(handler); //如果蛇迟到自己身体结束游戏,清除循环函数的句柄
return;
}
if(snakeheadx<0||snakeheadx>=(800/this.width)||snakeheady<0||snakeheady>=600/(this.height)){
alert('over'); //如果蛇撞到游戏边框,清除循环函数的句柄
clearInterval(handler);
return;
}
console.log(snakeheady);
}
this.init();
}
Snake.prototype.remove=function(){
for(var i = 0;i<this.ele.length;i++){
$("#bd").remove();
}
this.ele.length=0;
}
接下来去新建一个蛇的对象
var snake = new Snake();
接下来就是按键处理,在按键时候,把所有的连续放到堆栈里面,通过弹栈方式出处理按键处理,接下里就是按键的处理
document.addEventListener("keydown",function (e) {
switch (e.keyCode) {
case 37:
if(OperationSet.length==0 && snake.direction!="right"){
OperationSet.push("left");
}else if (OperationSet[OperationSet.length-1]!="right" && OperationSet[OperationSet.length-1]!=undefined && OperationSet[OperationSet.length-1] != "left")
OperationSet.push("left");
break;
case 40:
if(OperationSet.length==0 && snake.direction!="top"){
OperationSet.push("down");
}else if(OperationSet[OperationSet.length-1]!="top" && OperationSet[OperationSet.length-1]!=undefined && OperationSet[OperationSet.length-1] !="down")
OperationSet.push("down");
break;
case 39:
if(OperationSet.length==0 && snake.direction!="left"){
OperationSet.push("right");
}else if(OperationSet[OperationSet.length-1]!="left" && OperationSet[OperationSet.length-1]!=undefined && OperationSet[OperationSet.length-1] !="right")
OperationSet.push("right");
break;
case 38:
if(OperationSet.length==0 && snake.direction!="down"){
OperationSet.push("top");
}else if(OperationSet[OperationSet.length-1]!="down" && OperationSet[OperationSet.length-1]!=undefined && OperationSet[OperationSet.length-1] !="top" )
OperationSet.push("top");
break;
}
接下里要处理栈里面的数据,去更改蛇的移动方向如下
var directionFirst,directionSecond;
handler = setInterval(function(){
directionFirst = OperationSet.shift();
if(directionFirst!=directionSecond && directionFirst!=undefined){
directionSecond = directionFirst;
snake.direction=directionFirst;
}else {
snake.direction=directionSecond;
}
console.log(OperationSet[OperationSet.length-1]);
snake.move();
},200);
把上面的代码全部结合起来就是下面这样的
<!DOCTYPE html>
<html>
<head>
<title>贪吃蛇</title>
<meta charset="utf-8">
<style type="text/css">
*{
margin: 0;
padding: 0;
}
.map{
width: 800px;
height: 600px;
background-color: #7ca8d5;
position: relative;
border: 8px solid blue;
}
</style>
</head>
<body>
<div class="map" id="demo"></div>
</body>
<script src="jquery.js"></script>
<script type="text/javascript">
var handler;
var OperationSet=[];
var colors=["yellow","red","blue","pink","purple","green"];
var pos = parseInt( Math.random()*colors.length);
var Food=function(color){
this.ele=null;
this.x=0;
this.y=0;
this.width=20;
this.height=20;
this.color=color||"white";
}
Food.prototype.init = function() {
pos=parseInt( Math.random()*colors.length);
this.color=colors[pos];
this.remove();
var $div = $("<div></div>");
var $map = $(".map");
$(".map").append($div);
$div.width(this.width);
$div.attr("id","delete")
$div.height(this.height);
$div.css("background-color",this.color);
this.x=parseInt(Math.random()*($map.width()/this.width))*this.width+8;
this.y=parseInt(Math.random()*($map.height()/this.height))*this.height+8;
$div.offset({left:this.x,top:this.y});
};
Food.prototype.remove=function(){
$("div").remove("#delete");
}
var food = new Food(colors[pos]);
food.init();
function Snake(direction){
this.ele=[];
this.width=20;
this.height=20;
this.body=[
{x:3,y:2,color:"white"},
{x:2,y:2,color:"red"},
{x:1,y:2,color:"red"}];
OperationSet.push("right");
}
Snake.prototype.init = function() {
this.remove();
for (var i = 0; i < this.body.length; i++) {
var obj = this.body[i];
var $div=$("<div></div>");
var $map = $(".map");
$map.append($div);
$div.width(this.width);
$div.height(this.height);
$div.attr("position","absolute");
$div.attr("id","bd");
$div.css("left",obj.x*this.width+'px');
$div.css("position","absolute");
$div.css("top",obj.y*this.height+'px');
$div.css("background-color",obj.color);
this.ele.push($div);
}
};
Snake.prototype.move = function(food,event) {
var i = this.body.length-1;
for( ; i>0 ; i--){
this.body[i].x=this.body[i-1].x;
this.body[i].y=this.body[i-1].y;
}
switch(this.direction){
case "right":
this.body[0].x += 1;
break;
case "left":
this.body[0].x -= 1;
break;
case "top":
this.body[0].y -= 1;
break;
case "down":
this.body[0].y += 1;
break;
}
this.eat();
};
Snake.prototype.eat=function(){
var snakex = this.body[0].x*this.width+8;
var snakey = this.body[0].y*this.height+8;
var foodx=food.x;
var foody=food.y;
if(snakex==foodx&&snakey==foody){
var last = this.body[this.body.length-1];
this.body.push({x:last.x,y:last.y,color:food.color});
food.init();
for(var i=0;i<this.body.length;i++){
while(food.x==this.body[i].x&&food.y==this.body[i].y){
food.init();
}
}
}
for(var i=1;i<this.body.length;i++){
var snakeheadx=this.body[0].x;
var snakeheady=this.body[0].y;
if(snakeheadx==this.body[i].x && snakeheady==this.body[i].y){
alert('吃到自己 over');
clearInterval(handler);
return;
}
if(snakeheadx<0||snakeheadx>=(800/this.width)||snakeheady<0||snakeheady>=600/(this.height)){
alert('撞墙 over');
clearInterval(handler);
return;
}
}
this.init();
}
Snake.prototype.remove=function(){
for(var i = 0;i<this.ele.length;i++){
$("#bd").remove();
}
this.ele.length=0;
}
var snake = new Snake();
var directionFirst,directionSecond;
handler = setInterval(function(){
directionFirst = OperationSet.shift();
if(directionFirst!=directionSecond && directionFirst!=undefined){
directionSecond = directionFirst;
snake.direction=directionFirst;
}else {
snake.direction=directionSecond;
}
snake.move();
},200);
document.addEventListener("keydown",function (e) {
switch (e.keyCode) {
case 37:
if(OperationSet.length==0 && snake.direction!="right"){
OperationSet.push("left");
}else if (OperationSet[OperationSet.length-1]!="right" && OperationSet[OperationSet.length-1]!=undefined && OperationSet[OperationSet.length-1] != "left")
OperationSet.push("left");
break;
case 40:
if(OperationSet.length==0 && snake.direction!="top"){
OperationSet.push("down");
}else if(OperationSet[OperationSet.length-1]!="top" && OperationSet[OperationSet.length-1]!=undefined && OperationSet[OperationSet.length-1] !="down")
OperationSet.push("down");
break;
case 39:
if(OperationSet.length==0 && snake.direction!="left"){
OperationSet.push("right");
}else if(OperationSet[OperationSet.length-1]!="left" && OperationSet[OperationSet.length-1]!=undefined && OperationSet[OperationSet.length-1] !="right")
OperationSet.push("right");
break;
case 38:
if(OperationSet.length==0 && snake.direction!="down"){
OperationSet.push("top");
}else if(OperationSet[OperationSet.length-1]!="down" && OperationSet[OperationSet.length-1]!=undefined && OperationSet[OperationSet.length-1] !="top" )
OperationSet.push("top");
break;
}
</script>
</html>
当然这个按键处理目前存在bug,有能力的朋友可以指正哦。