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