学习了Html5的Canvas的使用,和JS创建对象,做了一个贪吃蛇小游戏,来巩固JS面向对象编程和Canvas的用法。
Node.js
1 /** 2 * 格子类,组成贪吃蛇和舞台 3 */ 4 function Node(x,y){ 5 this.x=x; 6 this.y=y; 7 /** 8 * 比较两个格子是否重合 9 */ 10 this.equals=function(x,y){ 11 return this.x==x&&this.y==y; 12 } 13 }
Snake.js
1 /*定义全局变量UP,表示方向向上*/ 2 var UP=0; 3 /*定义全局变量LEFT,表示方向向左*/ 4 var LEFT=1; 5 /*定义全局变量RIGHT,表示方向向右*/ 6 var RIGHT=2; 7 /*定义全局变量DOWN,表示方向向下*/ 8 var DOWN=3; 9 /*初始化方向向右*/ 10 var DIR=RIGHT; 11 /*初始化分数为0*/ 12 var SCORE=0; 13 /*游戏是否结束*/ 14 var GAMEOVER=false; 15 /*等级*/ 16 var LEVEL=1; 17 /*速度*/ 18 var SPEED=30; 19 /*最高等级*/ 20 var MAXLEVEL=6; 21 /*绘画的时间间隔*/ 22 var TIME=200; 23 /** 24 * 贪吃蛇类 25 */ 26 function Snake(){ 27 /** 28 * 初始化贪吃蛇 29 */ 30 this.nodes=[]; 31 this.nodes.push(new Node(20,20)); 32 this.nodes.push(new Node(20,21)); 33 this.nodes.push(new Node(20,22)); 34 this.nodes.push(new Node(20,23)); 35 this.nodes.push(new Node(21,23)); 36 this.nodes.push(new Node(22,23)); 37 this.nodes.push(new Node(23,23)); 38 this.nodes.push(new Node(23,24)); 39 this.nodes.push(new Node(23,25)); 40 this.nodes.push(new Node(23,26)); 41 /** 42 * 判断蛇身是否包含当前坐标 43 */ 44 this.contains=function(x,y){ 45 for(i=0;i<this.nodes.length;i++){ 46 var node=this.nodes[i]; 47 if(node.equals(x,y)){ 48 return true; 49 } 50 } 51 return false; 52 }; 53 /** 54 * 获得一个与蛇身不重合的格子节点 55 */ 56 this.randomFood=function(){ 57 var x; 58 var y; 59 do{ 60 x=Math.floor(Math.random()*50); 61 y=Math.floor(Math.random()*50); 62 }while(this.contains(x,y)); 63 return new Node(x,y); 64 }; 65 /** 66 * 初始化食物 67 */ 68 this.food=this.randomFood(); 69 70 /** 71 * 向前走一步 72 * 添加头节点 73 * 删除尾节点 74 */ 75 this.step=function(){ 76 var oldHead=this.nodes[0]; 77 //根据方向计算新头节点 78 var newHead; 79 switch (DIR){ 80 case UP: 81 newHead=new Node(oldHead.x,oldHead.y-1); 82 if(newHead.y==-1){ 83 newHead.y=49; 84 } 85 break; 86 case DOWN: 87 newHead=new Node(oldHead.x,oldHead.y+1); 88 if(newHead.y==50){ 89 newHead.y=0; 90 } 91 break; 92 case LEFT: 93 newHead=new Node(oldHead.x-1,oldHead.y); 94 if(newHead.x==-1){ 95 newHead.x=49; 96 } 97 break; 98 case RIGHT: 99 newHead=new Node(oldHead.x+1,oldHead.y); 100 if(newHead.x==50){ 101 newHead.x=0; 102 } 103 break; 104 default: 105 break; 106 } 107 /** 108 * 如果吃到自己则结束游戏 109 */ 110 if(this.contains(newHead.x,newHead.y)){ 111 GAMEOVER=true; 112 } 113 /** 114 * 每走一步,添加新的头节点 115 */ 116 this.nodes.unshift(newHead); 117 /** 118 * 如果新添加的头节点与食物重合,即吃掉食物, 119 * 重新为食物赋值,并且分数加1 120 */ 121 if(newHead.x==this.food.x&&newHead.y==this.food.y){ 122 this.food=this.randomFood(); 123 SCORE+=1; 124 /*每吃5个食物,则等级加1*/ 125 if(SCORE%5==0){ 126 /*最高等级为5*/ 127 if(LEVEL<MAXLEVEL){ 128 LEVEL+=1; 129 } 130 } 131 }else{ 132 /*如果没有吃掉食物,则删除尾节点*/ 133 this.nodes.pop(); 134 } 135 //为时间间隔重新赋值 136 TIME=200-LEVEL*SPEED; 137 }; 138 139 }
Stage.js
1 /** 2 * 舞台类 3 */ 4 function Stage(){ 5 this.width=50; 6 this.height=50; 7 this.snake=new Snake(); 8 this.print=function(ctx){ 9 //绘制舞台的背景 10 ctx.fillStyle="#abcdef"; 11 ctx.fillRect(0,0,500,500); 12 //绘制一条蛇 13 ctx.fillStyle="chartreuse"; 14 for(i=0;i<this.snake.nodes.length;i++){ 15 var node=this.snake.nodes[i]; 16 ctx.fillRect(node.x*10,node.y*10,9,9); 17 } 18 //绘制食物 19 ctx.fillStyle="#0000ff"; 20 ctx.fillRect(this.snake.food.x*10,this.snake.food.y*10,9,9); 21 //绘制分数 22 ctx.font="20px 微软雅黑"; 23 ctx.fillStyle="green"; 24 ctx.fillText("分数:"+SCORE,5,25); 25 //绘制等级 26 ctx.font="20px 微软雅黑"; 27 ctx.fillStyle="green"; 28 ctx.fillText("等级:"+LEVEL,100,25); 29 } 30 }
snake.html
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>贪吃蛇</title> 6 <style type="text/css"> 7 canvas{ 8 border: 1px solid black; 9 } 10 </style> 11 <script type="text/javascript" src="Node.js" ></script> 12 <script type="text/javascript" src="Snake.js" ></script> 13 <script type="text/javascript" src="Stage.js" ></script> 14 <script type="text/javascript"> 15 var game; 16 function load(){ 17 var stage=new Stage(); 18 //获取用于绘制canvas的Context对象 19 var canvas=document.getElementById("mCanvas"); 20 var ctx=canvas.getContext("2d"); 21 //绘制初始界面 22 stage.print(ctx); 23 game=window.setInterval(function(){ 24 stage.snake.step(); 25 stage.print(ctx); 26 if(GAMEOVER){ 27 ctx.fillStyle="red"; 28 ctx.font="50px 微软雅黑"; 29 ctx.fillText("GAMEOVER!",100,250); 30 window.clearInterval(game); 31 } 32 },TIME); 33 } 34 /** 35 * 方向键控制贪吃蛇的方向 36 * @param {Object} dir 37 */ 38 function changeDir(dir){ 39 switch (dir){ 40 case UP: 41 if(DIR!=DOWN){ 42 DIR=dir; 43 } 44 break; 45 case DOWN: 46 if(DIR!=UP){ 47 DIR=dir; 48 } 49 break; 50 case LEFT: 51 if(DIR!=RIGHT){ 52 DIR=dir; 53 } 54 break; 55 case RIGHT: 56 if(DIR!=LEFT){ 57 DIR=dir; 58 } 59 break; 60 default: 61 break; 62 } 63 } 64 </script> 65 </head> 66 <body onload="load()"> 67 <canvas id="mCanvas" width="500" height="500"></canvas> 68 <!--控制方向--> 69 <table cellpadding="0px" cellspacing="0px"> 70 <tr> 71 <td></td> 72 <td><input type="button" value="上" onclick="changeDir(UP)"/></td> 73 <td></td> 74 </tr> 75 <tr> 76 <td><input type="button" value="左" onclick="changeDir(LEFT)"></td> 77 <td></td> 78 <td><input type="button" value="右" onclick="changeDir(RIGHT)"/></td> 79 </tr> 80 <tr> 81 <td></td> 82 <td><input type="button" value="下" onclick="changeDir(DOWN)"/></td> 83 <td></td> 84 </tr> 85 </table> 86 </body> 87 </html>