2

我必须为 Android 编写一个落入容器中的球的模拟。首先,我尝试在 HTML5 画布中使用 Box2Dweb,但它有 3 个实体和 50 个球,它的运行速度非常慢,即使在使用 Firefox 的台式计算机中也是如此(奇怪的是,使用 Chrome 时它的性能非常好)。这是现场演示

这是代码

     var    b2Vec2 = Box2D.Common.Math.b2Vec2
        ,   b2BodyDef = Box2D.Dynamics.b2BodyDef
        ,   b2Body = Box2D.Dynamics.b2Body
        ,   b2FixtureDef = Box2D.Dynamics.b2FixtureDef
        ,   b2Fixture = Box2D.Dynamics.b2Fixture
        ,   b2World = Box2D.Dynamics.b2World
        ,   b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape
        ,   b2CircleShape = Box2D.Collision.Shapes.b2CircleShape
        ,   b2DebugDraw = Box2D.Dynamics.b2DebugDraw
        ;

     var world = new b2World(
           new b2Vec2(0, 10)    //gravity
        ,  true                 //allow sleep
     );

     var fixDef = new b2FixtureDef;
     fixDef.density = 1.0;
     fixDef.friction = 0.5;
     fixDef.restitution = 0.2;

     var bodyDef = new b2BodyDef;

     //create ground
     var canvas = $('#canvas'),
         offsetX = (canvas.width() / 30) / 4,
         offsetY = (canvas.height() / 30) / 5; //center the machine on the screen.

     bodyDef.type = b2Body.b2_staticBody;
     fixDef.shape = new b2PolygonShape;
     fixDef.shape.SetAsBox(5, 0.5);
     bodyDef.position.Set(5 + offsetX, 10 + offsetY);
     world.CreateBody(bodyDef).CreateFixture(fixDef);
     fixDef.shape.SetAsBox(0.5, 7);
     bodyDef.position.Set(0 + offsetX, 3 + offsetY);
     world.CreateBody(bodyDef).CreateFixture(fixDef);
     bodyDef.position.Set(10 + offsetX, 3 + offsetY);
     world.CreateBody(bodyDef).CreateFixture(fixDef);


     //create some objects
     var numObjects = 50;
     bodyDef.type = b2Body.b2_dynamicBody;
     for(var i = 0; i < numObjects; ++i) {
        fixDef.shape = new b2CircleShape(
            0.6 //Math.random() + 0.1 //radius
        );

        bodyDef.position.x = Math.random() * 9 + offsetX;
        bodyDef.position.y = Math.random() * 9 - 2;
        world.CreateBody(bodyDef).CreateFixture(fixDef);
     }

     //setup debug draw
     var debugDraw = new b2DebugDraw();
        debugDraw.SetSprite(document.getElementById("canvas").getContext("2d"));
        debugDraw.SetDrawScale(30.0);
        debugDraw.SetFillAlpha(0.5);
        debugDraw.SetLineThickness(1.0);
        debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
        world.SetDebugDraw(debugDraw);

     var rate = 60;

     window.requestAnimFrame = (function(){
        return window.requestAnimationFrame       ||
               window.webkitRequestAnimationFrame ||
               window.mozRequestAnimationFrame    ||
               function( callback ){
                 window.setTimeout(callback, 1000 / rate);
               };
     })();

     //update         
     (function update() {
        requestAnimFrame(update);
        world.Step(1 / rate, 10, 10);
        world.DrawDebugData();
        world.ClearForces();                        
     })();

我的问题是,如果我使用 Android 画布(不是 HTML5 画布)和 Box2D 编写本机实现会怎样?我会实现球的平稳运动吗?

而隐藏的线索是:成绩这么差是因为画画还是因为物理演算太多?通常,当涉及物理微积分时,我可以赢得多少性能?

4

1 回答 1

1

主要区别在于 HTML5 和 Box2DWeb您的游戏受限于浏览器优化和您自己的代码优化

有些浏览器没有硬件加速画布;或者浏览器的Javascript引擎优化不够。即使在桌面浏览器中,您也可以看到这种差异。例如,谷歌浏览器在他的V8引擎内部做了很多优化。

因为浏览器的 Javascript 引擎之间存在如此多的差异(正如您在 Firefox 和 Chrome 中所注意到的那样),所以很难对它们进行代码优化。

由于移动硬件通常非常有限并且移动浏览器发展不够完善,因此对主动高帧率进行优化是非常痛苦的,并且可能根本无法完成。

例如,您提供的代码可能会在没有本机 requestAnimationFrame 的浏览器中受到影响。此外,动态绘制形状对于低硬件设备来说太昂贵了。所以你最后一个问题的答案可能是:绘图和物理计算都在扼杀性能。但主要的瓶颈肯定是绘图。

使用原生 Android 画布可以让您快速响应,因为游戏将比浏览器更有效地使用设备硬件。

令人上瘾的是,用于 android 的 Box2D 比 Box2DWeb 更有效(原始 Box2D 的一个不错的端口,但仍然存在性能差距)。

底线,如果您的目标是主要的 Android 设备,您应该使用本机实现。但是,如果您想针对大量浏览器和设备而不需要为每个平台重新编写代码,请使用漂亮的 HTML5。(每个选择都意味着后果,您必须选择最适合您需要的选项)。

如果您决定使用 HTML5 画布,请参阅此答案。(顺便说一句,这是你自己的问题:))

如果你真的很投入,可以学习一点关于WebGLOpenGL ES的知识。

于 2013-05-03T06:50:30.713 回答