Cocos2d-js中Chipmunk引擎

咱們先介紹輕量級的物理引擎——Chipmunk。Chipmunk物理引擎,由Howling Moon Software的Scott Lebcke開發,用純C編寫。Chipmunk的下載地址是http://code.google.com/p/chipmunk-physics/,技術論壇是http://chipmunk-physics.net/forum。
Chipmunk核心概念
Chipmunk物理引擎有一些本身的核心概念,這些核心概念主要有: 
空間(space)。物理空間,全部物體都在這個空間中發生。
物體(body)。物理空間中的物體。
形狀(shape)。物體的形狀。
關節(joint)。用於鏈接兩個物體的約束。
使用Chipmunk物理引擎的通常步驟
使用Chipmunk物理引擎進行開發的通常步驟,以下圖所示。

javascript

使用Chipmunk物理引擎的通常步驟html



從圖中可見使用Chipmunk引擎步驟仍是比較簡單的。咱們還須要本身在遊戲循環中將鏈接精靈與物體起來,這可以使得精靈與物體的位置和角度等狀態同步。最後的檢測碰撞是根據業務需求而定,也多是使用關節。


實例:HelloChipmunk
咱們經過一個實例介紹一下,在Cocos2d-JS中使用Chipmunk物理引擎的開發過程,熟悉這些API的使用。這個實例運行後的場景以下圖所示,當場景啓動後,玩家能夠觸摸點擊屏幕,每次觸摸時候,就會在觸摸點生成一個新的精靈,精靈的運行自由落體運動。
html5


HelloChipmunk實例java



下面咱們看一下代碼部分,app.js文件中HelloWorldLayer初始化相關代碼以下:
json

[html] view plaincopy在CODE上查看代碼片派生到個人代碼片瀏覽器

  1. var SPRITE_WIDTH = 64;                                              ①  微信

  2. var SPRITE_HEIGHT = 64;                                             ②  app

  3. var DEBUG_NODE_SHOW = true;                                         ③  函數

  4.   

  5.   

  6. var HelloWorldLayer = cc.Layer.extend({                                 ④  網站

  7.     space: null,                                                        ⑤  

  8.     ctor: function () {  

  9.         

  10.         this._super();  

  11.   

  12.   

  13.         this.initPhysics();                                             ⑥  

  14.   

  15.   

  16.         this.scheduleUpdate();                                          ⑦  

  17.   

  18.   

  19.     }  

  20.         … …  

  21. });  

上述第①行代碼是定義精靈寬度常量SPRITE_WIDTH,第②行代碼是定義精靈高度常量SPRITE_HEIGHT,第③行代碼是定義是否繪製調試遮罩開關常量DEBUG_NODE_SHOW。
第④行代碼是聲明HelloWorldLayer層。第⑤行代碼聲明物理空間成員變量space。第⑥行代碼是在構造函數中調用this.initPhysics()語句實現初始化物理引擎。第⑦行代碼是在構造函數中調用this.scheduleUpdate()語句開啓遊戲循環,一旦開啓遊戲循環就開始回調update(dt)函數。
HelloWorldLayer中調試相關函數setupDebugNode代碼以下:
    setupDebugNode: function () {
        this._debugNode = new cc.PhysicsDebugNode(this.space);
        this._debugNode.visible = DEBUG_NODE_SHOW;
        this.addChild(this._debugNode);
    }
上述代碼第①行建立PhysicsDebugNode對象,它是一個物理引擎調試Node對象,參數是this.space物理空間成員變量。第②行代碼是設置繪製調試遮罩visible屬性。第③行代碼是將調試遮罩對象添加到當前層,以下圖所示是設置visible屬性true。

繪製調試遮罩

注意 繪製調試遮罩在JSB本地方式下運行沒有效果,在Web瀏覽器下運行纔可以看到效果。
HelloWorldLayer中觸摸事件相關的代碼以下:
 

[html] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. onEnter: function () {  

  2.      this._super();  

  3.      cc.log("onEnter");  

  4.      cc.eventManager.addListener({  

  5.          event: cc.EventListener.TOUCH_ONE_BY_ONE,  

  6.          onTouchBegan: this.onTouchBegan  

  7.      }, this);  

  8.  },  

  9.  onTouchBegan: function (touch, event) {  

  10.      cc.log("onTouchBegan");  

  11.      var target = event.getCurrentTarget();  

  12.      var location = touch.getLocation();  

  13.      target.addNewSpriteAtPosition(location);                               ①  

  14.      return false;  

  15.  },  

  16.  onExit: function () {  

  17.      this._super();  

  18.      cc.log("onExit");  

  19.      cc.eventManager.removeListeners(cc.EventListener.TOUCH_ONE_BY_ONE);  

  20.  }  

