主要关注问题:
学好html5canvas标签画出各种图型 包括图片 文字 图形
画坦克 敌人坦克 子弹
画布 坦克战场 定时刷新
子弹何时死亡 如何实现子弹飞效果
如何移动坦克 包括方向
如何让坦克发射子弹 如何让子弹自己沿着坦克发射的方向飞 打中敌人或者飞到边界让其死亡
敌机如何自动发射子弹 如何随机移动
定时器定时画子弹 什么时候才不画(死亡) 如何取消该定时器
在js里面如何实现继承 :对象冒充
原文参照韩顺平html5自写 看完视频后参照思想自己写代码 后续待完善
-------------------html--------------------------
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body onkeydown="ManaPlay();"> <script type="text/javascript" src="tankGame.js"></script> <canvas id="gameMap" width="400px" height="300px" style="background-color: black" > </canvas> <span id="aa">数据</span> <script> var canvas = document.getElementById("gameMap"); //得到画布 var cxt = canvas.getContext("2d"); //英雄坦克颜色 敌人坦克颜色 var heroColor=new Array("#BA9658","#FEF26E"); var enmeyColor=new Array("#00A2B5","#00FEFE"); var hero = new Hero(30,230,0,heroColor); // var heroBullet = null; //定义一颗空子弹 var heroBullets = new Array();//定义子弹数组 var enemyBullets = new Array();//定义敌人的子弹 //敌人坦克 , var enemys = new Array(); for(var i=0;i<3;i++){ var Enemy = new EnemyTank((i+1)*50,0,1,enmeyColor); enemys[i]=Enemy; //启动这个敌人的坦克 window.setInterval("enemys["+i+"].run()",50); //当创建敌人坦克时就分配子弹 var eb=new Bullet(enemys[i].x+9,enemys[i].y+30,1,2.2,"enemy",enemys[i]); enemyBullets[i]=eb; //启动该子弹 var ettimer=window.setInterval("enemyBullets["+i+"].run()",50); enemyBullets[i].timer=ettimer; } //初始化坦克 flashTankMap(); /** * 接收用户按键函数 * @constructor */ function ManaPlay(){ //拿到玩家当前按下的键 查对应字母的ascii码 var code=event.keyCode; 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(); } /** * 坦克地图的刷新操作 */ function flashTankMap(){ //画布清理 cxt.clearRect(0,0,400,300,heroColor); //画自己的坦克 drawTank(hero); //画敌人的坦克 for(var i=0;i<enemys.length;i++){ var Enemy =enemys[i]; drawTank(Enemy); } drawHeroBullet(); drawEnemyBullet(); } window.setInterval("flashTankMap()",100); </script> </body> </html>
--------------js部分——------------------------------
/** * 坦克类 专门生产坦克 包括英雄的坦克和敌人的坦克 * @param x * @param y * @param direct * @param color * @constructor */ function Tank(x,y,direct,color){ this.x=x; this.y=y; this.color=color; this.direct=direct; this.speed=1; //速度 //上 0 this.MoveUp = function(){ this.y-=this.speed; this.direct=0; } //下 1 this.MoveDown =function(){ this.y+=this.speed; this.direct=1; } //左 2 this.MoveLeft = function(){ this.x-=this.speed; this.direct=2; } // 右 3 this.MoveRight = function(){ this.x+=this.speed; this.direct=3; } } /** * 定义一个hero类 表示自己的坦克 * 定义坦克的属性和其上下移动的方法 * @param x 横坐标 * @param y 纵坐标 * @param direct 坦克的方向 * @constructor Liu */ 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+9,this.y,this.direct,1,"hero",this); break; case 2: heroBullet=new Bullet(this.x,this.y+9,this.direct,1,"hero",this); break; case 3: heroBullet=new Bullet(this.x+30,this.y+9,this.direct,1,"hero",this); break; case 1: heroBullet=new Bullet(this.x+9,this.y+30,this.direct,1,"hero",this); break; } heroBullets.push(heroBullet); //调用我们的子弹run,让它自己跑 var timer=window.setInterval("heroBullets["+(heroBullets.length-1)+"].run()",50); //把这个timer赋给这个子弹 如果不要子弹了 就停止跑 (js对象是引用传递!) heroBullets[heroBullets.length-1].timer=timer; } } /** * 敌人坦克类 * @param x * @param y * @param direct * @param color * @constructor */ function EnemyTank (x,y,direct,color){ this.tank=Tank; this.tank(x,y,direct,color); this.bulletIsLive =true; //定义坦克子弹的状态 是否死亡 this.count = 0;// 坦克走了多少步 this.run = function run() { //判断敌人的坦克当前方向 switch (this.direct) { case 0: if (this.y > 0) { this.y -= this.speed; } break; case 3: if (this.x + 30 < 400) { this.x += this.speed; } break; case 1: if (this.y + 30 < 300) { this.y += this.speed; } break; case 2: if (this.x > 0) { this.x -= this.speed; } break; } //改变方向,走30次,再改变方向 if (this.count > 30) { this.direct = Math.round(Math.random() * 3);//随机生成 0,1,2,3 this.count = 0; } this.count++; //判断子弹是否已经死亡,如果死亡,则增加新的一颗子弹 if(this.bulletIsLive==false) { //增子弹,这是需要考虑当前这个敌人坦克的方向,在增加子弹 switch (this.direct) { case 0: etBullet=new Bullet(this.x+9,this.y,this.direct,2,"enemy",this); break; case 2: etBullet=new Bullet(this.x,this.y+9,this.direct,2,"enemy",this); break; case 3: etBullet=new Bullet(this.x+30,this.y+9,this.direct,2,"enemy",this); break; case 1: etBullet=new Bullet(this.x+9,this.y+30,this.direct,2,"enemy",this); break; } //把子弹添加到敌人子弹数组中 enemyBullets.push(etBullet); //启动新子弹run var mytimer = window.setInterval("enemyBullets[" + (enemyBullets.length - 1) + "].run()", 50); enemyBullets[enemyBullets.length - 1].timer = mytimer; this.bulletIsLive = true; } } } /** * 画坦克类 * @param tank */ function drawTank(tank){ //根据方向画坦克 switch (tank.direct){ case 0: case 1: cxt.fillStyle=tank.color[0]; //矩形 cxt.fillRect(tank.x,tank.y,5,30); cxt.fillRect(tank.x+15,tank.y,5,30); cxt.fillRect(tank.x+6,tank.y+5,8,20); //设置画笔的样式 画坦克的圆盖 cxt.fillStyle=tank.color[1]; cxt.beginPath(); cxt.arc(tank.x+10,tank.y+15,4,0,360,true); cxt.fill(); cxt.closePath(); //设置线条的颜色 画炮筒 cxt.strokeStyle=tank.color[1]; cxt.beginPath(); if(tank.direct==0){ cxt.moveTo(tank.x+10,tank.y+15); cxt.lineTo(tank.x+10,tank.y); }else if(tank.direct==1){ cxt.moveTo(tank.x+10,tank.y+15); cxt.lineTo(tank.x+10,tank.y+30); } cxt.closePath(); cxt.stroke(); break; case 2: case 3: cxt.fillStyle=tank.color[0]; //矩形 cxt.fillRect(tank.x,tank.y,30,5); cxt.fillRect(tank.x,tank.y+15,30,5); cxt.fillRect(tank.x+5,tank.y+6,20,8); //设置画笔的样式 画坦克的圆盖 cxt.fillStyle=tank.color[1]; cxt.beginPath(); cxt.arc(tank.x+15,tank.y+10,4,0,360,true); cxt.fill(); cxt.closePath(); cxt.strokeStyle=tank.color[1]; cxt.beginPath(); if(tank.direct==3){ cxt.moveTo(tank.x+15,tank.y+10); cxt.lineTo(tank.x+30,tank.y+10); }else if(tank.direct==2){ cxt.moveTo(tank.x+15,tank.y+10); cxt.lineTo(tank.x,tank.y+10); } cxt.closePath(); cxt.stroke(); break; } } /** * 子弹类 坐标 方向 类型 坦克 * @param x * @param y * @param direct * @param speed * @param type * @param tank * @constructor */ function Bullet(x,y,direct,speed,type,tank){ this.x=x; this.y=y; this.direct=direct; this.speed=speed; this.isLive = true; this.timer=null;//这个用来判断 子弹越界或者死亡就终止前进 this.type = type; this.tank = tank; this.run = function run(){ //在该表这个子弹的坐标时,我们先判断子弹是否已经到边界 if(this.x<=0||this.x>=400||this.y<=0||this.y>=300){ //子弹要停止. window.clearInterval(this.timer); //子弹死亡 this.isLive=false; if(this.type=="enemy"){ this.tank.bulletIsLive=false; } }else{ switch (this.direct){ case 0: this.y-=this.speed; break; case 1: this.y+=this.speed; break; case 2: this.x-=this.speed; break; case 3: this.x+=this.speed; break; } } document.getElementById("aa").innerText="子弹x="+this.x+" 子弹y="+this.y; } } /** * 画玩家自己坦克的子弹 如果有的话 */ 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 drawEnemyBullet(){ //现在要画出所有子弹 for( var i=0;i<enemyBullets.length;i++){ var etBullet=enemyBullets[i]; //这里,我们加入了一句话,但是要知道这里加,是需要对整个程序有把握 if(etBullet.isLive){ cxt.fillStyle="#00FEFE"; cxt.fillRect(etBullet.x,etBullet.y,2,2); } } }