【问题标题】:Pooling Box2d Bodies?合并 Box2d 实体?
【发布时间】:2015-11-07 16:54:30
【问题描述】:

我正在尝试通过池化 box2d 主体来生成块,我不知道 libgdx 池化是否适用于主体,但如果适用,请有人解释我如何做到这一点以及我的代码有什么问题。

首先我在不同的方法上创建了 BodyDef 和 Body:

public BodyDef createDef(){
        BodyDef def = new BodyDef();
        def.type = BodyDef.BodyType.StaticBody;
        def.fixedRotation = true;
        def.position.set(6, 6);

        return(def);
    }

    public Body createBody(){
        Body body = world.createBody(createDef());
        PolygonShape shape = new PolygonShape();
        shape.setAsBox(1, 1);
        body.createFixture(shape, 1.0f);
        shape.dispose();

        return(body);
    }

 public void createPlatform(){
      Body platform = Pools.obtain(Body.class); //then use pooling
        platform = createBody(); //here I set the value equal to the return value of createBody() method 
        bodies.add(platform);//adding platform to the ArrayList
    }

然后生成块我只需调用此方法:

public void spawnChunk(){
        createPlatform();
    }

我对此很陌生,我不知道块的含义是什么,但我知道它在横向滚动游戏中用于生成地形,我收到此错误消息

Exception in thread "LWJGL Application" java.lang.RuntimeException: Class cannot be created (missing no-arg constructor): com.badlogic.gdx.physics.box2d.Body
    at com.badlogic.gdx.utils.ReflectionPool.<init>(ReflectionPool.java:41)
    at com.badlogic.gdx.utils.Pools.get(Pools.java:29)
    at com.badlogic.gdx.utils.Pools.get(Pools.java:38)
    at com.badlogic.gdx.utils.Pools.obtain(Pools.java:48)
    at com.nivekbryan.ragingpotato.Physics.createPlatform(Physics.java:53)
    at com.nivekbryan.ragingpotato.Physics.spawnChunk(Physics.java:59)
    at com.nivekbryan.ragingpotato.WorldController.update(WorldController.java:17)
    at com.nivekbryan.ragingpotato.MainClass.render(MainClass.java:27)
    at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:215)
    at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:120)

【问题讨论】:

    标签: java libgdx box2d pooling


    【解决方案1】:

    不要对 box2d 体或关节使用池化,来自 box2d wiki:

    所以当你创建一个 b2Body 或一个 b2Joint 时,你需要调用工厂 b2World 上的功能。您永远不应该尝试将这些类型分配到 另一种方式。

    所以你应该只使用Body body = world.createBody(bodyDef); 来创建body。

    接下来,您将身体添加到某种列表中,这是绝对不应该做的!如果您需要访问您世界中的所有实体,请这样做:

    // Global field
    Array<Body> bodies = new Array<>();
    
    // When you want to access the bodies.
    world.getBodies(bodies);
    for(Body body : bodies)
    {
        // Do something
    }
    

    错误意味着Body 类没有看起来像的构造函数

    public Body() {}
    

    因此不能由通用池类实现创建,因为它试图调用此构造函数。

    要解决这个问题,您可以自己实现池,但如上所述,您不应该这样做。


    您当前代码的另一个错误是您似乎误解了 java 中的变量赋值。

    // gets a body from your pool, arbitrary method
    Body pooledBody = getFromPool();
    
    // assigns a new body to pooledBody, so your pooling is "voided".
    pooledBody = world.createBody(createDef());
    

    正如您在此示例中看到的那样,getFromPool(); 无效,因为您在下一行为 pooledBody 分配了一个新值。

    一个更简单的例子,说明为什么它不能按你的意愿工作:

    int a = getFromPool(); // lets says this assigns 4 to a
    a = 5;
    System.out.println(a);
    

    将始终打印 5,从不打印 4!


    您可以合并的是 BodyDefFixutureDefShape 类,因为它们没有参数构造函数。

    【讨论】:

    • 什么是 getFromPool() ?你设置 pooledBody 等于一个已经有 def 和 fixture 的身体?然后创建 pooledBody?
    • getFromPool(); 只是一种任意方法来表明您从池中获得了身体。但正如我所说,不要那样做,形成 box2d wiki :So when you create a b2Body or a b2Joint, you need to call the factory functions on b2World. You should never try to allocate these types in another manner.
    • 我刚刚意识到,由于我无法在主体上使用池化,因此使用数组是没用的,因为我的计划是将主体池化,然后将其添加到数组中并在不需要时将其删除.如果不进行池化,我怎么能做到这一点?总是创建一个新的然后删除它是一个坏主意,因为它会消耗更多的内存。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多