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方法:
---
1 var t=this; 2 t.x=x; 3 t.y=y; 4 t.w=w; 5 //食物 6 t.foodInit=function(){ 7 ctx.fillStyle='red'; 8 ctx.fillRect(x,y,w,w); 9 } 10 //蛇 11 t.snakeInit=function(){ 12 ctx.fillStyle='black'; 13 ctx.strokeStyle='white'; 14 ctx.fillRect(x,y,w,w); 15 ctx.strokeRect(x,y,w,w); 16 } 17 //清除蛇尾 18 t.clear=function(){ 19 ctx.fillStyle='white'; 20 ctx.strokeStyle='white'; 21 ctx.fillRect(x,y,w,w); 22 ctx.strokeRect(x,y,w,w); 23 }
----
接着是Fram函數里,要設置一個畫布環境並且要隨機產生食物:
----
1 function Farm(){ 2 var t=this; 3 ctx.fillStyle='white'; 4 ctx.fillRect(0,0,canvas.width,canvas.height); 5 //隨機生成食物 6 t.addfood=function(){ 7 var x=parseInt(canvas.width/gridWidth*Math.random())*gridWidth; 8 var y=parseInt(canvas.height/gridWidth*Math.random())*gridWidth; 9 var food=new Node(x,y,gridWidth); 10 food.foodInit(); 11 foods.push(food); 12 } 13 }
----
寫到這里,當你啟動gameStar函數時候會看到一些食物隨機產生在畫布上,顏色改一下,會有不同的畫布環境:
---
1 //開始游戲 2 function gameStart(){ 3 var farm=new Farm(); 4 setInterval(farm.addfood,2000); 5 } 6 gameStart();
---
現在到了最難的地方就是處理蛇,首先是畫一條蛇並啟動它和鍵盤事件取如下:
---
1 function Snake(x,y,len,speed){ 2 var t=this; 3 t.x=x; 4 t.y=y; 5 t.dir='R'; 6 //t.len=len; 7 var nx=x;ny=y; 8 t.init=function(){ 9 for (var i = 0; i <len; i++) { 10 var tempNode=new Node(nx,ny,gridWidth); 11 tempNode.snakeInit(); 12 nx-=gridWidth=10; 13 snakes.push(tempNode); 14 }; 15 //setInterval(t.move,speed) 16 } 17 18 //取得鍵盤方向 19 document.onkeydown=function(e){ 20 var code=e.keyCode; 21 switch(code){ 22 case 37: 23 t.dir='L'; 24 break; 25 case 38: 26 t.dir='U'; 27 break; 28 case 39: 29 t.dir='R'; 30 break; 31 case 40: 32 t.dir='D'; 33 break; 34 } 35 }
}
---
這主要是讓蛇動的move方法:
1 //移動蛇 2 t.move=function(){ 3 var newHead; 4 //初始化蛇頭的位置從而確定方向 5 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) 6 { 7 gameover(); 8 } 9 else{ 10 if(t.dir=='R'){ 11 newHead=new Node(snakes[0].x+gridWidth,snakes[0].y,gridWidth); 12 }else if(t.dir=='L'){ 13 newHead=new Node(snakes[0].x-gridWidth,snakes[0].y,gridWidth); 14 }else if(t.dir=='D'){ 15 newHead=new Node(snakes[0].x,snakes[0].y+gridWidth,gridWidth); 16 }else if(t.dir=='U'){ 17 newHead=new Node(snakes[0].x,snakes[0].y-gridWidth,gridWidth); 18 } 19 } 20 //畫蛇頭 21 newHead.snakeInit(); 22 //追加到數組中(長度會自動加) 23 snakes.unshift(newHead); 24 //清除尾部 25 snakes[snakes.length-1].clear(); 26 //並從數組中移除(長度會自動減) 27 snakes.pop(); 28 29 //判斷食物是否和蛇頭相撞 30 for (var i = 0; i < foods.length; i++) { 31 if(foods[i].equal(snakes[0])){ 32 //給蛇增加長度 33 t.addFood(); 34 clearInterval(snake_interval); 35 } 36 } 37 38 //給蛇增加長度(在尾巴加) 39 t.addFood=function(){ 40 var tail1=snakes[snakes.length-1]; 41 var tail2=snakes[snakes.length-2]; 42 var addNode; 43 if(tail1.x==tail2.x){ 44 if(tail1.y>=tail2.y) 45 addNode=new Node(tail1.x,tail1.y+gridWidth,gridWidth); 46 else 47 addNode=new Node(tail1.x,tail1.y-gridWidth,gridWidth); 48 } 49 else{ 50 if(tail1.x>=tail2.x) 51 addNode=new Node(tail1.x+gridWidth,tail1.y,gridWidth); 52 else 53 addNode=new Node(tail1.x-gridWidth,tail1.y,gridWidth); 54 } 55 56 //數組加入尾部 57 snakes.push(addNode); 58 addNode.snakeInit(); 59 }//addFood函數 60 }//move函數結束
---
到現在就是一點 其他條件設置,比喻不能反方向穿,不能穿自己。設置游戲結束后的步驟,現在可以先自己 思考下怎么寫。
---
所有的代碼在這里,有不足的可以提出一起進步:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>小游戲之貪吃蛇2次重寫(面向對象)</title> 6 <style> 7 #canvas{border: 1px solid red;} 8 </style> 9 </head> 10 <body> 11 <canvas id='canvas' width='800' height='600'></canvas> 12 <script> 13 var canvas=document.getElementById("canvas"); 14 var ctx=canvas.getContext('2d'); 15 var gridWidth=10; 16 var foods=new Array(),snakes=new Array();//放食物和蛇的數組 17 //原料初始化 18 function Node(x,y,w){ 19 var t=this; 20 t.x=x; 21 t.y=y; 22 t.w=w; 23 //食物 24 t.foodInit=function(){ 25 ctx.fillStyle='red'; 26 ctx.fillRect(x,y,w,w); 27 } 28 //蛇 29 t.snakeInit=function(){ 30 ctx.fillStyle='black'; 31 ctx.strokeStyle='white'; 32 ctx.fillRect(x,y,w,w); 33 ctx.strokeRect(x,y,w,w); 34 } 35 //清除蛇尾 36 t.clear=function(){ 37 ctx.fillStyle='white'; 38 ctx.strokeStyle='white'; 39 ctx.fillRect(x,y,w,w); 40 ctx.strokeRect(x,y,w,w); 41 } 42 //判斷是否重合 43 t.equal=function(node){ 44 if(this.x==node.x&&this.y==node.y) { 45 return true; 46 }else{ 47 return false; 48 } 49 } 50 } 51 52 //生成一個畫布和食物 53 function Farm(){ 54 var t=this; 55 ctx.fillStyle='white'; 56 ctx.fillRect(0,0,canvas.width,canvas.height); 57 //隨機生成食物 58 t.addfood=function(){ 59 var x=parseInt(canvas.width/gridWidth*Math.random())*gridWidth; 60 var y=parseInt(canvas.height/gridWidth*Math.random())*gridWidth; 61 var food=new Node(x,y,gridWidth); 62 food.foodInit(); 63 foods.push(food); 64 } 65 } 66 //畫蛇 67 function Snake(x,y,len,speed){ 68 var t=this; 69 t.x=x; 70 t.y=y; 71 t.dir='R'; 72 //t.len=len; 73 var nx=x;ny=y; 74 t.init=function(){ 75 for (var i = 0; i <len; i++) { 76 var tempNode=new Node(nx,ny,gridWidth); 77 tempNode.snakeInit(); 78 nx-=gridWidth; 79 snakes.push(tempNode); 80 }; 81 snake_interval=setInterval(t.move,speed) 82 } 83 84 //取得鍵盤方向 85 document.onkeydown=function(e){ 86 var code=e.keyCode; 87 t.odir=t.dir; 88 switch(code){ 89 case 37: 90 t.dir='L'; 91 break; 92 case 38: 93 t.dir='U'; 94 break; 95 case 39: 96 t.dir='R'; 97 break; 98 case 40: 99 t.dir='D'; 100 break; 101 } 102 } 103 //移動蛇 104 t.move=function(){ 105 var newHead; 106 //初始化蛇頭的位置從而確定方向 107 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) 108 { 109 gameover(); 110 } 111 else{ 112 if(t.dir=='R'){ 113 newHead=new Node(snakes[0].x+gridWidth,snakes[0].y,gridWidth); 114 }else if(t.dir=='L'){ 115 newHead=new Node(snakes[0].x-gridWidth,snakes[0].y,gridWidth); 116 }else if(t.dir=='D'){ 117 newHead=new Node(snakes[0].x,snakes[0].y+gridWidth,gridWidth); 118 }else if(t.dir=='U'){ 119 newHead=new Node(snakes[0].x,snakes[0].y-gridWidth,gridWidth); 120 } 121 } 122 123 //禁止反向跑 124 if(newHead.x==snakes[1].x&&newHead.y==snakes[1].y){ 125 t.dir=t.odir; 126 return; 127 } 128 129 130 //畫蛇頭 131 newHead.snakeInit(); 132 //追加到數組中(長度會自動加) 133 snakes.unshift(newHead); 134 //清除尾部 135 snakes[snakes.length-1].clear(); 136 //並從數組中移除(長度會自動減) 137 snakes.pop(); 138 139 //判斷食物是否和蛇頭相撞 140 for (var i = 0; i < foods.length; i++) { 141 if(foods[i].equal(snakes[0])){ 142 //給蛇增加長度 143 t.addFood(); 144 clearInterval(snake_interval); 145 speed=speed<20?speed:speed-10; 146 snake_interval=setInterval(t.move,speed); 147 } 148 } 149 150 //判斷是否與自己相撞 151 for (var i = 1; i < snakes.length; i++) { 152 if(snakes[i].equal(snakes[0])){ 153 gameover(); 154 } 155 }; 156 157 //給蛇增加長度(在尾巴加) 158 t.addFood=function(){ 159 var tail1=snakes[snakes.length-1]; 160 var tail2=snakes[snakes.length-2]; 161 var addNode; 162 if(tail1.x==tail2.x){ 163 if(tail1.y>=tail2.y) 164 addNode=new Node(tail1.x,tail1.y+gridWidth,gridWidth); 165 else 166 addNode=new Node(tail1.x,tail1.y-gridWidth,gridWidth); 167 } 168 else{ 169 if(tail1.x>=tail2.x) 170 addNode=new Node(tail1.x+gridWidth,tail1.y,gridWidth); 171 else 172 addNode=new Node(tail1.x-gridWidth,tail1.y,gridWidth); 173 } 174 175 //數組加入尾部 176 snakes.push(addNode); 177 addNode.snakeInit(); 178 console.log(snakes.length); 179 180 }//addFood函數 181 }//move函數結束 182 183 }/*snake函數結束*/ 184 185 //開始游戲 186 function gameStart(){ 187 var farm=new Farm(); 188 food_interval=setInterval(farm.addfood,2000); 189 190 //畫蛇 191 snakes=[];//重新初始化數組,不要把前一次的數組元素遺留 192 var snake=new Snake(100,100,5,500); 193 snake.init(); 194 } 195 gameStart(); 196 //結束 197 function gameover(){ 198 var judge=confirm("游戲結束,是否重新開始"); 199 clearInterval(snake_interval); 200 clearInterval(food_interval); 201 while(!judge){ 202 //res= confirm("游戲結束,是否重新開始"); 203 return false; 204 } 205 gameStart(); 206 207 } 208 </script> 209 </body> 210 </html>