用javascript寫星際飛機大戰游戲


在github里看到了個不錯的腳本游戲,決定親自動手來寫,效果如下

 

下面是代碼的思路分享

把整個代碼理解消化確實不容易,但是如果你堅持看完相信你一定會有收獲

如果沒興趣可以直接點擊下面的鏈接 復制代碼 開玩:

http://www.cnblogs.com/demonxian3/p/6241755.html

 

1丶首先准備好素材

游戲的元素有:飛機 敵機 子彈 背景 暫停

 

 

素材的大小可以通過drawImage()來改變其大小,因此不需要太糾結素材多少像素

 

創建一個html文件 和一個js文件 

然后開始編輯該html文件

 

2.寫一個畫布:

<canvas id="canvas" width=500 height=500 style="border:1px solid #c3c3c3"></canvas>

 

 

3.獲取畫布對象

canvas = document.getElementById('canvas') 

cxt = canvas.getContext('2d');

 

 

4.設置畫布屬性

復制代碼
var boxx=0

var boxy=0

var boxwidth=500

var boxheight=500
復制代碼

 

 

 

 **************************畫飛機****************************

 

5.聲明飛機相關的變量

飛機橫坐標 縱坐標 寬度 高度 這些都是為下面的drawImage做准備的

復制代碼
var planex;

var planey;

var planewidth=60;

var planeheight=60;

var planeImage = new Image();

planeImage.src="images/hero.jpg";  //引入圖片
復制代碼

 

6.布置飛機初始位置

planex = (boxwidth - planewidth) / 2   //畫布的中央

planey = boxheight - planeheight     //畫布的底端

因為這里的坐標(x,y)指的是飛機左上角的坐標,因此需要把飛機的長度算上 

 

 

7.畫出飛機

有了坐標和寬高就可以把飛機畫出來了

cxt.drawImage(planeImage,planex,planey,planewidth,planeheight);

 

現在可以打開網頁測試下,看看飛機是否畫出來了,

如果沒有畫出來,那么請別灰心,耐心的查一下有什么錯誤的地方

如果成功顯示出飛機了那么go on!

 

 

飛機畫出來了但是飛機不會動 

那么怎么能讓飛機動呢? 

改變其坐標!

那么什么時候動呢?

按下鍵盤上的 ↑ ↓ ← → 鍵的時候

我們知道鍵盤有個事件驅動 onkeydown

而這個事件驅動有個屬性keycode 

用這個屬性可以綁定上下左右鍵對應的函數

如下可以看到對應的keycode碼

 

下面是四個我們需要的按鍵的對應碼

左 : 37

上 : 38

右 : 39

下 : 40

 

光有事件驅動onkeydown還不夠,我們還需要實時監聽事件的發生

說的通俗點就是 你在任意時刻去按鍵盤 程序都能夠及時響應

下面這個函數就可以幫我們實時監聽事件

addEventListener()函數

語法

element.addEventListener( eventfunctionuseCapture)
 
參數解釋:
element    表示需要使用該方法的對象 
event        表示監聽什么事件  
function    表示監聽到事件后做出什么響應 
useCapture 表示在捕獲或冒泡執行 默認為false 我們就按照默認來
聲明一個運動跨度變量 這個變量的作用你馬上就能看到了
var sp=0;

 

 
8.監聽body元素 響應事件
下面四個if語句用來判斷飛機是否出界
 
復制代碼
body.addEventListener('keydown',function (event){
            switch(event.keyCode){
                case 37 : if(planex>boxx){sp=8}else{sp=0}planex-=sp;break;
                case 38 : if(planey>boxy){sp=8}else{sp=0}planey-=sp;break;
                case 39 : if((planex+planewidth)<boxwidth){sp=8}else{sp=0}planex+=sp;break;
                case 40 : if((planey+planeheight)<boxheight){sp=8}else{sp=0}planey+=sp;break;
                default:break;
            }
        },false)

 
復制代碼

 

到這里 你可以測試一下飛機是否可以動起來了

當然我會直接告訴你結果----不能動!!

因為上面的事件監聽改變的只是飛機的坐標,但是圖片還在原地

為了讓圖片跟着坐標動起來,我們需要寫一個函數

 

 

9.更新飛機圖片位置函數 

復制代碼
function drawplane(){

  cxt.clearRect(boxx,boxy,boxwidth,boxheight);                      //清除所有就元素

  cxt.drawImage(planeImage,planex,planey,planewidth,planeheight);  //重新畫出飛機

}
 

