HTML5坦克大战(韩顺平版本)
HTML5坦克大战(韩顺平版本)
2017-3-22 22:46:22 by SemiconductorKING
去年暑假学习了一下HTML5实现简单的坦克大战,觉得对JavaScript初学者来说,练习这个小游戏代码段可以学到很多东西,包括canvas的简单运用,类的构造,类的继承等等。编写一个完整的游戏要有较强的逻辑性,这个demo的学习视频以及demo文件下载见我分享的链接:
链接:http://pan.baidu.com/s/1boAzSir 密码:mcp2
demo截图:
此demo只是一个简单的练习,效果low不low先不提,看代码吧:
HTML文件代码:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset='utf-8'/> 5 <script src='tank.js'></script> 6 </head> 7 <body onkeydown="changeDirect()"> 8 <h1 style="color: #0714b9;">html5坦克大战</h1> 9 <div style="margin: 30px"> 10 <canvas id='tankMap' width='500px' height='300px' style='background-color:#3e0549;'> 11 你的浏览器不支持canvas标签 ||||| You are seeing this message because your web browser does not support the canvas tag. 12 </canvas> 13 </div> 14 <div id='add1'></div> 15 <div id='add2'></div> 16 <div id='add3'></div> 17 <div style="margin: 30px;font-size: 12px"> 18 <p>控制方法:按下键盘w s a d或者↑ ↓ ← →分别是坦克的上下左右行驶<br/>按下j或者Enter键为射击</p> 19 </div> 20 </body> 21 <script> 22 var canvas = document.getElementById('tankMap'); 23 //获得画笔 24 var ctx = canvas.getContext('2d'); 25 26 //定义炸弹数组 27 var bombs = new Array(); 28 29 //构造英雄 30 var hero = new Hero(380,260,0,heroColor); 31 32 //创建敌人数组 33 var enemyTanks = new Array(); 34 35 //创建敌人的子弹数组 36 var enemyBullets = new Array(); 37 for(var i=0;i<6;i++){ 38 var enemyTank = new EnemyTank((i+1)*50,0,2,enemyColor); 39 enemyTanks[i] = enemyTank; 40 //drawTank(enemyTanks[i]); 41 //让敌人的坦克动起来 42 var timer = window.setInterval("enemyTanks["+i+"].run()",50); 43 enemyTanks[i].timer = timer; 44 //让敌人发射子弹 45 var enemyBullet = new Bullet(enemyTanks[i].x+9,enemyTanks[i].y+30,enemyTanks[i].direct,enemyTanks[i],'enemy'); 46 enemyBullets.push(enemyBullet); 47 enemyBullets[i].timer = window.setInterval("enemyBullets["+i+"].run()",50); 48 } 49 50 //定义英雄子弹数组 51 var heroBullets = new Array(); 52 var heroBullet = null; 53 54 if(hero.isLive){ 55 drawTank(hero); 56 } 57 58 //flashMap(); 59 //重置画布 60 function flashMap(){ 61 ctx.clearRect(0,0,500,300); 62 isHitHeroTank(enemyBullets,hero); 63 if(hero.isLive){ 64 drawTank(hero); 65 } 66 67 isHitEnemyTank(heroBullets,enemyTanks); 68 //画出自己坦克的子弹 69 drawHeroBullet(heroBullets); 70 //画出敌人坦克的子弹 71 drawEnemyBullet(enemyBullets,enemyTanks); 72 for(var i=0;i<6;i++){ 73 if(enemyTanks[i].isLive){ 74 drawTank(enemyTanks[i]); 75 } 76 } 77 78 //画出爆炸图片 79 for(var k=0;k<bombs.length;k++){ 80 var img = new Image(); 81 img.src = 'bomb_1.gif'; 82 var x = bombs[k].x; 83 var y = bombs[k].y; 84 ctx.drawImage(img,x,y,30,30); 85 ctx.drawImage(img,x,y,40,35); 86 ctx.drawImage(img,x,y,35,40); 87 bombs.splice(k,1); 88 } 89 } 90 91 function changeDirect(){ 92 var keycode = event.keyCode; 93 switch(keycode){ 94 case 38:; 95 case 87:hero.moveUp();break; 96 case 39:; 97 case 68:hero.moveRight();break; 98 case 40:; 99 case 83:hero.moveBottom();break; 100 case 37:; 101 case 65:hero.moveLeft();break; 102 case 74:; 103 case 13:hero.shotEnemy();break; 104 } 105 flashMap(); 106 } 107 window.setInterval("flashMap()",50); 108 </script> 109 </html>
tank.js代码:
1 //定义敌人和我们自己的坦克的颜色 2 var enemyColor = new Array("#0BB","#0FF"); 3 var heroColor = new Array("#dc0","#ff5"); 4 //封装一个公用的坦克父类 5 function Tank(x,y,direct){ 6 this.x = x; 7 this.y = y; 8 this.speed = 3; 9 this.direct = direct; 10 this.moveUp = function(){ 11 if (hero.y>0) { 12 hero.y -= hero.speed; 13 } 14 hero.direct = 0; 15 } 16 this.moveRight = function(){ 17 if (hero.x+30<500) { 18 hero.x += hero.speed; 19 } 20 hero.direct = 1; 21 } 22 this.moveBottom = function(){ 23 if (hero.y+30<300) { 24 hero.y += hero.speed; 25 } 26 hero.direct = 2; 27 } 28 this.moveLeft = function(){ 29 if (hero.x>0) { 30 hero.x -= hero.speed; 31 } 32 hero.direct = 3; 33 } 34 } 35 36 //英雄坦克类 37 function Hero(x,y,direct,color){ 38 //将坦克类的构造方法赋给hero 39 this.hero = Tank; 40 //调用,拥有坦克类的所有的属性和方法 41 this.hero(x,y,direct); 42 this.color = color; 43 this.direct = direct; 44 this.isLive = true; 45 this.shotEnemy = function(){ 46 switch(this.direct){ 47 case 0: 48 heroBullet = new Bullet(this.x+9,this.y,this.direct); 49 break; 50 case 1: 51 heroBullet = new Bullet(this.x+30,this.y+9,this.direct); 52 break; 53 case 2: 54 heroBullet = new Bullet(this.x+9,this.y+30,this.direct); 55 break; 56 case 3: 57 heroBullet = new Bullet(this.x,this.y+9,this.direct); 58 break; 59 } 60 heroBullets.push(heroBullet); 61 heroBullets[heroBullets.length-1].timer = window.setInterval("heroBullets["+(heroBullets.length-1)+"].run()",50); 62 } 63 } 64 //敌人的坦克 65 function EnemyTank(x,y,direct,color){ 66 //将坦克类的构造方法赋给敌人坦克 67 this.enemyTank = Tank; 68 //调用,拥有坦克类的所有的属性和方法 69 this.enemyTank(x,y,direct); 70 this.color = color; 71 this.isLive = true; 72 this.timer = null; 73 this.speed = 1; 74 this.count = 0; 75 this.direct = direct; 76 this.bulletIsLive = true; 77 this.run = function(){ 78 switch(this.direct){ 79 case 0: 80 if(this.y>0){ 81 this.y--; 82 } 83 break; 84 case 1: 85 if(this.x+30<500){ 86 this.x += this.speed; 87 } 88 break; 89 case 2: 90 if(this.y+30<300){ 91 this.y += this.speed; 92 } 93 break; 94 case 3: 95 if(this.x>0){ 96 this.x -= this.speed; 97 } 98 break; 99 } 100 101 if(this.count>=30){ 102 this.direct = Math.round(Math.random()*3); 103 this.count=0; 104 } 105 this.count++; 106 //在坦克走的过程中,判断一下,这个坦克的子弹是否活着 107 if(this.bulletIsLive == false && this.isLive){ 108 //子弹over,加子弹 109 switch(this.direct){ 110 case 0: 111 enemyBullets.push(new Bullet(this.x+9,this.y,this.direct,this,'enemy')); 112 break; 113 case 1: 114 enemyBullets.push(new Bullet(this.x+30,this.y+9,this.direct,this,'enemy')); 115 break; 116 case 2: 117 enemyBullets.push(new Bullet(this.x+9,this.y+30,this.direct,this,'enemy')); 118 break; 119 case 3: 120 enemyBullets.push(new Bullet(this.x,this.y+9,this.direct,this,'enemy')); 121 break; 122 } 123 enemyBullets[enemyBullets.length-1].timer = window.setInterval("enemyBullets["+(enemyBullets.length-1)+"].run()",50); 124 this.bulletIsLive = true; 125 } 126 } 127 } 128 //绘制坦克 129 function drawTank(hero){ 130 switch(hero.direct){ 131 case 0: 132 case 2: 133 ctx.fillStyle = hero.color[0]; 134 ctx.fillRect(hero.x,hero.y,5,30); 135 ctx.fillRect(hero.x+15,hero.y,5,30); 136 ctx.fillRect(hero.x+6,hero.y+5,8,20); 137 ctx.fillStyle = hero.color[1]; 138 ctx.beginPath(); 139 ctx.arc(hero.x+10,hero.y+15,3,0,Math.PI*2,true); 140 ctx.closePath(); 141 ctx.fill(); 142 //画出炮筒(直线) 143 ctx.strokeStyle = hero.color[1]; 144 ctx.lineWidth = 2; 145 ctx.moveTo(hero.x+10,hero.y+15); 146 if(hero.direct==0){ 147 ctx.lineTo(hero.x+10,hero.y); 148 }else if(hero.direct==2){ 149 ctx.lineTo(hero.x+10,hero.y+30); 150 } 151 ctx.stroke(); 152 break; 153 case 1: 154 case 3: 155 ctx.fillStyle = hero.color[0]; 156 ctx.fillRect(hero.x,hero.y,30,5); 157 ctx.fillRect(hero.x,hero.y+15,30,5); 158 ctx.fillRect(hero.x+5,hero.y+6,20,8); 159 //需要注意,画圆的时候需要重新开启路径 160 ctx.fillStyle = hero.color[1]; 161 ctx.beginPath(); 162 ctx.arc(hero.x+15,hero.y+10,3,0,Math.PI*2,true); 163 ctx.closePath(); 164 ctx.fill(); 165 //画出炮筒(直线) 166 ctx.strokeStyle = hero.color[1]; 167 ctx.lineWidth = 2; 168 ctx.moveTo(hero.x+15,hero.y+10); 169 if(hero.direct ==1){ 170 ctx.lineTo(hero.x+30,hero.y+10); 171 }else if(hero.direct ==3){ 172 ctx.lineTo(hero.x,hero.y+10); 173 } 174 ctx.stroke(); 175 break; 176 } 177 } 178 179 //定义一个子弹类 180 function Bullet(x,y,direct,tank,type){ 181 this.x = x; 182 this.y = y; 183 this.speed = 3; 184 this.direct = direct; 185 this.timer = null; 186 this.isLive = true; 187 this.tank = tank; 188 this.type = type; 189 this.run = function(){ 190 switch(this.direct){ 191 case 0: 192 this.y -= this.speed; 193 break; 194 case 1: 195 this.x += this.speed; 196 break; 197 case 2: 198 this.y += this.speed; 199 break; 200 case 3: 201 this.x -= this.speed; 202 break; 203 } 204 document.getElementById('add1').innerText = " 子弹x轴:"+this.x+" 子弹y轴:"+this.y; 205 document.getElementById('add2').innerText = " 坦克x轴:"+hero.x+" 坦克y轴:"+hero.y; 206 document.getElementById('add3').innerText = " hero子弹数量:"+heroBullets.length; 207 if(this.x <0 || this.x>=500 ||this.y<0 || this.y>300 || this.isLive==false){ 208 this.isLive = false; 209 if(this.type=='enemy'){ 210 this.tank.bulletIsLive = false; 211 } 212 window.clearInterval(this.timer); 213 } 214 } 215 } 216 function drawHeroBullet(bullets){ 217 for(var i=0;i<bullets.length;i++){ 218 var heroBullet = bullets[i]; 219 if(heroBullet.isLive){ 220 ctx.fillStyle = '#FEF26E'; 221 ctx.fillRect(heroBullet.x,heroBullet.y,2,2); 222 } 223 } 224 } 225 //画出敌人坦克的子弹 226 function drawEnemyBullet(enemyBullets){ 227 for(var i=0;i<enemyBullets.length;i++){ 228 var enemyBullet = enemyBullets[i]; 229 if(enemyBullet.isLive){ 230 ctx.fillRect(enemyBullet.x,enemyBullet.y,2,2); 231 } 232 } 233 } 234 function isHitEnemyTank(heroBullets,enemyTanks){ 235 for(var i=0;i<heroBullets.length;i++){ 236 for(var j=0;j<enemyTanks.length;j++){ 237 //判断一下自己的子弹和敌人的坦克坐标 238 if(enemyTanks[j].isLive){ 239 switch(enemyTanks[j].direct){ 240 case 0: 241 case 2: 242 if(heroBullets[i].x>=enemyTanks[j].x&&heroBullets[i].x<=enemyTanks[j].x+20&&heroBullets[i].y>=enemyTanks[j].y&&heroBullets[i].y<=enemyTanks[j].y+30){ 243 //标记敌人的坦克和我们的子弹已经死掉了 244 heroBullets[i].isLive = false; 245 enemyTanks[j].isLive = false; 246 var bomb = new Bomb(enemyTanks[j].x,enemyTanks[j].y); 247 bombs.push(bomb); 248 249 } 250 break; 251 case 1: 252 case 3: 253 if(heroBullets[i].x>=enemyTanks[j].x&&heroBullets[i].x<=enemyTanks[j].x+30&&heroBullets[i].y>=enemyTanks[j].y&&heroBullets[i].y<=enemyTanks[j].y+20){ 254 //标记敌人的坦克和我们的子弹已经死掉了 255 heroBullets[i].isLive = false; 256 enemyTanks[j].isLive = false; 257 var bomb = new Bomb(enemyTanks[j].x,enemyTanks[j].y); 258 bombs.push(bomb); 259 } 260 break; 261 } 262 } 263 264 } 265 } 266 } 267 268 //定义炸弹类 269 function Bomb(x,y){ 270 this.x = x; 271 this.y = y; 272 } 273 274 //判断敌人的子弹是否击中自己的坦克 275 function isHitHeroTank(enemyBullets,heroTank){ 276 for(var i=0;i<enemyBullets.length;i++){ 277 if(enemyBullets[i].isLive && heroTank.isLive){ 278 switch(heroTank.direct){ 279 case 0: 280 case 2: 281 if(enemyBullets[i].x >= heroTank.x && enemyBullets[i].x <= heroTank.x+20 && enemyBullets[i].y >= heroTank.y && enemyBullets[i].y <= heroTank.y +30){ 282 heroTank.isLive = false; 283 enemyBullets[i].isLive = false; 284 } 285 break; 286 case 1: 287 case 3: 288 if(enemyBullets[i].x >= heroTank.x && enemyBullets[i].x <= heroTank.x+30 && enemyBullets[i].y >= heroTank.y && enemyBullets[i].y <= heroTank.y +20){ 289 heroTank.isLive = false; 290 enemyBullets[i].isLive = false; 291 } 292 break; 293 } 294 } 295 } 296 }
end...