LAG:JAVA Box2D游戏不流动

时间:2015-08-05 00:38:32

标签: java libgdx box2d interpolation fluid

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

某些设备会出现此问题;如果它是旧设备或新设备并不重要。

例如,该应用程序在Sony Xperia Z1,Motorola 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/

学习固定时间步和插值方法,但我认为我的代码中有一个我无法看到的失败。

这是我的代码:

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();
    }
}

1 个答案:

答案 0 :(得分:0)

在使用box2d之前我遇到了这个问题,当物理步骤耗时超过1/60秒时,小口吃。

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

最后,我根本没有使用固定的时间步长(只是delta到世界步骤),所有这一切都顺利用box2d。

但如果您仍想使用固定步骤,我有一些建议:

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

希望它有所帮助!