1. 程式人生 > >HTML5+JS實現坦克大戰小遊戲

HTML5+JS實現坦克大戰小遊戲

   聽了韓順平老師的視訊教程,學到了不少程式設計思想,原來看似簡單的坦克大戰小遊戲寫起來其實並不簡單。這裡總結一下這幾天學到的東西。

        首先是關於html5的知識了。這裡我們基本上只用了畫布canvas來畫坦克,還有就是html5的第一行<!DOCTYPE html>來說明這是一個使用html5寫的頁面,html5的特性之一就包括canvas,這是html中沒有的標籤。

        另外一個就是js了,涉及到的語法都是最簡單、最基本的用法,這在程式碼中進行解釋。同時,韓老師在這個視訊中程式碼有個bug就是敵人坦克在死後依然會發子彈,小弟在此進行了修正。

       接下來最重要的就是我們要來分析一下坦克大戰小遊戲的設計思路:

       1、要有作戰區域,這有canvas 可以幫我們解決。

       2、要有坦克,包括自己的、敵人的。

       3、要能有子彈,包括自己的、敵人的。

       4、要有炸彈。

       5、我的坦克要能按鍵發射子彈,敵人的坦克要能連續自動發射子彈。

       6、我的子彈打到敵人時子彈要消失,同時敵人爆炸並消失,不能再發子彈。

       以上是遊戲設計的簡單思路,這是初步設計,接下來以程式碼來分析詳細的設計過程:

       步驟一:

          組織程式碼,為了程式碼易讀,而且我使用的是html5+js來實現,自不必多說,使用tankGame.js+tankGame.html來組織我的程式碼,js用於類以及方法的實現過程,html實現函式呼叫以及網頁的顯示。

       步驟二:設計作戰區域:

         code 1 from tankeGame.html

<canvas id="tankMap" width="500px" height="500px" style="background-color:black"></canvas>
<pre class="html" name="code"><script type="text/javascript">

	//得到畫布
	var canvas1=document.getElementById("tankMap");
	//獲得畫圖工具
	var cxt=canvas1.getContext("2d");</script>
<script type="text/javascript">
	//得到畫布
	var canvas1=document.getElementById("tankMap");
	//得到繪圖上下文(你可以理解是畫筆)
	var cxt=canvas1.getContext("2d");</script>

     步驟三:畫坦克,包括自己的和敵人的:

// 基類,裡面有基本的共有屬性和方法
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和EnemyTanke繼承自基類。注意繼承的方法。

//定義一個Hero類
	//x 表示坦克的 橫座標, y 表示縱座標, direct 方向	
	function Hero(x,y,direct,color){
	
		//繼承的方法和格式,tank其實就是一個物件
		this.tank=Tank;
		this.tank(x,y,direct,color);

		//增加一個私有函式,射擊敵人坦克.
		this.shotEnemy=function(){
			
			//建立子彈, 子彈的位置應該和hero有關係,並且和hero的方向有關
			switch(this.direct){
				case 0:
				heroBullet=new Bullet(this.x+9,this.y,this.direct,3,"hero",this);
				break;
				case 1:
				heroBullet=new Bullet(this.x+30,this.y+9,this.direct,3,"hero",this);
				break;
				case 2:
				heroBullet=new Bullet(this.x+9,this.y+30,this.direct,3,"hero",this);
				break;
				case 3: //右
				heroBullet=new Bullet(this.x,this.y+9,this.direct,3,"hero",this);
				break;
			}

			//把這個子彈物件放入到陣列中	 -> push函式
			heroBullets.push(heroBullet);
			//定時器.
			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.qetBullet=null;
  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;
   }
   //改變方向,走50次,再改變方向
   if(this.count>50){
    this.direct=Math.round(Math.random()*3);//隨機生成 0,1,2,3
    this.count=0;
   }
   this.count++;
   //判斷敵人坦克是否還活著
   //if(this.tank.isLive==true){
   //判斷子彈是否已經死亡,如果死亡,則增加新的一顆子彈
   if(this.bulletIsLive==false){
    //增子彈,這是需要考慮當前這個敵人坦克的方向,在增加子彈
     switch(this.direct){
      case 0:
       qetBullet=new Bullet(this.x+9,this.y,this.direct,3,"enemy",this);
      break;
      case 1:
       qetBullet=new Bullet(this.x+30,this.y+9,this.direct,3,"enemy",this);
      break;
      case 2:
       qetBullet=new Bullet(this.x+9,this.y+30,this.direct,3,"enemy",this);
      break;
      case 3: //右
      qetBullet=new Bullet(this.x,this.y+9,this.direct,3,"enemy",this);
      break;
        }</p><p>    //把子彈新增到敵人子彈陣列中
    enemyBullets.push(qetBullet);
    //啟動新子彈run
    var mytimer=window.setInterval("enemyBullets["+(enemyBullets.length-1)+"].run()",50);
    enemyBullets[enemyBullets.length-1].timer=mytimer;</p><p>    this.bulletIsLive=true;
   }
  }
 