上述代碼第①行是調用當前層的addNewSpriteAtPosition函數實現是在觸摸點添加精靈對象,其中target是當前層對象,注意這裏不能使用this。
HelloWorldLayer中初始化物理引擎initPhysics()函數代碼以下:

[html] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. initPhysics: function () {  

  2.   

  3.   

  4.        var winSize = cc.director.getWinSize();  

  5.   

  6.   

  7.        this.space = new cp.Space();                                     ①  

  8.        this.setupDebugNode();                                           ②  

  9.   

  10.   

  11.        // 設置重力  

  12.        this.space.gravity = cp.v(0, -100);                                  ③  

  13.        var staticBody = this.space.staticBody;                              ④  

  14.   

  15.   

  16.        // 設置空間邊界  

  17.        var walls = [ new cp.SegmentShape(staticBody, cp.v(0, 0),   

  18.                                         cp.v(winSize.width, 0), 0),                     ⑤  

  19.            new cp.SegmentShape(staticBody, cp.v(0, winSize.height),   

  20.                                         cp.v(winSize.width, winSize.height), 0),            ⑥  

  21.            new cp.SegmentShape(staticBody, cp.v(0, 0),   

  22.                                         cp.v(0, winSize.height), 0),                    ⑦  

  23.            new cp.SegmentShape(staticBody, cp.v(winSize.width, 0),   

  24.                                         cp.v(winSize.width, winSize.height), 0)         ⑧  

  25.        ];  

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

  27.            var shape = walls[i];  

  28.            shape.setElasticity(1);                                          ⑨  

  29.            shape.setFriction(1);                                            ⑩  

  30.            this.space.addStaticShape(shape);                            ⑪  

  31.        }  

  32.    }  

代碼第①行new cp.Space()是建立物理空間。第②行代碼this.setupDebugNode()是設置調試Node對象。第③行代碼this.space.gravity = cp.v(0, -100)是爲空間設置重力,cp.v(0, -100)是建立一個cp.v結構體,cp.v是Chipmunk中的二維矢量類型,參數(0, -100)表示只有重力做用物體,-100表示沿着y軸向下,其中的100也是一個經驗值。
第④行代碼var staticBody = this.space.staticBody得到從物理空間中得到靜態物體。
代碼第⑤~⑧是建立物理空間,它是由4條邊線段形狀構成的,從上到下分別建立了這4個線段形狀(cp.SegmentShape),new cp.SegmentShape語句能夠建立一條線段形狀,它的構造函數有4個參數,第一個形狀所附着的物體,因爲是靜態物體,本例中使用this.space.staticBody表達式得到靜態物體。第二個參數是線段開始點,第三個參數是線段結束點,第四個參數是線段的寬度。
代碼第⑨~⑪行是設置線段形狀屬性,因爲有4個邊須要進行循環。其中第⑨行代碼是經過函數shape.setElasticity(1)設置彈性係數屬性爲1。第⑩行代碼shape.setFriction(1)設置摩擦係數。
第⑪行代碼this.space.addStaticShape(shape)是將靜態物體與形狀關聯起來。
HelloWorldLayer中建立精靈addNewSpriteAtPosition()函數代碼以下:

[html] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1.  addNewSpriteAtPosition: function (p) {  

  2.      cc.log("addNewSpriteAtPosition");  

  3.   

  4.   

  5.         var body = new cp.Body(1, cp.momentForBox(1, SPRITE_WIDTH, SPRITE_HEIGHT)); ①  

  6.         body.setPos(p);                                                 ②  

  7.      this.space.addBody(body);                                          ③  

  8.   

  9.   

  10.      var shape = new cp.BoxShape(body, SPRITE_WIDTH, SPRITE_HEIGHT);            ④  

  11.      shape.setElasticity(0.5);  

  12.      shape.setFriction(0.5);  

  13.      this.space.addShape(shape);                                            ⑤  

  14.   

  15.   

  16.      //建立物理引擎精靈對象  

  17.      var sprite = new cc.PhysicsSprite(res.BoxA2_png);                          ⑥  

  18.      sprite.setBody(body);                                              ⑦  

  19.      sprite.setPosition(cc.p(p.x, p.y));                                          

  20.      this.addChild(sprite);                                               

  21. }  

