用javascript 面向對象製做坦克大戰(三)

  以前,咱們完成了坦克的移動和地圖的繪製,此次咱們來完成碰撞檢測和炮彈的發射。

 

  上代碼前來張最新的類圖:javascript

 

3. 碰撞檢測

    前面咱們已經完成了坦克的移動和地圖的繪製,下面咱們開始寫碰撞檢測。

3.1    建立碰撞檢測對象

        咱們建立一個對象來作碰撞檢測,因爲碰撞檢測都是在對象移動的時候進行的因此咱們讓Mover繼承咱們的碰撞對象。
 
HitTestObject.js:
 
 1 // 碰撞檢測對象 繼承自頂級對象
 2 HitTestObject = function () { }
 3 
 4 HitTestObject.prototype = new TankObject();
 5 // 碰撞檢測 參數爲地圖對象 返回true則不能移動
 6 HitTestObject.prototype.HitTest = function (battleField) {
 7 
 8     var nextObj = this.GetNextBattleFieldCell(battleField);
 9     if (nextObj == null) {
10         return true;// 場景越界
11     }
12     // 檢測是不是障礙物
13     if (nextObj.obj instanceof Barrier) {
14 
15         if (nextObj.obj instanceof EmptyB) {
16             // 判斷是否被其餘坦克佔用  Tank繼承自Mover
17             return nextObj.occupier instanceof Mover;
18         }
19         return !nextObj.obj.CanAcross;
20     }
21 
22 
23 }
24 
25 // 返回對象移動下個位置的地圖對象
26 HitTestObject.prototype.GetNextBattleFieldCell = function (battleField) {
27 
28     if (this.Direction == EnumDirection.Up && this.YPosition == 0 ||
29         this.Direction == EnumDirection.Down && this.YPosition == 12 ||
30         this.Direction == EnumDirection.Left && this.XPosition == 0 ||
31         this.Direction == EnumDirection.Right && this.XPosition == 12
32         ) {
33         return null;/* 場景越界 */
34     }
35 
36     var y = this.YPosition;
37     var x = this.XPosition;
38     var nextAxes = this.GetNextAxes(x, y);
39     return battleField[nextAxes.y][nextAxes.x];
40 }
41 
42 // 獲得對象的下個位置的座標
43 HitTestObject.prototype.GetNextAxes = function (x, y) {
44     var point = { x: x, y: y };
45     switch (this.Direction + "") {    // 加空字符轉換爲字符串類型
46         case EnumDirection.Up:
47             point.y--; break;
48         case EnumDirection.Right:
49             point.x++; break;
50         case EnumDirection.Down:
51             point.y++; break;
52         case EnumDirection.Left:
53             point.x--; break;
54     }
55     return point;
56 }
57 
58 
59 HitTestObject.prototype.OnHitTest = function (battleField) {
60     //  預留給炮彈對象重寫
61 }
View Code

 

  這裏咱們把以前寫的地圖二維數組對象充分利用上了。經過對象x,y座標取對應的地圖對象,再根據屬性判斷是否可被穿過,是否已被佔用。

3.2   調用碰撞檢測

  這裏須要咱們在以前的代碼作一系列的更改了。java

 更改 Mover.js數組

  一、繼承碰撞檢測對象
 
Mover.prototype = new HitTestObject();

  

   二、在Mover方法中調用碰撞檢測
// 碰撞檢測
    if (this.HitTest(battleField)) { return this.OnHitTest(battleField); }

  

 
  三、移動完成後佔用新地圖對象,清空原對象地圖佔用。
 
battleField[nextPoint.y][nextPoint.x].occupier = This;  /*佔用新位置*/

// 清空對象原來位置佔有
battleField[yp][xp].occupier = null;

  

還有一些更改就不一一列出了,你們能夠下載源碼查看。
 
更改    Frame.js 給方法加上參數。
更改 tank.js  UpdateUi方法
初始化坦克時,佔有當前位置。
  

4.   發射炮彈

     炮彈能夠移動,因此繼承自咱們的Mover對象。炮彈擊中障礙物時會有爆炸效果,因此咱們先寫爆炸對象。

 

4.1 爆炸效果對象

  Explode.js:

 

 

 1 // 爆炸效果類
 2 Explode = function () {
 3     this.container = document.getElementById("divMap");
 4     this.UI = null;
 5     this.step = 8;  // 共8張圖
 6     this.speed = 50;    // 動畫播放速度
 7 }
 8 
 9 // 播放爆炸效果
10 Explode.prototype.Play = function (x,y) {
11     this.UI = UtilityClass.CreateE("div", "", "explode", this.container);
12     this.MoveTo(x, y);
13 
14     var i = 0;
15     var This = this;
16     var FxTimer = setInterval(function () {
17         This.UI.style.backgroundPosition = '0 -' + i * 60 + 'px';
18         i++;
19         if (i==This.step) {
20             clearInterval(FxTimer);
21             This.Stop();
22         }
23     },this.speed);
24 }
25 
26 // 播放位置 
27 Explode.prototype.MoveTo = function (x,y) {
28 
29     if (this.UI != null) {
30         this.UI.style.left = x * 40 - 10 + "px";
31         this.UI.style.top = y * 40 - 10 + "px";
32     }
33 
34 }
35 
36 // 移除dom元素
37 Explode.prototype.Stop = function () {
38     UtilityClass.RemoveE(this.UI, this.container);
39 }
View Code

 

 

 


4.2 炮彈對象

   Bomb.js:
 
 1 //  炮彈對象,這個對象須要放在TANK對象前面,有前後順序
 2 Bomb = function () {
 3     this.Owner = null;
 4     this.Power = 1;
 5     this.Speed = 7;
 6 }
 7 
 8 Bomb.prototype = new Mover();
 9 Bomb.prototype.Load = function (x,y) {
10     // 建立炮彈對象,初始化位置
11     this.UI = UtilityClass.CreateE("div", "", "bomb", document.getElementById("divMap"))
12     this.SetPosition(x * 40, y * 40);   /*父類方法*/
13 
14 }
15 
16 // 重寫HitTest方法
17 Bomb.prototype.HitTest = function (battleField) {
18     var nextObj = this.GetNextBattleFieldCell(battleField);
19     if (nextObj == null) {
20         return true;
21     }
22     // 檢測是不是障礙物
23     if (nextObj.obj instanceof Barrier) {
24         // 河流穿過
25         if (this instanceof Bomb && nextObj.obj instanceof RiverB) {
26             return false;
27         }
28 
29         return !nextObj.obj.CanAcross;
30     }
31 
32 }
33 
34 // 重寫OnHitTest方法 當炮彈碰撞到不可穿過對象時調用
35 Bomb.prototype.OnHitTest = function (battleField) {
36 
37     // 播放爆炸效果
38     var ex = new Explode();
39     ex.Play(this.XPosition, this.YPosition);
40     this.Owner.BombUsed--;      /*已用彈藥數減一*/
41     // 清空地圖佔有位置,移除元素
42     battleField[this.YPosition][this.XPosition].occupier = null;
43     UtilityClass.RemoveE(this.UI, document.getElementById("divMap"));
44 
45     var nextObj = this.GetNextBattleFieldCell(battleField);
46     if (nextObj == null) { return; }
47     // 炮彈打到了障礙物
48     if (nextObj.obj instanceof Barrier) {
49         if (nextObj.obj.CanBeAttacked) {
50             nextObj.obj.DefenVal -= this.Power;
51             // 障礙物防護值降到0,把障礙物變爲空地
52             if (nextObj.obj.DefenVal <= 0) {
53                 var to = new EmptyB();
54                 to.UI = nextObj.obj.UI;
55                 to.XPosition = nextObj.obj.XPosition;
56                 to.YPosition = nextObj.obj.YPosition;
57                 nextObj.obj = to;
58                 to.UI.className = "";
59                 battleField[this.YPosition][this.XPosition].obj.UI.className = "";
60             }
61         }
62     }
63         
64 }
View Code

 

   主要的對象完成了,調用就是水到渠成了,咱們須要給坦克添加一個發射炮彈的方法,並在玩家按下空格鍵時調用就能夠了。  你們能夠試着本身寫下實現。  
 
TankV3.0 下載地址:
 
相關文章
相關標籤/搜索