var fps                               //其實只是用來調飛機流暢度

var gameTimmer = setInterval (run,1000/fps);      //gameTimer是游戲的總驅動計時器

 

function run(){                           //drawplane函數自動運行

 drawplane();                      

}
復制代碼

 

 **************************畫子彈****************************

 

 10.設置子彈的相關變量 也是為drawImage函數的五個參數所做准備

復制代碼
var bulletx;

var bullety;

var bulletwidth=10;

var bulletheight=10;

var bulletImage=new Image();  

bulletImage.src="images/bullet.png"
復制代碼

 

 

11.存放子彈的彈夾-----數組

用數組來存放子彈方便我們訪問每個子彈對象

var herobullet;                    //用來表示單個子彈

var allbullets = new Array();      //用來表示所有子彈

 

12.設置子彈初始位置

我們希望 每顆子彈的起始位置是隨着飛機而改變的 因此把飛機的變量引進來

bulletx=planex+planewidth/2

bullety=planey+bulletheight

 

13.聲明子彈的構造函數、

這部分有點難理解 也是本代碼的難點

下面聲明的構造函數是用來制作子彈的

 

復制代碼
function bullet(x,y){

this.x=x;                //子彈橫坐標

this.y=y;          //子彈縱坐標

this.islive=true;       //子彈存活屬性

this.timmer=null;     //子彈計時器 用來使得子彈自己運動

    this.run = function run(){    //子彈的運動方法

       if(this.islive==false||this.y<-10){  //判斷子彈是否存活或出界

       clearInterval(this.timmer);  //停止運動

    this.islive=false;

        }else{

        this.y-=20           //讓子彈往上飛

    }

    }

}
復制代碼

 

 14.生產子彈

 有了做子彈的秘方 那么就可以開始制造子彈了

 在這里可以使用到我們之前定義的數組存放每顆子彈

復制代碼
function producebullet(){

  herobullet = new bullet(bulletx,bullety);  //生產子彈
 
  allbullets.push(herobullet);  //存放子彈

  var timmer = setInterval("allbullets[" + (allbullets.length-1) +"].run()" , 50); //設置子彈子彈運行 這里用到eval可以將字符變為有效方法 

  allbullets[allbullets.length-1].timmer=timmer;  //將自動運行的子彈方法賦予到子彈的屬性

}
復制代碼

 

15.畫出子彈

同飛機的道理相同:光改變坐標是看不出效果,還需要把圖片位置也更新了

復制代碼
function  drawbullet(){

  for (var i=0;i<allbullets.length;i++){ //遍歷每顆子彈

  if(allbullets[i].islive){  //如果子彈掛了 就不需要再畫出來了

  cxt.drawImage(bulletImage,allbullets.x,allbullets.y,bulletwidth,bulletheight);

  }

  }

}
復制代碼

 

 16.讓drawbullet函數自動運行

然后把drawbullet函數 放到之前定義的run函數里 不是子彈的方法

復制代碼
function run(){

  drawplane();

  drawbullet();

}
復制代碼

 

17.讓子彈自動生產

給生產子彈的函數加個計時器

btimmer = setInterval(producebullet,500)

 

 **************************畫敵機****************************

我們來回顧下畫子彈的步驟

 

設置相關屬性 ->  確定初始坐標 -> 子彈構造函數 ->  生產子彈 -> 畫出子彈 -> 自動生產和繪畫

 

畫敵機的步驟和上面的步驟是一樣的

 

但是有個不同的點 那就是敵機初始的橫坐標應該是隨機的  而縱坐標都是0 (頂部位置)

 

說到隨機 Math.random()函數 是不可以缺少的

但這個只能產生0~1的隨機數

因此 Math.random*500   范圍就是0~500范圍

最后四拾伍入   Math.ceil(Math.random*500);

 

18.設置敵機的相關屬性

 

復制代碼
var enemyx;
var enemyy;
var enemywidth=30
var enemyheight=30
var allenemys = new Arr(); //和子彈一樣 數組用來存放所有敵機
var heroenemy; //用來表示其中單個敵機
var enemyImage= new Image();
enemyImage.src="images/enemy.png"
復制代碼

 

 

19.敵機構造函數

 

復制代碼
//構造函數
//下面基本上和子彈差不多 就不解釋了
function enemy(x,y){

  this.x=x;

  this.y=y;

  this.islive=true;

  this.timmer=null;

  this.run = function run(){

   if (this.islive==false||this.y>boxheight){

   clearInterval(this.timmer);

   this.islive=false;

   }else{

   this.y+=2.5;   

   }

  }

}

復制代碼

20生產敵機

 

復制代碼
//生產隨機位置的敵機

function produceenemy(){

  enemyx=Math.ceil(Math.random()*500);  //產生隨機初始位

  enemyy=33;                            //在畫布頂端產生敵機

  heroenemy = new enemy(enemyx,enemyy);  //生產敵機

  allenemys.push(heroenemy);            //加入數組

  var timmer = setInterval("allenemys[" + (allenemys.length-1) + "].run()"); //啟動run函數並使其自動運行

  allenemys[allenemys.length-1].timmer=timmer;   //run函數賦予在enemy屬性

}

 
復制代碼

 

21畫出敵機

復制代碼
//畫出敵機

function drawenemy(){

  for (var i=0;i<allenemys.length;i++){

  if(allenemys[i].islive){

   cxt.drawImage(enemyImage,allenemys[i].x,allenemys[i].y,enemywidth,enemyheight)

  }

 }

}
復制代碼

 

 

22自動生產敵機 更新敵機

最后把 drawenemy 加入run函數里  給produeenemy 加個計時器

復制代碼
function run(){

  drawplane();

  drawbullet();

  drawenemy();

}
 
         

etimmer = setInterval(produceenemy,800);

 
         
復制代碼

 

 **************************擊中敵機****************************

飛機 敵機  子彈 都畫好了 而且都可以動起來了 , 現在來寫子彈碰到敵機時敵機消失的規則

 

上圖可以清晰的看出子彈擊中敵機的范圍

擊中條件:

bulletx + bulletwidth > enemyx

bulletx < enemyx + enemywidth

bullety < enemyy + enemyheight

復制代碼
function checkbullet{

  for(var i=0;i<allenemys.length;i++){  //遍歷敵機

    if (allenemys[i].islive){

    var e = allenemys[i];              //獲取敵機對象

    }

    for(var j=0;j<allbullets.length;j++){  //遍歷

      if(allbullets[j].islive){

        var b = allbullets[j];

        if(b.x+b.width>e.x&&b.x<e.x+e.width&&b.y<e.y+e.height){ //這里使用到上面的規則

          b.islive=false;  //在構造函數里只要islive的屬性為假 就會停止run函數的計時器

          e.islive=false;  //因此子彈和敵機相關計時器都被clear掉了

          score+=100;  //加分

        }

      }

    }

  }

}
復制代碼

 

**************************擊中我機****************************

我機的死亡的規則:

 

 

擊中條件:

enemyx+enemywidth > planex

enemyx < planex + planewidth

enemyy + enemyheight > planey

 

復制代碼
function checkenemy(){

  for(var i=0;i<allenemys[i].length;i++){

        if(allenemys[i].islive){

      var e = allenemys[i];

      if(e.x+e.width > planex && e.x < planex + planewidth && e.y + e.height > planey){

        e.islive=false;

        stop();

      }

    }

     }

}
復制代碼

 

 **************************停止一切****************************

然后把stop函數寫出來

復制代碼
function stop(){

  clearInterval(btimmer);    //停止生產子彈

  clearInterval(etimmer);    //停止生產敵機

  clearInterval(gameTimmer);    //停止游戲

  allenemys.length=0;        //初始化

  allbullets.length=0;      //初始化

  show.innerHTML=score;       //統計總分

  score=0;

}
復制代碼

 

 **************************啟動一切****************************

然后把checkbullet函數 和checkenemy函數 放到游戲驅動run 里頭

復制代碼
function run(){

  drawplane();  //畫飛機

  drawenemy();  //畫敵機

  drawbullet();  //畫子彈

  checkbullet(); //檢查子彈

  checkenemy();  //檢查敵機

  drawscore();  //實時加分

}
復制代碼

 

 

最后設置一下加分相關的標簽

這個標簽用來顯示當前分數

<div style="position: absolute;top: 90px;left: 30px;
font-weight: bold;font-size: 40px;color:cornflowerblue"> <span id="show">0</span></div>

 

 

獲取標簽

show = document.getElementById('show');

 

 

實時計分

function drawscore(){

  show.innerHTML=score;

}

 

 

當然還可以加一些小細節,比如暫停按鈕 彈出窗口統計得分

還可以玩好玩的,比如飛機無敵 無限子彈 超級子彈 無敵並排子彈 總之你自己想怎么改都行

源代碼:http://www.cnblogs.com/demonxian3/p/6241755.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM