2015-08-05 1 views
0

Я разработчик игр для новичков. Я пытался разработать игру с использованием физических движков LibGDX и Box2D, но когда я экспортирую приложение для Android, он не работает так, как должно быть.LAG: не движение жидкости на JAVA Box2D игра

Эта проблема возникает в некоторых устройствах; это не имеет значения, если это старое устройство или новое.

Например, приложение хорошо работает в Sony Xperia Z1, Motorola XT615, LG L1, LG L3, LG L5 и т. Д. Однако в Sony Xperia U, Motorola Moto E, Samsung 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(); 
    } 
} 
+0

Вы пытались установить положение спрайтов в положение тела, а не вычислять положение каждого кадра? Это может быть проблема с поплавком, так как вы получаете другое поведение на разных устройствах. –

ответ

0

Я имел эту точно проблему перед использованием box2d, небольшой заикание, когда шаги физики заняло больше времени, чем 1/60 секунды.

Я также пробовал интерполяцию и читал много статей об этом без каких-либо успехов.

В конце я не использую фиксированный timestep вообще (просто дельта к шагу мира), и все идет гладко с box2d.

Но если вы все же хотите использовать фиксированный шаг, у меня есть несколько предложений:

  • Используйте Gdx.graphics.getDeltaTime(), поскольку это дает вам сглаженной дельту с п предыдущих кадров.
  • Используйте deltaTime в шаге мирового шага: world.step(deltaTime, 8, 3); и accumulator -= deltaTime.

Надеюсь, это поможет!