In the previous article, we created the enemy's tank and our own tank. Next, we should let the tank fire bullets. Let's take a look at how to make our tank fire bullets.
Earlier we used object-oriented thinking to encapsulate Tank, and used object impersonation to implement our tank and the enemy's tank. Following this method, should we also encapsulate a Bullet? The answer is yes. . Okay, then let's think about what this Bullet "class" should encapsulate? The position should be there, the direction of the bullet's flight should be there, the speed of flight should be there, and the action of flying out by itself should be there. Okay, that's about it. The encapsulated Bulle "t class" is as follows:
//子弹类 function Bullet(x,y,direct,speed){ this.x=x; this.y=y; this.speed=speed; this.direct=direct; this.timer=null; this.run=function(){ switch(this.direct){ case 0: this.y-=this.speed; break; case 1: this.x+=this.speed; break; case 2: this.y+=this.speed; break; case 3: this.x-=this.speed; break; } } }
We have created the bullet model. Now we will use our tank to create bullets and send them out. In the Hero class Add shotEnemy method.
//定义一个Hero类 function Hero(x,y,direct,color){ //下面两句话的作用是通过对象冒充达到继承的效果 this.tank=Tank; this.tank(x,y,direct,color); //射击敌人函数 this.shotEnemy=function(){ switch(this.direct){ case 0: heroBullet=new Bullet(this.x+10,this.y,this.direct,1); break; case 1: heroBullet=new Bullet(this.x+30-4,this.y+10+4,this.direct,1); break; case 2: heroBullet=new Bullet(this.x+10,this.y+30,this.direct,1); break; case 3: heroBullet=new Bullet(this.x-4,this.y+10+4,this.direct,1); break; } //把这个子弹放入数组中——》push函数 //调用我们子弹的run //var timer=window.setInterval("heroBullet.run()",50); //heroBullet.timer=timer; heroBullets.push(heroBullet); var timer=window.setInterval("heroBullets["+(heroBullets.length-1)+"].run()",50); heroBullets[heroBullets.length-1].timer=timer; } }
In the key listening function, add a key to listen for firing bullets "J"
case 74: //J :发子弹 hero.shotEnemy(); break;
Okay, let's try firing bullets! Why can only one bullet be fired, and it is getting faster and faster? What is going on? Looking at the code we wrote above, it turns out that once our bullets are fired, they cannot stop. Although they have run out of our "battlefield", they are still running in one direction. Once the second bullet is fired, the first bullet will It disappears because the bullet is not redrawn when the interface is refreshed. Okay, now that we know the reason, let's determine whether the bullet is out of bounds, and then give the bullet a status isLive (this status marks whether the bullet exists, if it does not exist, it will not be redrawn when the bullet is redrawn). The modified code is as follows:
//子弹类 unction Bullet(x,y,direct,speed){ this.x=x; this.y=y; this.speed=speed; this.direct=direct; this.timer=null; this.isLive=true; this.run=function(){ //判断子弹是否已经到边界了 if(this.x<=0||this.x>=400||this.y<=0||this.y>=300){ //子弹要停止 window.clearInterval(this.timer); //子弹死亡 this.isLive=false; }else{ //可以去修改坐标 switch(this.direct){ case 0: this.y-=this.speed; break; case 1: this.x+=this.speed; break; case 2: break; } } }
If the bullet exceeds the scope of the canvas, set the isLive attribute to false
Then we add a refresh bullet function to the previous refresh interface function
//定时刷新我们的作战区(定时重绘) //自己的坦克,敌人坦克,子弹,炸弹,障碍物 function flashTankMap(){ //把画布清理 cxt.clearRect(0,0,400,300); //我的坦克 drawTank(hero); //我的子弹 drawHeroBullet(); //敌人的坦克 for(var i=0;i<3;i++){ drawTank(enemyTanks[i]); } }
//画出自己的子弹 function drawHeroBullet(){ for(var i=0;i<heroBullets.length;i++){ var heroBullet=heroBullets[i]; if(heroBullet!=null&&heroBullet.isLive){ cxt.fillStyle="#FEF26E"; cxt.fillRect(heroBullet.x,heroBullet.y,2,2); } } }
You can see that the isLive attribute of the bullet is determined in the drawHeroBullet above.
Let’s take a look at the running results
The full source code is as follows:
tankGame06.js
//为了编程方便,我们定义两个颜色数组 var heroColor=new Array("#BA9658","#FEF26E"); var enemyColor=new Array("#00A2B5","#00FEFE"); //子弹类 function Bullet(x,y,direct,speed){ this.x=x; this.y=y; this.speed=speed; this.direct=direct; this.timer=null; this.isLive=true; this.run=function(){ //判断子弹是否已经到边界了 if(this.x<=0||this.x>=400||this.y<=0||this.y>=300){ //子弹要停止 window.clearInterval(this.timer); //子弹死亡 this.isLive=false; }else{ //可以去修改坐标 switch(this.direct){ case 0: this.y-=this.speed; break; case 1: this.x+=this.speed; break; case 2: this.y+=this.speed; break; case 3: this.x-=this.speed; break; } } } } //定义一个Tank类(基类) function Tank(x,y,direct,color){ this.x=x; this.y=y; this.speed=1; this.direct=direct; this.color=color; //上移 this.moveUp=function(){ this.y-=this.speed; this.direct=0; } //右移 this.moveRight=function(){ this.x+=this.speed; this.direct=1; } //下移 this.moveDown=function(){ this.y+=this.speed; this.direct=2; } //左移 this.moveLeft=function(){ this.x-=this.speed; this.direct=3; } } //定义一个Hero类 function Hero(x,y,direct,color){ //下面两句话的作用是通过对象冒充达到继承的效果 this.tank=Tank; this.tank(x,y,direct,color); //设计敌人函数 this.shotEnemy=function(){ switch(this.direct){ case 0: heroBullet=new Bullet(this.x+10,this.y,this.direct,1); break; case 1: heroBullet=new Bullet(this.x+30-4,this.y+10+4,this.direct,1); break; case 2: heroBullet=new Bullet(this.x+10,this.y+30,this.direct,1); break; case 3: heroBullet=new Bullet(this.x-4,this.y+10+4,this.direct,1); break; } //把这个子弹放入数组中——》push函数 //调用我们子弹的run //var timer=window.setInterval("heroBullet.run()",50); //heroBullet.timer=timer; heroBullets.push(heroBullet); var timer=window.setInterval("heroBullets["+(heroBullets.length-1)+"].run()",50); heroBullets[heroBullets.length-1].timer=timer; } } //定义一个EnemyTank类 function EnemyTank(x,y,direct,color){ this.tank=Tank; this.tank(x,y,direct,color); } //绘制坦克 function drawTank(tank){ //考虑方向 switch(tank.direct){ case 0: //向上 case 2: //向下 //设置颜色 cxt.fillStyle=tank.color[0]; //左边的矩形 cxt.fillRect(tank.x,tank.y,5,30); //右边的矩形 cxt.fillRect(tank.x+17,tank.y,5,30); //画中间的矩形 cxt.fillRect(tank.x+6,tank.y+5,10,20); //画出坦克的盖子 cxt.fillStyle=tank.color[1]; cxt.arc(tank.x+11,tank.y+15,5,0,Math.PI*2,true); cxt.fill(); //画出炮筒 cxt.strokeStyle=tank.color[1]; cxt.lineWidth=1.5; cxt.beginPath(); cxt.moveTo(tank.x+11,tank.y+15); if(tank.direct==0){ //只是炮筒的方向不同 cxt.lineTo(tank.x+11,tank.y); }else{ cxt.lineTo(tank.x+11,tank.y+30); } cxt.closePath(); cxt.stroke(); break; case 1: case 3: //设置颜色 cxt.fillStyle="#BA9658"; //上边的矩形 cxt.fillRect(tank.x-4,tank.y+4,30,5); //下边的矩形 cxt.fillRect(tank.x-4,tank.y+17+4,30,5); //画中间的矩形 cxt.fillRect(tank.x+5-4,tank.y+6+4,20,10); //画出坦克的盖子 cxt.fillStyle="#FEF26E"; cxt.arc(tank.x+15-4,tank.y+11+4,5,0,Math.PI*2,true); cxt.fill(); //画出炮筒 cxt.strokeStyle="#FEF26E"; cxt.lineWidth=1.5; cxt.beginPath(); cxt.moveTo(tank.x+15-4,tank.y+11+4); if(tank.direct==1){ //只是炮筒的方向不同 cxt.lineTo(tank.x+30-4,tank.y+11+4); }else{ cxt.lineTo(tank.x-4,tank.y+11+4); } cxt.closePath(); cxt.stroke(); break; } }
Tank War.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> </head> <body onkeydown="getCommand();"> <h1>html5-坦克大战</h1> <!--坦克大战的战场--> <canvas id="tankMap" width="400px" height="300px" style="background-color:black"></canvas> <!--将tankGame04.js引入--> <script type="text/javascript" src="tankGame06.js"></script> <script type="text/javascript"> //得到画布 var canvas1=document.getElementById("tankMap"); //得到绘图上下文 var cxt=canvas1.getContext("2d"); //我的tank //规定0向上、1向右、2向下、3向左 var hero=new Hero(40,40,0,heroColor); //定义子弹数组 var heroBullets=new Array(); //敌人的tank var enemyTanks=new Array(); for(var i=0;i<3;i++){ var enemyTank = new EnemyTank((i+1)*50,0,2,enemyColor); enemyTanks[i]=enemyTank; } //画出自己的子弹 function drawHeroBullet(){ for(var i=0;i<heroBullets.length;i++){ var heroBullet=heroBullets[i]; if(heroBullet!=null&&heroBullet.isLive){ cxt.fillStyle="#FEF26E"; cxt.fillRect(heroBullet.x,heroBullet.y,2,2); } } } //定时刷新我们的作战区(定时重绘) //自己的坦克,敌人坦克,子弹,炸弹,障碍物 function flashTankMap(){ //把画布清理 cxt.clearRect(0,0,400,300); //我的坦克 drawTank(hero); //我的子弹 drawHeroBullet(); //敌人的坦克 for(var i=0;i<3;i++){ drawTank(enemyTanks[i]); } } flashTankMap(); //接收用户按键的函数 function getCommand(){ var code = event.keyCode; //键盘上字幕的ASCII码 switch(code){ case 87: //W :上 hero.moveUp(); break; case 68: //D :右 hero.moveRight(); break; case 83: //S :下 hero.moveDown(); break; case 65: //A :左 hero.moveLeft(); break; case 74: //J :发子弹 hero.shotEnemy(); break; } flashTankMap(); } //每隔100毫秒去刷新一次作战区 window.setInterval("flashTankMap()",100); </script> </body> </html>
The above is the content of Xiaoqiang’s HTML5 mobile development road (9)-Tank War Game 3. For more related content, please pay attention to the PHP Chinese website (www. php.cn)!