javascript 面向對象制作坦克大戰 (一)


  PS:這個坦克大戰是在網上下的一段源碼之后,自己進行的重寫。   寫這個的目的是為了鞏固自己這段時間對js的學習。整理到博客上,算是對自己近端時間學習js的一個整理。 同時也希望可以幫助到學習js的園友。由於自己也是剛學js不久,所以難免出現錯誤。如果發現希望給予指正。   這個教程適合熟悉js基本語法和面向對象語法的園友學習。 本身沒有太難的東西,這個案例將js面向對象用的比較好,可以作為js面向對象的入門教程。

1.   創建基本對象,實現坦克簡單的移動。

1.1    如何在地圖中繪制畫布?

    考慮到瀏覽器兼容的問題,我們用操作dom的方式來實現游戲對象的繪制和刷新。我們如何存儲我們的地圖呢? 我們應該把地圖用一個二維數組來保存, js中沒有二維數組,但是可以通過在一維數組從存儲數組來實現。

1.2    代碼實現

    我們將畫布設計為 13 * 13 的一個二維數組,每個元素在地圖中對應的長和寬均為40px,可以把整個地圖看成由 40px*40p x大小的單元格組成的一個表格,那么我們整個畫布的大小為 520px  *  520px ;
 
   上代碼前先給大家來一張對象關系圖:
 

1.2.1    創建頂級對象

html代碼:
 
 1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
 2 <html>
 3 <head>
 4     <title>坦克大戰</title>
 5     <link rel=stylesheet href="css/main.css" />
 6     <script src="js/Common.js"></script>
 7     <script src="js/TankObject.js"></script>
 8     <script src="js/Mover.js"></script>
 9     <script src="js/Tank.js"></script>
10     <script src="js/Frame.js"></script>
11     <script>
12         window.onload = function () {
13             // 調用游戲裝載對象
14             var loader = new GameLoader();
15             loader.Begin();
16         }
17     </script>
18 </head>
19 
20 <body>
21     <!--地圖容器-->
22     <div id="divMap">
23     </div>
24     <div id="debugInfo">
25     </div>
26 </body>
27 </html>
View Code

 

 

TankObject.js文件:
 
 1 // 頂級對象
 2 TankObject = function () {
 3     this.XPosition = 0; // 對象在地圖(13*13)中的X的位置 
 4     this.YPosition = 0;
 5     this.UI = null; // dom元素
 6 }
 7 // 更改UI靜態方法
 8 TankObject.prototype.UpdateUI = function (battlFiled) { }
 9 // 設置位置,參數是這樣:1*40,6*40
10 TankObject.prototype.SetPosition = function (leftPosition, topPosition) {
11     // 在地圖的位置 Math.round四舍五入    
12     this.XPosition = Math.round(leftPosition / 40);
13     this.YPosition = Math.round(topPosition / 40);
14     // 設置在窗體上的位置
15     if (this.UI != null && this.UI.style != null) {
16         this.UI.style.left = leftPosition + "px";
17         this.UI.style.top = topPosition + "px";
18     }
19 }
View Code

 

 
 
    這里​我們用X,Y坐標表示對象在地圖上的位置。后面我們會將地圖中的每個對象都放入二維數組中,這時可以通過X,Y坐標來取得對應的對象。
    然后用css中的left和top來控制我們對象在窗體中的位置。(可以移動的對象:坦克,子彈)
 

1.2.2   創建公用對象

    我們還需要創建一個公共的對象,來寫入我們常用的一些方法。
 
Common.js:
 
// 坦克移動的四個方向
var EnumDirection = {
    Up: "0",
    Right: "1",
    Down: "2",
    Left: "3"
};


// 通用方法對象
var UtilityClass = {
    // 創建dom元素到parentNode中,可指定id,className
    CreateE: function (type, id, className, parentNode) {
        var J = document.createElement(type);
        if (id) { J.id = id };
        if (className) { J.className = className };
        return parentNode.appendChild(J);
    },  // 移除元素
    RemoveE: function (obj, parentNode) {
        parentNode.removeChild(obj);
    },
    GetFunctionName: function (context, argumentCallee) {
        for (var i in context) {
            if (context[i] == argumentCallee) { return i };
        }
        return "";
    },  // 綁定事件,返回func方法,this為傳入的obj
    BindFunction: function (obj,func) {
        return function () {
            func.apply(obj, arguments);
        };
    }
};
View Code

  

1.2.3    創建移動對象

 
 
