程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> 基於HTML5的WebGL結合Box2DJS物理引擎應用

基於HTML5的WebGL結合Box2DJS物理引擎應用

編輯:關於PHP編程

基於HTML5的WebGL結合Box2DJS物理引擎應用


上篇我們基於HT for Web呈現了A* Search Algorithm的3D尋路效果,這篇我們將采用HT for Web 3D來呈現Box2DJS物理引擎的碰撞效果,同上篇其實Box2DJS只是二維的平面碰撞物理引擎,但同樣通過3D的呈現能讓人更直觀的體驗到碰撞效果,最終例子效果:

http://hightopo.com/demo/box2djs/ht-box2d-demo.html

Box2D最早是Erin Catto在GDC大會上的一個展示例子,後來不斷完善成C++的開源物理引擎庫,這些年了衍生出Java、ActionScript以及JS等版本,被廣泛應用在游戲領域。說其豐富的確很豐富,說亂也夠亂的,找個Box2D的JS版就有N多選擇,而且不同版本API還有差異,可參考這裡的對比http://stackoverflow.com/questions/7628078/which-box2d-javascript-library-should-i-use

雖然版本較多有點亂,但各個版本的基本原理和API都類似,以下為我基於Box2DJS融合HT for Web寫的例子代碼。Box2D有很多參數功能點,這裡例子我們僅呈現最基礎簡單的要素,主要讓大家理解Box2DJS引擎的基本使用,以及呈現上如何與HT for Web結合。

以下代碼在createNode中即構建的HT for Web的Node對象,同時構建了Box2D的Body對象,並通過userData屬性關聯在一起,在requestAnimationFrame的渲染過程,先通過world.Step(1 / 60, 10, 10);更新物理引擎的內部運算,然後遍歷所有Body元素將運算結果,也就是Body的位置和旋轉角度等信息同步到HT for Web的Node對象,從而達到了HT for Web和Box2DJS的強強結合各施其才。

function init() {    dm = new ht.DataModel();    g3d = new ht.graph3d.Graph3dView(dm);    g3d.setGridVisible(true);    g3d.addToDOM();    g3d.setEye(100, 50, 150);    // Define the world    var gravity = new b2Vec2(0, -100);    var doSleep = false;    world = new b2World(gravity, doSleep);    createNode([0, -3, 0], [100, 6, 100], false, 0);    createNode([-100, -50, 0], [400, 6, 100], false, -Math.PI/8);    createNode([100, -50, 0], [50, 6, 100], false, Math.PI/6);    createNode([1, 50, 0], [10, 10, 10], true);    createNode([-1, 90, 0], [10, 10, 10], true);    render();}function createNode(p3, s3, dynamic, angle) {    var node = new ht.Node();    node.p3(p3);    node.s3(s3);                   node.setRotationZ(angle == null ? Math.PI * Math.random() : angle);    dm.add(node);    var fixDef = new b2FixtureDef();    if (dynamic) {        fixDef.density = 0.5;        fixDef.friction = 0.5;        fixDef.restitution = 0.5;                            node.s({            'all.color': 'red',            'batch': 'dynamic'        });    } else {        fixDef.density = 0.0;                        }    var shape = new b2PolygonShape();    shape.SetAsBox(s3[0] / 2, s3[1] / 2);    fixDef.shape = shape;    var bodyDef = new b2BodyDef();    bodyDef.type = dynamic ? b2Body.b2_dynamicBody : b2Body.b2_staticBody;    bodyDef.position.Set(p3[0], p3[1]);    bodyDef.angle = node.getRotationZ();    bodyDef.userData = node;    world.CreateBody(bodyDef).CreateFixture(fixDef);}count = 0function render() {    count++;    if(count % 10 === 0){        createNode([-1, 50, 0], [10, 10, 10], true);    }                    world.Step(1 / 60, 10, 10);    var list = world.GetBodyList();    while (list) {                                                      var node = list.m_userData;        if(node){            var position = list.GetPosition();            if(position.y < -150 || g3d.isSelected(node)){                dm.remove(node);                world.DestroyBody(list);            }else{                node.p3(position.x, position.y, 0);                node.setRotationZ(list.GetAngle());                                        }                                                      }                            list = list.GetNext();    }                        requestAnimationFrame(render);}

http://hightopo.com/demo/box2djs/ht-box2d-demo.html

例子中物體掉落到-150以下我就刪除了Box2DJS以及HT的DataModel中對應的數據元素,同時選中圖元也會自動刪除圖元,count % 10 === 0 這個用來沒十次刷新產生一個新的立方體。Box2D還可以玩出很多花樣,如果數據量大也可以考慮參考《3D拓撲自動布局之Web Workers篇》,將Box2DJS的密集運算在WebWork中執行,我沒評估過性能的提升幅度,數據量大時WebWork和GUI線程的數據序列化傳遞也會有負擔需注意,最終的例子3D效果玩起來還是挺有趣的:http://v.youku.com/v_show/id_XODM0OTQ0NzEy.html

Screen Shot 2014-11-25 at 8.05.11 PM

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved