html5面向对象做一个贪吃蛇小游戏

时间:2023-03-08 22:16:19
html5面向对象做一个贪吃蛇小游戏

canvas加面向对象方式的贪吃蛇 2016-08-25

这个小游戏可以增加对面向对象的理解,可以加强js逻辑能力,总之认真自己敲一两遍收获还是不少啊!!适合刚学canvas的同学练习!!

废话不多说,直接来讲思路和代码.

-----------------------------------------------------------------------------------------------------------------

开发思路:首先要有蛇吃的食物,就是一个个canvas随机画出的方块,然后是蛇,蛇也是方块组成。于是我们构造一个函数,功能是产生食物和蛇的原材料,和处理一些关于方块的函数(后面会上代码)。其次是,开始游戏的函数,当页面加载完成后开始游戏,然后是当游戏开始是时候,我们要初始化一个画布和随机产生食物,接着是关于画蛇和控制蛇的构造函数。最后是当触发游戏结束的条件时候的游戏结束函数。首先搭建一个整体思路然后再细细入手,博主是这样写的,大神别笑话.

初始代码如下:

------

<script>
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext('2d');
var gridWidth=10;
var foods=new Array(),snakes=new Array();//放食物和蛇的数组
//原料初始化
function Node(x,y,w){ } //生成一个画布和食物
function Farm(){ }
//画蛇
function Snake(x,y,len,speed){
}
}
//开始游戏
function gameStart(){
}
gameStart();
//结束游戏
function gameover(){}
<script>

------

接着,就是一个一个思考:首先是Node函数里面设置一些基本生成方块方法,由于,蛇和食物并不同,所以分成单独的2个函数,并且,蛇运动的时候要去掉尾部的方块,所以这里还要加一个去掉clear方法:

---

          var t=this;
t.x=x;
t.y=y;
t.w=w;
//食物
t.foodInit=function(){
ctx.fillStyle='red';
ctx.fillRect(x,y,w,w);
}
//蛇
t.snakeInit=function(){
ctx.fillStyle='black';
ctx.strokeStyle='white';
ctx.fillRect(x,y,w,w);
ctx.strokeRect(x,y,w,w);
}
//清除蛇尾
t.clear=function(){
ctx.fillStyle='white';
ctx.strokeStyle='white';
ctx.fillRect(x,y,w,w);
ctx.strokeRect(x,y,w,w);
}

----

接着是Fram函数里,要设置一个画布环境并且要随机产生食物:

----

     function Farm(){
var t=this;
ctx.fillStyle='white';
ctx.fillRect(0,0,canvas.width,canvas.height);
//随机生成食物
t.addfood=function(){
var x=parseInt(canvas.width/gridWidth*Math.random())*gridWidth;
var y=parseInt(canvas.height/gridWidth*Math.random())*gridWidth;
var food=new Node(x,y,gridWidth);
food.foodInit();
foods.push(food);
}
}

----

写到这里,当你启动gameStar函数时候会看到一些食物随机产生在画布上,颜色改一下,会有不同的画布环境:

---

     //开始游戏
function gameStart(){
var farm=new Farm();
setInterval(farm.addfood,2000);
}
gameStart();

---

现在到了最难的地方就是处理蛇,首先是画一条蛇并启动它和键盘事件取如下:

---

          function Snake(x,y,len,speed){
var t=this;
t.x=x;
t.y=y;
t.dir='R';
//t.len=len;
var nx=x;ny=y;
t.init=function(){
for (var i = 0; i <len; i++) {
var tempNode=new Node(nx,ny,gridWidth);
tempNode.snakeInit();
nx-=gridWidth=10;
snakes.push(tempNode);
};
//setInterval(t.move,speed)
} //取得键盘方向
document.onkeydown=function(e){
var code=e.keyCode;
switch(code){
case 37:
t.dir='L';
break;
case 38:
t.dir='U';
break;
case 39:
t.dir='R';
break;
case 40:
t.dir='D';
break;
}
}
}

---

这主要是让蛇动的move方法:

         //移动蛇
t.move=function(){
var newHead;
//初始化蛇头的位置从而确定方向
if(snakes[0].x+snakes[0].w>=canvas.width||snakes[0].x-snakes[0].w<0||snakes[0].y-snakes[0].w<0||snakes[0].y+snakes[0].w>canvas.height)
{
gameover();
}
else{
if(t.dir=='R'){
newHead=new Node(snakes[0].x+gridWidth,snakes[0].y,gridWidth);
}else if(t.dir=='L'){
newHead=new Node(snakes[0].x-gridWidth,snakes[0].y,gridWidth);
}else if(t.dir=='D'){
newHead=new Node(snakes[0].x,snakes[0].y+gridWidth,gridWidth);
}else if(t.dir=='U'){
newHead=new Node(snakes[0].x,snakes[0].y-gridWidth,gridWidth);
}
}
//画蛇头
newHead.snakeInit();
//追加到数组中(长度会自动加)
snakes.unshift(newHead);
//清除尾部
snakes[snakes.length-1].clear();
//并从数组中移除(长度会自动减)
snakes.pop(); //判断食物是否和蛇头相撞
for (var i = 0; i < foods.length; i++) {
if(foods[i].equal(snakes[0])){
//给蛇增加长度
t.addFood();
clearInterval(snake_interval);
}
} //给蛇增加长度(在尾巴加)
t.addFood=function(){
var tail1=snakes[snakes.length-1];
var tail2=snakes[snakes.length-2];
var addNode;
if(tail1.x==tail2.x){
if(tail1.y>=tail2.y)
addNode=new Node(tail1.x,tail1.y+gridWidth,gridWidth);
else
addNode=new Node(tail1.x,tail1.y-gridWidth,gridWidth);
}
else{
if(tail1.x>=tail2.x)
addNode=new Node(tail1.x+gridWidth,tail1.y,gridWidth);
else
addNode=new Node(tail1.x-gridWidth,tail1.y,gridWidth);
} //数组加入尾部
snakes.push(addNode);
addNode.snakeInit();
}//addFood函数
}//move函数结束

---

到现在就是一点 其他条件设置,比喻不能反方向穿,不能穿自己。设置游戏结束后的步骤,现在可以先自己 思考下怎么写。

---

所有的代码在这里,有不足的可以提出一起进步:

         <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>小游戏之贪吃蛇2次重写(面向对象)</title>