Mover.js
 
 1 // 移動對象,繼承自頂層對象
 2 Mover = function () {
 3     this.Direction = EnumDirection.Up;
 4     this.Speed = 1;
 5 }
 6 Mover.prototype = new TankObject();
 7 Mover.prototype.Move = function () {
 8     if (this.lock) {
 9         return;/* 停用或者尚在步進中,操作無效 */
10     }
11     // 根據方向設置坦克的背景圖片
12     this.UI.style.backgroundPosition = "0 -" + this.Direction * 40 + "px";
13     // 如果方向是上和下,vp就是top;如果方向是上和左,val就是-1
14     var vp = ["top", "left"][((this.Direction == EnumDirection.Up) || (this.Direction == EnumDirection.Down)) ? 0 : 1];
15     var val = ((this.Direction == EnumDirection.Up) || (this.Direction == EnumDirection.Left)) ? -1 : 1;
16     this.lock = true;/* 加鎖 */
17     // 把當前對象保存到This
18     var This = this;
19     // 記錄對象移動起始位置
20     var startmoveP = parseInt(This.UI.style[vp]);
21     var xp = This.XPosition, yp = This.YPosition;
22     var subMove = setInterval(function () {
23         // 開始移動,每次移動5px
24         This.UI.style[vp] = parseInt(This.UI.style[vp]) + 5 * val + "px";
25         // 每次移動一個單元格 40px
26         if (Math.abs((parseInt(This.UI.style[vp]) - startmoveP)) >= 40) {
27             clearInterval(subMove);
28             This.lock = false;/* 解鎖,允許再次步進 */
29             // 記錄對象移動后在表格中的位置
30             This.XPosition = Math.round(This.UI.offsetLeft / 40);
31             This.YPosition = Math.round(This.UI.offsetTop / 40);
32 
33         }
34     }, 80 - this.Speed * 10);
35 
36 }
View Code

 

 
    這里的移動對象繼承自我們的頂級對象 ,這里this就代表調用Move方法的對象。
    Move對象的功能根據對象的方向和速度進行移動,每次移動5px總共移動40px一個單元格。后面這個對象還會進行擴展,會加入碰撞檢測等功能。
 
 
 

1.2.4    創建坦克對象

 
 
Tank.js 文件:
 
//tank對象 繼承自Mover
Tank=function(){}

Tank.prototype = new Mover();


// 創建玩家坦克,繼承自tank對象
SelfTank = function () {
    this.UI = UtilityClass.CreateE("div", "", "itank", document.getElementById("divMap"));
    this.MovingState = false;
    this.Speed = 4;
}
SelfTank.prototype = new Tank();
// 設置坦克的位置
SelfTank.prototype.UpdateUI = function () {
    this.UI.className = "itank";
    // 頂級對象方法,設置坦克的位置
    this.SetPosition(this.XPosition * 40, this.YPosition * 40);
}
View Code

 


 
     現在只創建了玩家坦克,后面我們還會往里添加敵人坦克。
 
 

1.2.5    創建游戲裝載對象(核心)

 1 // 游戲載入對象 整個游戲的核心對象
 2 GameLoader = function () {
 3     this.mapContainer = document.getElementById("divMap");  // 存放游戲地圖的div
 4     this._selfTank = null;  // 玩家坦克
 5     this._gameListener = null; // 游戲主循環計時器id
 6 }
 7 GameLoader.prototype = {
 8     Begin: function () {
 9         // 初始化玩家坦克
10         var selfT = new SelfTank();
11         selfT.XPosition = 4;
12         selfT.YPosition = 12;
13         selfT.UpdateUI();
14         this._selfTank = selfT;
15 
16         // 添加按鍵事件
17         var warpper = UtilityClass.BindFunction(this, this.OnKeyDown);
18         window.onkeydown = document.body.onkeydown = warpper;
19         warpper = UtilityClass.BindFunction(this, this.OnKeyUp);
20         window.onkeyup = document.body.onkeyup = warpper;
21         // 游戲主循環
22         warpper = UtilityClass.BindFunction(this, this.Run);
23         /*長定時器監聽控制鍵*/
24         this._gameListener = setInterval(warpper, 20);
25 
26     }
27     // 鍵盤按下玩家坦克開始移動
28     , OnKeyDown: function (e) {
29         switch ((window.event || e).keyCode) {
30             case 37:
31                 this._selfTank.Direction = EnumDirection.Left;
32                 this._selfTank.MovingState = true;
33                 break;        //
34             case 38:
35                 this._selfTank.Direction = EnumDirection.Up;
36                 this._selfTank.MovingState = true;
37                 break;        //
38             case 39:
39                 this._selfTank.Direction = EnumDirection.Right;
40                 this._selfTank.MovingState = true;
41                 break;        //
42             case 40:
43                 this._selfTank.Direction = EnumDirection.Down;
44                 this._selfTank.MovingState = true;
45                 break;        //
46         }
47 
48     }
49     // 按鍵彈起停止移動
50     , OnKeyUp: function (e) {
51         switch ((window.event || e).keyCode) {
52             case 37:
53             case 38:
54             case 39:
55             case 40:
56                 this._selfTank.MovingState = false;
57                 break;
58         }
59     }
60     /*游戲主循環運行函數,游戲的心臟,樞紐*/
61     , Run: function () {
62         if (this._selfTank.MovingState) {
63             this._selfTank.Move();
64         }
65     }
66 
67 
68 };
View Code

 

 
    游戲裝載對象代碼看起來很多,其實就做了兩件事情:
        1、創建玩家坦克對象。
        2、添加按鍵監聽事件,當玩家按下移動鍵調用坦克Move方法移動坦克。
 
  總結:到這里我們的坦克可以通過按鍵自由的移動了。下一步我們需要完善地圖和碰撞檢測。
 
 
  這個版本源碼下載地址:
 
 
 
 
 


免責聲明!

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



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