【问题标题】:LAG : not fluid movement on JAVA Box2D gameLAG:在 JAVA Box2D 游戏中运动不流畅
【发布时间】:2015-08-05 00:38:32
【问题描述】:

我是一名新手游戏开发者。我一直在尝试使用 LibGDX 和 Box2D 物理引擎开发游戏,但是当我导出我的 android 应用程序时,它无法正常工作。

这个问题出现在某些设备上;不管是旧设备还是新设备。

例如,该应用在 Sony Xperia Z1、摩托罗拉 XT615、LG L1、LG L3、LG L5 等中运行良好。但是,在索尼 Xperia U、摩托罗拉 Moto E、三星 Galaxy 上,并没有像我预期的那样工作。

当对象在屏幕上移动时,您可以看到非流体行为。这就是我遇到的问题。这就像口吃效果,而不是流畅的。

我在论坛上读到,当我在世界上设置时间步长时,它可能是一个 FPS(每秒帧数)问题。因此,我使用的是固定时间步长方法,并使用“累加器”中的剩余时间对其进行插值。我读了这些文章:

http://gafferongames.com/game-physics/fix-your-timestep/
http://saltares.com/blog/games/fixing-your-timestep-in-libgdx-and-box2d/

学习了固定时间步长和插值方法,但是我觉得我的代码有一个看不到的fail。

这是我的代码:

public class MyGame extends ApplicationAdapter {

SpriteBatch batch;                                                                                      
Texture img;                                                                                             
Sprite sprite;                                                                                             
Body body;                                                                                 
Box2DDebugRenderer debugRenderer;                                                                           
OrthographicCamera camera;                                                                                              
World world;                                                                                                                  
final float PixelsToMeters=100f;                                                                                                  
float step = 1.0f / 60.0f ,alpha;                                                                                              
Vector2 currentPosition,lastPosition,position;                                                                                           
double currentTime,accumulator,lastAngle,currentAngle;                                                                                            
final float BODY_WIDTH=95f,BODY_HEIGHT=95f;


@Override
public void create () {
    world= new World(new Vector2(0f,-9.8f),true);
    batch = new SpriteBatch();
    img = new Texture("circulo.png");
    sprite=new Sprite(img);

    //BODY DEFINITION
    BodyDef bodydef=new BodyDef();
    bodydef.type= BodyType.DynamicBody;
    bodydef.position.set(-3.5f,-2.4f);
    body=world.createBody(bodydef);

    CircleShape shape=new CircleShape();
    shape.setRadius((sprite.getWidth()/2)/PixelsToMeters);

    FixtureDef fixturedef=new FixtureDef();
    fixturedef.shape=shape;
    fixturedef.density=0.1f;
    fixturedef.restitution=1f;
    fixturedef.friction=0.5f;
    body.createFixture(fixturedef);
    shape.dispose();

    //SET SPRITE POSITION
    sprite.setPosition(body.getPosition().x *PixelsToMeters - BODY_WIDTH/2, 
            body.getPosition().y * PixelsToMeters - BODY_HEIGHT/2);

    //THROW CIRCLE 
    body.setLinearVelocity(3.5f,9.5f);

    lastPosition=new Vector2();
    position=new Vector2();
    camera=new 

OrthographicCamera(Gdx.graphics.getWidth(),Gdx.graphics.getHeight());

    }

    @Override
    public void render () {
        camera.update();

        double newTime = TimeUtils.millis() / 1000.0;
        double frameTime = Math.min(newTime - currentTime, 0.25);
        float deltaTime = (float)frameTime;

        currentTime = newTime;
        accumulator+=deltaTime;

        while (accumulator >= step) {

            //SAVE LAST BODY POSITION AND ANGLE
            lastPosition.x=body.getPosition().x;
            lastPosition.y=body.getPosition().y;
            lastAngle=body.getAngle();

            world.step(step, 8, 3);
            accumulator -= step;
        }

        //SAVE CURRENT BODY POSITION AND ANGLE
        currentPosition= new Vector2(body.getPosition().x,body.getPosition().y);
        currentAngle=body.getAngle();

        alpha=(float) (accumulator/step);

        position.x = lastPosition.x + (currentPosition.x - lastPosition.x) * alpha;
        position.y = lastPosition.y + (currentPosition.y - lastPosition.y) * alpha;

        sprite.setPosition(position.x * PixelsToMeters - BODY_WIDTH/2, position.y * PixelsToMeters
                -BODY_HEIGHT/2);
        sprite.setRotation((float)Math.toDegrees(lastAngle+(currentAngle-lastAngle)*alpha));

    Gdx.gl.glClearColor(0, 0, 0, 0);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    batch.setProjectionMatrix(camera.combined);

    batch.begin();
        batch.draw(sprite, sprite.getX(), sprite.getY(),
                sprite.getOriginX(), sprite.getOriginY(),
                sprite.getWidth(), sprite.getHeight(), sprite.getScaleX(),
                sprite.getScaleY(), sprite.getRotation());
    batch.end();
    }

    @Override
    public void dispose() {
        world.dispose();
        batch.dispose();
        img.dispose();
        super.dispose();
    }
}

【问题讨论】:

  • 您是否尝试将精灵位置设置为身体的位置,而不是计算每帧的位置?可能是浮动问题,因为您在不同设备上的行为不同。

标签: java libgdx box2d interpolation fluid


【解决方案1】:

在使用 box2d 之前,我遇到了这个确切的问题,当物理步骤花费的时间超过 1/60 秒时会出现轻微的卡顿。

我也尝试过插值并阅读了很多关于它的文章,但没有任何成功。

最后我根本没有使用固定的时间步长(只是与世界步长的增量),并且使用 box2d 一切顺利。

但如果你还想使用固定步长,我有一些建议:

  • 使用Gdx.graphics.getDeltaTime(),因为它会为您提供包含前 n 帧的平滑增量。
  • 在世界步循环中使用 deltaTime:world.step(deltaTime, 8, 3);accumulator -= deltaTime

希望对你有帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多