<style>
#canvas{border: 1px solid red;}
</style>
</head>
<body>
<canvas id='canvas' width='' height=''></canvas>
<script>
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext('2d');
var gridWidth=;
var foods=new Array(),snakes=new Array();//放食物和蛇的数组
//原料初始化
function Node(x,y,w){
var t=this;
t.x=x;
t.y=y;
t.w=w;
//食物
t.foodInit=function(){
ctx.fillStyle='red';
ctx.fillRect(x,y,w,w);
}
//蛇
t.snakeInit=function(){
ctx.fillStyle='black';
ctx.strokeStyle='white';
ctx.fillRect(x,y,w,w);
ctx.strokeRect(x,y,w,w);
}
//清除蛇尾
t.clear=function(){
ctx.fillStyle='white';
ctx.strokeStyle='white';
ctx.fillRect(x,y,w,w);
ctx.strokeRect(x,y,w,w);
}
//判断是否重合
t.equal=function(node){
if(this.x==node.x&&this.y==node.y) {
return true;
}else{
return false;
}
}
} //生成一个画布和食物
function Farm(){
var t=this;
ctx.fillStyle='white';
ctx.fillRect(,,canvas.width,canvas.height);
//随机生成食物
t.addfood=function(){
var x=parseInt(canvas.width/gridWidth*Math.random())*gridWidth;
var y=parseInt(canvas.height/gridWidth*Math.random())*gridWidth;
var food=new Node(x,y,gridWidth);
food.foodInit();
foods.push(food);
}
}
//画蛇
function Snake(x,y,len,speed){
var t=this;
t.x=x;
t.y=y;
t.dir='R';
//t.len=len;
var nx=x;ny=y;
t.init=function(){
for (var i = ; i <len; i++) {
var tempNode=new Node(nx,ny,gridWidth);
tempNode.snakeInit();
nx-=gridWidth;
snakes.push(tempNode);
};
snake_interval=setInterval(t.move,speed)
} //取得键盘方向
document.onkeydown=function(e){
var code=e.keyCode;
t.odir=t.dir;
switch(code){
case :
t.dir='L';
break;
case :
t.dir='U';
break;
case :
t.dir='R';
break;
case :
t.dir='D';
break;
}
}
//移动蛇
t.move=function(){
var newHead;
//初始化蛇头的位置从而确定方向
if(snakes[].x+snakes[].w>=canvas.width||snakes[].x-snakes[].w<||snakes[].y-snakes[].w<||snakes[].y+snakes[].w>canvas.height)
{
gameover();
}
else{
if(t.dir=='R'){
newHead=new Node(snakes[].x+gridWidth,snakes[].y,gridWidth);
}else if(t.dir=='L'){
newHead=new Node(snakes[].x-gridWidth,snakes[].y,gridWidth);
}else if(t.dir=='D'){
newHead=new Node(snakes[].x,snakes[].y+gridWidth,gridWidth);
}else if(t.dir=='U'){
newHead=new Node(snakes[].x,snakes[].y-gridWidth,gridWidth);
}
} //禁止反向跑
if(newHead.x==snakes[1].x&&newHead.y==snakes[1].y){
t.dir=t.odir;
return;
} //画蛇头
newHead.snakeInit();
//追加到数组中(长度会自动加)
snakes.unshift(newHead);
//清除尾部
snakes[snakes.length-].clear();
//并从数组中移除(长度会自动减)
snakes.pop(); //判断食物是否和蛇头相撞
for (var i = ; i < foods.length; i++) {
if(foods[i].equal(snakes[])){
//给蛇增加长度
t.addFood();
clearInterval(snake_interval);
speed=speed<?speed:speed-;
snake_interval=setInterval(t.move,speed);
}
} //判断是否与自己相撞
for (var i = ; i < snakes.length; i++) {
if(snakes[i].equal(snakes[])){
gameover();
}
}; //给蛇增加长度(在尾巴加)
t.addFood=function(){
var tail1=snakes[snakes.length-];
var tail2=snakes[snakes.length-];
var addNode;
if(tail1.x==tail2.x){
if(tail1.y>=tail2.y)
addNode=new Node(tail1.x,tail1.y+gridWidth,gridWidth);
else
addNode=new Node(tail1.x,tail1.y-gridWidth,gridWidth);
}
else{
if(tail1.x>=tail2.x)
addNode=new Node(tail1.x+gridWidth,tail1.y,gridWidth);
else
addNode=new Node(tail1.x-gridWidth,tail1.y,gridWidth);
} //数组加入尾部
snakes.push(addNode);
addNode.snakeInit();
console.log(snakes.length); }//addFood函数
}//move函数结束 }/*snake函数结束*/ //开始游戏
function gameStart(){
var farm=new Farm();
food_interval=setInterval(farm.addfood,); //画蛇
snakes=[];//重新初始化数组,不要把前一次的数组元素遗留
var snake=new Snake(,,,);
snake.init();
}
gameStart();
//结束
function gameover(){
var judge=confirm("游戏结束,是否重新开始");
clearInterval(snake_interval);
clearInterval(food_interval);
while(!judge){
//res= confirm("游戏结束,是否重新开始");
return false;
}
gameStart(); }
</script>
</body>
</html>