//繪製坦克(敵人坦克和自己的坦克)
	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;

			}
		}
	}

步驟四:畫子彈:

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>=500||this.y<=0||this.y>=500||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;
				}
			}

	}
}
//Bullet只是一個類,並沒有畫坦克的方法,需要我們自己設計,draw一個
<pre class="javascript" name="code">//畫出自己的子彈
		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 j=0;j<enemyTanks.length;j++){
					
    var enemyTank=enemyTanks[j];
						
    if(enemyTank.isLive==true){
       for( var i=0;i<enemyBullets.length;i++){
       var etBullet=enemyBullets[i];
       if(etBullet!=null&&etBullet.isLive){
	   cxt.fillStyle="#00FEFE";
	   cxt.fillRect(etBullet.x,etBullet.y,2,2);
	}
       } 
     }	
   }
}    	
<p>步驟五:檢測判斷自己的坦克是否擊中敵人坦克。</p><pre class="javascript" name="code">//編寫一個函式,專門用於判斷我的子彈,是否擊中了某個敵人坦克
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 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;
		}
	}
}

//畫出敵人炸彈 
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="picture/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="picture/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="picture/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);

			}
		}
	}
}

步驟七:響應鍵盤事件

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;
		}


步驟八:頁面重新整理:

//專門寫一個函式,用於定時重新整理我們的作戰區,把要在作戰區出現的元素(自己坦克,敵人坦克,子彈,炸彈,
	//障礙物...)->遊戲思想
	function flashTankMap(){
		
		//把畫布清理
		cxt.clearRect(0,0,500,500); 

		//我的坦克
		drawTank(hero);

		//畫出自己的子彈
		//子彈飛效果是怎麼出現的?[答 : 首先我們應該每隔一定時間(setInterval)就去重新整理作戰區,如果在重新整理的時候,子彈座標變換了,給人的感覺就是子彈在飛!]
		drawHeroBullet();

		//敵人的坦克
		//判斷一下敵人坦克是否擊中
		isHitEnemyTank();
		drawEnemyBomb();
		drawEnemyBullet();
		
		//畫出所有敵人坦克
		for(var i=0;i<3;i++){
			drawTank(enemyTanks[i]);
		}
			
	}


總結:坦克大戰小遊戲雖小但是涉及到的內容和思想卻不少,在學習程式設計的過程中慢慢的體會程式設計思想非常重要。在此非常感謝韓順平老師的視訊!!!

相關推薦

HTML5+JS實現坦克大戰遊戲

   聽了韓順平老師的視訊教程,學到了不少程式設計思想,原來看似簡單的坦克大戰小遊戲寫起來其實並不簡單。這裡總結一下這幾天學到的東西。         首先是關於html5的知識了。這裡我們基本上只用了畫布canvas來畫坦克,還有就是html5的第一行<!DOCTY

C++練習例項———控制檯程式碼實現坦克大戰遊戲

    坦克大戰是一款經典的遊戲,今天我來介紹一個在vs中僅用控制檯程式碼實現的坦克大戰小遊戲,在很多學校裡作為一個面對物件程式設計的大作業,對於學習C++的多型性很有幫助。程式的架構思路由老師提供,遊戲中用到了EasyX圖形庫,這個庫非常小巧輕便,下載地址:https://

原生JS實現的h5遊戲-植物大戰僵屍

完成後 資源 life css lan posit 獲得 抽象 dom 代碼地址如下:http://www.demodashi.com/demo/12755.html 項目介紹 本項目是利用原生js實現的h5小遊戲-植物大戰僵屍,主要結合了一下自己對於h5小遊戲的理解,

坦克大戰遊戲 版本號v1.10

python 初階 ''' v1.10 實現子彈的移動與消失 ''' import pygame,time,random SCREEN_WIDTH = 900 SCREEN_HEIGHT = 550 VERSION = 'V1.10' # v1.07新增 記錄敵

Python 坦克大戰遊戲進階 版本號v1.14

python初階 ''' v1.14 實現牆壁類 以及 子彈與牆壁的碰撞 ''' import pygame,time,random SCREEN_WIDTH = 900 SCREEN_HEIGHT = 550 VERSION = 'V1.14' # v1.0

python t坦克大戰遊戲程序 版本號v1.16

python 初階 ''' v1.16 實現音效類 ''' import pygame,time,random SCREEN_WIDTH = 900 SCREEN_HEIGHT = 550 VERSION = 'V1.16' # v1.07新增 記錄敵方坦克的數

js實現猜數字遊戲

用js實現簡易的猜數字小遊戲<head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body>     

js實現猜數字遊戲