上述代碼第①行代碼是使用cp.Body構造函數建立一個動態物體,構造函數第一個參數質量,這裏的1是一個經驗值,咱們能夠經過改變它的大小而改變物體的物理特性。第二參數慣性值,它決定了物體運動時受到的阻力,設置慣性值使用cp.momentForBox函數。cp.momentForBox函數是計算多邊形的慣性值,它的第一個參數是慣性力矩[ 慣性力矩,也叫「MOI」,是Moment Of Inertia的縮寫,慣性力矩是用來判斷一個物體在受到力矩做用時,容不容易繞着中心軸轉動的數值。——引自於百度百科 http://www.baike.com/wiki/慣性力矩],這裏的1也是一個經驗值,第二個參數是設置物體的寬度,第三個參數是設置物體的高度,相似的函數還有不少,如cp.momentForBox、cp.momentForSegment和cp.momentForCircle等。
第②行代碼body.setPos(p)是設置物體重心(物體的幾何中心)的座標。第③行代碼this.space.addBody(body)是把物體添加到物理空間中。
第④行代碼是建立cp.BoxShape形狀對象。第⑤行代碼this.space.addShape(shape)是添加形狀到空間中。
第⑥行代碼是建立物理引擎精靈對象,其中cc.PhysicsSprite是由Cocos2d-JS提供的物理引擎精靈對象,採用cc.PhysicsSprite類自動地將精靈與物體位置和旋轉角度同步起來,咱們在遊戲循環函數中須要簡單的語句就能夠實現它們的同步了。代碼第⑦行sprite.setBody(body)是設置精靈所關聯的物體。
HelloWorldLayer中建立精靈update函數代碼以下: 

[html] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. update: function (dt) {  

  2.             var timeStep = 0.03;                                                ①  

  3.         this.space.step(timeStep);                                          ②  

  4.     }  

上述代碼第①行的timeStep表示自上一次循環過去的時間,它影響到物體本次循環將要移動的距離和旋轉的角度。咱們不建議使用update 的dt參數做爲timeStep,由於dt時間是上下浮動的,因此使用dt做爲timeStep時間,物體的運動速度就不穩定。咱們建議使用固定的timeStep時間。
第②行代碼this.space.step(timeStep)更新物理引擎世界。
最後咱們要修改project.json文件,添加模塊聲明,代碼以下:

[html] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. {  

  2.     "project_type": "javascript",  

  3.   

  4.   

  5.     "debugMode" : 1,  

  6.     "showFPS" : true,  

  7.     "frameRate" : 60,  

  8.     "id" : "gameCanvas",  

  9.     "renderMode" : 2,  

  10.     "engineDir":"frameworks/cocos2d-html5",  

  11.   

  12.   

  13.         "modules" : ["cocos2d", "external"],                                        ①  

  14.   

  15.   

  16.     "jsList" : [  

  17.         "src/resource.js",  

  18.         "src/app.js"  

  19.     ]  

  20. }  

咱們在第①行"modules"配置中添加external模塊,external模塊包含了chipmunk等子模塊,這些模塊的定義你們能夠打開<工程目錄>\frameworks\cocos2d-html5\ moduleConfig.json,這裏Cocos2d-JS的全部模塊,以及每一個模塊所包含的js文件。


更多內容請關注最新Cocos圖書《Cocos2d-x實戰:JS卷——Cocos2d-JS開發

本書交流討論網站:http://www.cocoagame.net

歡迎加入Cocos2d-x技術討論羣:257760386

更多精彩視頻課程請關注智捷課堂Cocos課程:http://v.51work6.com

智捷課堂現推出Cocos會員,敬請關注:http://v.51work6.com/courseInfoRedirect.do?action=netDetialInfo&courseId=844465&amp;categoryId=0

《Cocos2d-x實戰 JS卷》現已上線,各大商店均已開售:

京東:http://item.jd.com/11659698.html

歡迎關注智捷iOS課堂微信公共平臺,瞭解最新技術文章、圖書、教程信息

相關文章
相關標籤/搜索