Html 5 坦克大戰(韓順平版本)
html 5代碼部分如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> </head> <body onkeydown="getCommand();"> <h1>hmtl5-經典的坦克大戰</h1> <!--坦克大戰的戰場--> <canvas width="400px" height="300px" ></canvas> <span >數據</span> <!--把tankGames.js引入到本頁麵--> <script type="text/javascript" src="tankGame7.js"></script> <script type="text/javascript"> //得到畫布 var canvas1=document.getElementById("tankMap"); //得到繪圖上下文(你可以理解是畫筆) var cxt=canvas1.getContext("2d"); //我的坦克 hero //方向 var hero=new Hero(140,140,0,heroColor); //定義子彈數組 var heroBullets=new Array(); //定義敵人的坦克(敵人的坦克有多少? 思路 : 是單個單個的定義,還是放在數組中?) var enemyTanks=new Array(); //定義敵人子彈的數組 var enemyBullets=new Array(); //定義一個炸彈數組(可以存放很多炸彈,) var bombs=new Array(); //先死後活 ,定3個,後麵我們把敵人坦克的數量,作出變量 //0->上, 1->右, 2->下 3->左 for(var i=0;i<3;i++){ //創建一個坦克 var enemyTank=new EnemyTank((i+1)*50,0,2,enmeyColor); //把這個坦克放入數組 enemyTanks[i]=enemyTank; //啟動這個敵人的坦克 window.setInterval("enemyTanks["+i+"].run()",50); //當創建敵人坦克時就分配子彈 var eb=new Bullet(enemyTanks[i].x+9,enemyTanks[i].y+30,2,1.2,"enemy",enemyTanks[i]); enemyBullets[i]=eb; //啟動該子彈 var ettimer=window.setInterval("enemyBullets["+i+"].run()",50); enemyBullets[i].timer=ettimer; } //先調用一次 flashTankMap(); //專門寫一個函數,用於定時刷新我們的作戰區,把要在作戰區出現的元素(自己坦克,敵人坦克,子彈,炸彈, //障礙物...)->遊戲思想 function flashTankMap(){ //把畫布清理 cxt.clearRect(0,0,400,300); //我的坦克 drawTank(hero); //畫出自己的子彈 //子彈飛效果是怎麼出現的?[答 : 首先我們應該每隔一定時間(setInterval)就去刷新作戰區,如果在刷新的時候,子彈坐標變換了,給人的感覺就是子彈在飛!] drawHeroBullet(); //敵人的坦克 //判斷一下敵人坦克是否擊中 isHitEnemyTank(); drawEnemyBomb(); drawEnemyBullet(); //畫出所有敵人坦克 for(var i=0;i<3;i++){ drawTank(enemyTanks[i]); } } //這是一個接受用戶按鍵函數 function getCommand(){ //我怎麼知道,玩家按下的是什麼鍵 //說明當按下鍵後 事件--->event對象----->事件處理函數() var code=event.keyCode;//對應字母的ascii碼->我們看碼表 switch(code){ case 87://上 hero.moveUp(); break; case 68: hero.moveRight(); break; case 83: hero.moveDown(); break; case 65: hero.moveLeft(); break; case 74: hero.shotEnemy(); break; } //觸發這個函數 flashTankMap(); flashTankMap(); //重新繪製所有的敵人的坦克.你可以在這裏寫代碼(思想,我們幹脆些一個函數,專門用於定時刷新我們的畫布[作戰區]) } //每隔100毫秒去刷新一次作戰區 window.setInterval("flashTankMap()",100); </script> </body> </html>javascript部分代碼如下:
//為了編程方便,我們定義兩個顏色數組 var heroColor=new Array("#BA9658","#FEF26E"); var enmeyColor=new Array("#00A2B5","#00FEFE"); //其它的敵人坦克,這裏的擴展性,還是不錯的. //定義一個炸彈類 function Bomb(x,y){ this.x=x; this.y=y; this.isLive=true; //炸彈是否活的,默認true; //炸彈有一個生命值 this.blood=9; //減生命值 this.bloodDown=function(){ if(this.blood>0){ this.blood--; }else{ //說明炸彈死亡 this.isLive=false; } } } //子彈類 //type表示:這顆子彈是敵人的,還是自己的 //tank表示對象,說明這顆子彈,屬於哪個坦克. function Bullet(x,y,direct,speed,type,tank){ this.x=x; this.y=y; this.direct=direct; this.speed=speed; this.timer=null; this.isLive=true; this.type=type; this.tank=tank; this.run=function run(){ //在該表這個子彈的坐標時,我們先判斷子彈是否已經到邊界 //子彈不前進,有兩個邏輯,1.碰到邊界,2. 碰到敵人坦克. if(this.x<=0||this.x>=400||this.y<=0||this.y>=300||this.isLive==false){ //子彈要停止. 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.x+=this.speed; break; case 2: this.y+=this.speed; break; case 3: this.x-=this.speed; break; } } document.getElementById("aa").innerText="子彈x="+this.x+" 子彈y="+this.y; } } //這是一個Tank類 function Tank(x,y,direct,color){ this.x=x; this.y=y; this.speed=1; this.isLive=true; 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類 //x 表示坦克的 橫坐標, y 表示縱坐標, direct 方向 function Hero(x,y,direct,color){ //下麵兩句話的作用是通過對象冒充,達到繼承的效果 this.tank=Tank; this.tank(x,y,direct,color); //增加一個函數,射擊敵人坦克. this.shotEnemy=function(){ //創建子彈, 子彈的位置應該和hero有關係,並且和hero的方向有關.!!! //this.x 就是當前hero的橫坐標,這裏我們簡單的處理(細化) switch(this.direct){ case 0: heroBullet=new Bullet(this.x+9,this.y,this.direct,1,"hero",this); break; case 1: heroBullet=new Bullet(this.x+30,this.y+9,this.direct,1,"hero",this); break; case 2: heroBullet=new Bullet(this.x+9,this.y+30,this.direct,1,"hero",this); break; case 3: //右 heroBullet=new Bullet(this.x,this.y+9,this.direct,1,"hero",this); break; } //把這個子彈對象放入到數組中 -> push函數 heroBullets.push(heroBullet); //調用我們的子彈run, 50 是老師多次測試得到的一個結論., 這裏技術難度比較大. //就算你工作過1-2年,你也未必想到, 下麵啟動方式,每個子彈的定時器是獨立,如果按原來的方法 //則所有子彈共享一個定時器. var timer=window.setInterval("heroBullets["+(heroBullets.length-1)+"].run()",50); //把這個timer賦給這個子彈(js對象是引用傳遞!) heroBullets[heroBullets.length-1].timer=timer; } } //定義一個EnemyTank類 function EnemyTank (x,y,direct,color){ //也通過對象冒充,來繼承Tank this.tank=Tank; this.count=0; this.bulletIsLive=true; this.tank(x,y,direct,color); this.run=function run(){ //判斷敵人的坦克當前方向 switch(this.direct){ case 0: if(this.y>0){ this.y-=this.speed; } break; case 1: if(this.x+30<400){ this.x+=this.speed; } break; case 2: if(this.y+30<300){ this.y+=this.speed; } break; case 3: 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,1,"enemy",this); break; case 1: etBullet=new Bullet(this.x+30,this.y+9,this.direct,1,"enemy",this); break; case 2: etBullet=new Bullet(this.x+9,this.y+30,this.direct,1,"enemy",this); break; case 3: //右 etBullet=new Bullet(this.x,this.y+9,this.direct,1,"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; } } } //畫出自己的子彈,多說一句,你也可以把該函數封裝到Hero類中 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); } } } //繪製坦克(敵人坦克和自己的坦克) function drawTank(tank){ //說明所有的坦克都要isLive這個屬性 if(tank.isLive){ //考慮方向 switch(tank.direct){ case 0: //上 case 2:// 下 //畫出自己的坦克,使用前麵的繪圖技術 //設置顏色 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.arc(tank.x+10,tank.y+15,4,0,360,true); cxt.fill(); //畫出炮筒(直線) cxt.strokeStyle=tank.color[1]; //設置線條的寬度 cxt.lineWidth=1.5; cxt.beginPath(); cxt.moveTo(tank.x+10,tank.y+15); if(tank.direct==0){ cxt.lineTo(tank.x+10,tank.y); }else if(tank.direct==2){ cxt.lineTo(tank.x+10,tank.y+30); } cxt.closePath(); cxt.stroke(); break; case 1: //右和左 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.arc(tank.x+15,tank.y+10,4,0,360,true); cxt.fill(); //畫出炮筒(直線) cxt.strokeStyle=tank.color[1]; //設置線條的寬度 cxt.lineWidth=1.5; cxt.beginPath(); cxt.moveTo(tank.x+15,tank.y+10); //向右 if(tank.direct==1){ cxt.lineTo(tank.x+30,tank.y+10); }else if(tank.direct==3){ //向左 cxt.lineTo(tank.x,tank.y+10); } cxt.closePath(); cxt.stroke(); break; } } } //編寫一個函數,專門用於判斷我的子彈,是否擊中了某個敵人坦克 function isHitEnemyTank(){ //取出每顆子彈 for(var i=0;i<heroBullets.length;i++){ //取出一顆子彈 var heroBullet=heroBullets[i]; if(heroBullet.isLive){ //子彈是活的,才去判斷 //讓這顆子彈去和遍曆每個敵人坦克判斷 for(var j=0;j<enemyTanks.length;j++){ var enemyTank=enemyTanks[j]; if(enemyTank.isLive){ //子彈擊中敵人坦克的條件是什麼? 很多思路 , 韓老師的思想是 //(看看這顆子彈,是否進入坦克所在矩形) //根據當時敵人坦克的方向來決定 switch(enemyTank.direct){ case 0: //敵人坦克向上 case 2://敵人坦克向下 if(heroBullet.x>=enemyTank.x&&heroBullet.x<=enemyTank.x+20 &&heroBullet.y>=enemyTank.y&&heroBullet.y<=enemyTank.y+30){ //把坦克isLive 設為false ,表示死亡 enemyTank.isLive=false; //該子彈也死亡 heroBullet.isLive=false; //創建一顆炸彈 var bomb=new Bomb(enemyTank.x,enemyTank.y); //然後把該炸彈放入到bombs數組中 bombs.push(bomb); } break; case 1: //敵人坦克向右 case 3://敵人坦克向左 if(heroBullet.x>=enemyTank.x&&heroBullet.x<=enemyTank.x+30 &&heroBullet.y>=enemyTank.y&&heroBullet.y<=enemyTank.y+20){ //把坦克isLive 設為false ,表示死亡 enemyTank.isLive=false; heroBullet.isLive=false; //創建一顆炸彈 var bomb=new Bomb(enemyTank.x,enemyTank.y); //然後把該炸彈放入到bombs數組中 bombs.push(bomb); } break; } } }//for } } } //畫出敵人炸彈 function drawEnemyBomb(){ for(var i=0;i<bombs.length;i++){ //取出一顆炸彈 var bomb=bombs[i]; if(bomb.isLive){ //更據當前這個炸彈的生命值,來畫出不同的炸彈圖片 if(bomb.blood>6){ //顯示最大炸彈圖 var img1=new Image(); img1.src="bomb_1.gif"; var x=bomb.x; var y=bomb.y; img1.onload=function(){ cxt.drawImage(img1,x,y,30,30); } }else if(bomb.blood>3){ var img2=new Image(); img2.src="bomb_2.gif"; var x=bomb.x; var y=bomb.y; img2.onload=function(){ cxt.drawImage(img2,x,y,30,30); } }else { var img3=new Image(); img3.src="bomb_3.gif"; var x=bomb.x; var y=bomb.y; img3.onload=function(){ cxt.drawImage(img3,x,y,30,30); } } //減血 bomb.bloodDown(); if(bomb.blood<=0){ //怎麼辦?把這個炸彈從數組中去掉 bombs.splice(i,1); } } } }代碼下載地址:https://download.csdn.net/detail/xunzaosiyecao/7847405
最後更新:2017-04-03 05:40:09