<bdo id="4g88a"><xmp id="4g88a">
  • <legend id="4g88a"><code id="4g88a"></code></legend>

    2D物理引擎 Box2D for javascript Games -- 番外篇-- (為游戲添加皮膚)

    此章為非原書內容,是為了后續章節需要新增的一章
    注意由于 Javascript 版改寫需要,原書第七章去掉,改為提前至番外篇,番外篇講的其實是類似“為游戲添加皮膚” 的內容
    原第七章刪除后,第七章內容實際為原書第八章

    2D物理引擎 Box2D for javascript Games -- 番外篇

    此篇,并不是書中的篇符,而是通過希望通過結合實際的 canvas 繪圖庫實現 box2d 物理引擎在各繪圖庫上應用,繪圖庫網上有很多現成的

    如:createjs, pixi.js 等,Egret或者其它游戲引擎有自己的物理引擎擴展庫,所以就不說了。

    現在通過之前的學習,基本掌握了剛體等基礎概念。那如何如何應用于現實畫面中呢?

    box2d 只是模擬了物體,是虛擬的,如果不是通過 debug 是看不到任何畫面的,要讓用戶看到畫面,必須得結合 canvas 繪圖能力,自己操作 canvas 繪圖的原始 API 太麻煩,所以就有了 createjs 等其它流行的 canvas 庫.

    以下都以createJS代替canvas,當然你用其它庫或者直接操作canvas也都可以

    先上效果圖

    image

    完成代碼位于

    https://github.com/willian12345/Box2D-for-Javascript-Games/blob/master/extra.html

    box2d呈現于 createJS,貼上圖的基本原理,就是將物理引擎世界中剛體的所有狀態復制到 createJS 舞臺對象!

    function init() {
             var   b2Vec2 = Box2D.Common.Math.b2Vec2
                ,  b2AABB = Box2D.Collision.b2AABB
                ,  b2BodyDef = Box2D.Dynamics.b2BodyDef
                ,  b2Body = Box2D.Dynamics.b2Body
                ,  b2FixtureDef = Box2D.Dynamics.b2FixtureDef
                ,  b2Fixture = Box2D.Dynamics.b2Fixture
                ,  b2World = Box2D.Dynamics.b2World
                ,  b2MassData = Box2D.Collision.Shapes.b2MassData
                ,  b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape
                ,  b2CircleShape = Box2D.Collision.Shapes.b2CircleShape
                ,  b2DebugDraw = Box2D.Dynamics.b2DebugDraw
                ,  b2MouseJointDef =  Box2D.Dynamics.Joints.b2MouseJointDef
                ;
             var worldScale = 30; // box2d中以米為單位,1米=30像素
             var gravity = new b2Vec2(0, 5);
             var sleep = true;
             var world;
             var stage,debug;
    
    
             function main(){
                stage = new createjs.Stage("canvas");
                debug = new createjs.Stage("debug");
    
                setupPhysics();
    
                debugDraw();
    
                debug.on("stagemousedown", stagemousedown);
    
                createjs.Ticker.timingMode = createjs.Ticker.RAF;
                createjs.Ticker.on("tick", function(){
                   stage.update();
                   world.DrawDebugData(); // 為了顯示出createjs對象,這里不再繪制box2d對象至canvas
                   world.Step(1/30, 10, 10);// 更新世界模擬
                   world.ClearForces(); // 清除作用力
                });
             }
             main();
    
    
             function Ball(){
                this.view = new createjs.Bitmap('soccer.png');
                this.view.regX = this.view.regY = 50;
    
                // 創建box2d球形體
                var bodyDef = new b2BodyDef();
                bodyDef.position.Set(Math.random()*640 / worldScale, 0/worldScale);
                bodyDef.type = b2Body.b2_dynamicBody
                bodyDef.userData = 0;
                var circleShape = new b2CircleShape(50 / worldScale);
                var fixtureDef = new b2FixtureDef();
                fixtureDef.shape = circleShape;
                fixtureDef.density = 1;
                fixtureDef.restitution = .4
                fixtureDef.friction = .5;
                this.view.body = world.CreateBody(bodyDef);
                this.view.body.CreateFixture(fixtureDef);
    
                this.view.on("tick", function(){
                   // 讓createjs的bitmap對象實時復制box2d對象的位置與旋轉角度
                   this.x = this.body.GetPosition().x * worldScale;
                   this.y = this.body.GetPosition().y * worldScale;
                   this.rotation = this.body.GetAngle() * (180 / Math.PI);
                });
             }
             
             function setupPhysics(){
                world = new b2World(new b2Vec2(0, 50), true);
                floor();  
             }
    
             function stagemousedown(){
                var b = new Ball();
                stage.addChild(b.view); // 將產生的createjs對象添加至舞臺上
             }
    
             function floor(){
                var bodyDef = new b2BodyDef();
                bodyDef.position.Set(320/worldScale, 465/worldScale);
                var polygonShape = new b2PolygonShape();
                polygonShape.SetAsBox(320/worldScale, 15/worldScale);
                var fixtureDef = new b2FixtureDef();
                fixtureDef.shape = polygonShape;
                fixtureDef.restitution = .4;
                fixtureDef.friction = .5;
                var theFloor = world.CreateBody(bodyDef);
                theFloor.CreateFixture(fixtureDef);
             }
    
             //setup debug draw
             function debugDraw(){
                var debugDraw = new b2DebugDraw();
                debugDraw.SetSprite(debug.canvas.getContext('2d'));
                debugDraw.SetDrawScale(worldScale);
                debugDraw.SetFillAlpha(0.5);
                debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
                world.SetDebugDraw(debugDraw);
             }
          };
    

    這一句

    this.view = new createjs.Bitmap('soccer.png');
    

    通過 createjs 的 Bitmap 對象讀取圖片,創建一個足球

    this.view 這個顯示對象即 createjs 的 Bitmap 對象,用于顯示在舞臺即 canvas 上

    this.view.on("tick", function(){
        // 讓createjs的bitmap對象實時復制box2d對象的位置與旋轉角度
        this.x = this.body.GetPosition().x * worldScale;
        this.y = this.body.GetPosition().y * worldScale;
        this.rotation = this.body.GetAngle() * (180 / Math.PI);
    });
    

    在Bitmap對象上偵聽 tick 事件,tick 事件可以理解為 FLASH 中的 ENTER_FRAME 事件,即每一幀調用一次,在每幀中將剛體的 x,y 位置屬性與角度屬性復制到 createJS 的顯示對象上,就完成了結合

    注釋掉這一句,就可以隱藏掉box2Djs的調試狀態變成一個正常的帶物理效果的足球了

    // debugDraw();

    更多關于createJS請至官網或者搜索相關知識,你也完成可以用其它繪圖庫完成一樣的操作,比如Pixi.js

    相關系列:

    HTML5之2D物理引擎 Box2D for javascript Games 系列 第一部分


    注:轉載請注明出處博客園:王二狗 Sheldon 池中物 (willian12345@126.com)

    https://github.com/willian12345

    posted @ 2019-02-17 15:18  池中物王二狗  閱讀(1647)  評論(1編輯  收藏  舉報
    轉載入注明博客園 王二狗Sheldon Email: willian12345@126.com https://github.com/willian12345
    免费视频精品一区二区_日韩一区二区三区精品_aaa在线观看免费完整版_世界一级真人片
    <bdo id="4g88a"><xmp id="4g88a">
  • <legend id="4g88a"><code id="4g88a"></code></legend>