//很好玩的遊戲哦,可以看看你的智商 是否驚人額 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transi

Javascript實現飛機大戰遊戲

原始碼地址:https://github.com/markLijun/planeWar 最近看到一個用JS寫的坦克大戰小遊戲,覺得好神奇,於是自己嘗試著寫了一個飛機大戰。 敵機類 function Enemy(x, y) this.x = x; this.y = y;

用html+css+js實現中國象棋遊戲開發專案

var game={ RN:10,//行數 CN:9,//列數 CSIZE:40,//每個單元格大小 OFFSET:20,//單元格區域距離最外層邊界的距離, URL:"images/chess.png",//儲存所有棋子的圖片地址 data:null,//實時儲存棋盤中棋子的物件 chessP

坦克大戰遊戲關鍵技術總結

        這兩天參照韓順平的坦克大戰遊戲並在其基礎上初步完善成一個小的頁面遊戲,最終js程式碼大約570行,html程式碼200多行,具體可參見https://github.com/Mrkaiyang/Art/tree/gh-pages/tank。主要實現了以下功能:

用JavaSE寫一個坦克大戰遊戲

俗話說千里之行始於足下,由於自己的程式設計基礎太差,學完JavaSE之後又沒有做過什麼小專案練練手,所以打算通過這個小專案來練練手,鍛鍊鍛鍊自己的程式設計基礎。預計學習時間將在一週之內。通過這個部落格來記錄構築這個小遊戲的每一步。

Python:用Pygame實現飛機大戰遊戲

2、開啟main.py檔案,寫入程式碼。 # main.py import pygame import sys import traceback import myplane import enemy import bullet imp

[原始碼分享]基於Python的Pygame庫實現的仿微信遊戲中的飛機大戰遊戲

不知大家是否還記得當時微信上風靡一時的打飛機小遊戲,通過控制我方飛機的上下左右移動,發射子彈來擊毀敵機,增加得分。這是一款簡單操作易上手又很有趣味性的遊戲,我使用python作為基本語言,利用pygame仿照微信版本完成了這款低配版飛機大戰遊戲。   我方飛機會按時的不斷髮射子彈,玩家通過上下左

[原始碼和文件分享]基於Python的Pygame庫實現的仿微信遊戲中的飛機大戰遊戲

不知大家是否還記得當時微信上風靡一時的打飛機小遊戲,通過控制我方飛機的上下左右移動,發射子彈來擊毀敵機,增加得分。這是一款簡單操作易上手又很有趣味性的遊戲,我使用python作為基本語言,利用pygame仿照微信版本完成了這款低配版飛機大戰遊戲。 我方飛機會按時的不斷髮射子彈,玩家通過上下左右的方向鍵來躲避

[HTML5]用JS實現當年瘋魔IOS遊戲市場的切水果

切水果遊戲曾經是一款風靡蘋果手機的休閒遊戲,今天要介紹的就是一款網頁版的切水果遊戲,由JavaScript和HTML5實現,雖然功能和原版的相差很大,但是基本的功能還是具備了,還是模仿挺逼真的。有一定JavaScript水平的朋友可以看看原始碼,相信你的JavaScript水

基於原生JS坦克大戰遊戲

主要含有以下功能:1、玩家採用等級機制,共5級;2、補充裝備有子彈、金星、炸彈、導彈、手槍、戰艦,分值各不相同;3、打掉障礙可加分;4、用滑鼠控制子彈射擊,左鍵為單發射擊、右鍵為雙發射擊,遮蔽滑鼠右鍵預設的選單;5、空格鍵控制導彈射擊,遮蔽其他鍵的使用;6、沒有戰艦的情況下無

網頁HTML5--飛機大戰遊戲開發--canvas的應用

一,概述 此小專案,是用來練習HTML5的canvas的程式設計運用。在這個專案中,我們需要建立一個可執行的網頁小遊戲,開發此小遊戲並不難,大概如下圖所示: 在整個遊戲的執行中,總共要分為5個狀態(state)去實現,分別是首頁(START),載入中(STARTING)

【Java_專案篇】--JAVA實現坦克大戰遊戲--坦克發射子彈(三)

前期相關文章 一、任務需求 新增hero坦克子彈並且發射。 二、思路 1.建立子彈類 1.由於每顆子彈都是一個獨立的執行緒,會不斷變換子彈座標,所以子彈類要實現Runnable介面。 2.子彈需要座標x,y以及方向,所以建構函式有三個引數。

HTML5+JavaScript製作坦克大戰遊戲——學習筆記三

1.接《HTML5+JavaScript製作坦克大戰遊戲——學習筆記二》 解決了以下問題: 1)可以同時傳送多顆子彈 2)在第一顆子彈消亡之前傳送第二顆子彈,第一顆子彈不會消失 示例程式碼:(TankBattle.html) <!DOCTYPE html> &