2017-07-03 125 views
0

如何處理不同尺寸的幀?如果我在構造函數中設置了Bounds(0,0,100,100),那麼一些框架會更小,但是如果我更新它,那麼框架會向左和向上移動。如何讓每一幀都在同一個地方?Java libGDX不同尺寸的動畫幀

mayby你可以看到它 http://imgur.com/a/AN8Gc

public class Player extends Sprite{ 

//floats 
private float animationTimer; 

//box2d variables 
public World world; 
public Body body; 

//enums 
public enum State{STANDING, MOVING, SHOOTING, RELOAD, MALEE_ATTACK} 
public State currentState; 
public State previousState; 

//booleans 
boolean shoot; 
boolean reload; 
boolean maleeAttack; 

private TextureRegion region; 

public PlayScreen playScreen; 

public Player(PlayScreen playScreen){ 
    this.playScreen = playScreen; 
    this.world = playScreen.getWorld(); 
    definePlayer(); 

    animationTimer = 0; 

    region = Assets.instance.playerAssets.idleAniamtion.getKeyFrame(animationTimer); 

    setRegion(region); 
    setBounds(0, 0, getRegionWidth()/Constants.PPM, getRegionHeight()/Constants.PPM); 
    setPosition(0, 0); 

    currentState = State.STANDING; 
    previousState = State.STANDING; 

    shoot = false; 
    reload = false; 
    maleeAttack = false; 
} 

public void definePlayer(){ 
    BodyDef bodyDef = new BodyDef(); 
    bodyDef.position.set(100/Constants.PPM, 100/Constants.PPM); 
    bodyDef.type = BodyDef.BodyType.DynamicBody; 
    body = world.createBody(bodyDef); 

    FixtureDef fixtureDef = new FixtureDef(); 
    CircleShape shape = new CircleShape(); 
    shape.setRadius(50/Constants.PPM); 
    fixtureDef.shape = shape; 
    body.createFixture(fixtureDef).setUserData(this); 

    body.setLinearDamping(Constants.LINEAR_DAMPING); 
} 

public void update(float delta){ 
    region = Assets.instance.playerAssets.idleAniamtion.getKeyFrame(animationTimer); 
    setRegion(getFrame(delta)); 
    moving(); 
    //rotate(); 

} 

public void moving(){ 
    setPosition(body.getPosition().x - getWidth()/2, body.getPosition(). y - getHeight()/2); 
//setBounds(0, 0, getRegionWidth()/Constants.PPM, getRegionHeight()/Constants.PPM); update bounds 
    if (input.isKeyPressed(Input.Keys.W) && body.getLinearVelocity().y < 5){ 
     body.applyLinearImpulse(new Vector2(0, 1), body.getWorldCenter(), true); 
    } 
    if (input.isKeyPressed(Input.Keys.S) && body.getLinearVelocity().y > -5){ 
     body.applyLinearImpulse(new Vector2(0, -1), body.getWorldCenter(), true); 
    } 
    if (input.isKeyPressed(Input.Keys.D) && body.getLinearVelocity().x < 5){ 
     body.applyLinearImpulse(new Vector2(1, 0), body.getWorldCenter(), true); 
    } 
    if (input.isKeyPressed(Input.Keys.A) && body.getLinearVelocity().x > -5){ 
     body.applyLinearImpulse(new Vector2(-1, 0), body.getWorldCenter(), true); 
    } 
    if (Gdx.input.isKeyPressed(Input.Keys.R)){ 
     reload = true; 
    } 

    if (Gdx.input.isKeyPressed(Input.Keys.F)){ 
     maleeAttack = true; 
    } 
    if (Gdx.input.isButtonPressed(Input.Buttons.LEFT)){ 
     shoot = true; 
    } 

} 

public TextureRegion getFrame(float delta){ 
    TextureRegion region; 

    currentState = getState(); 

    switch (currentState){ 
     case MOVING: 
      region = Assets.instance.playerAssets.moveAnimation.getKeyFrame(animationTimer); 
      break; 
     case SHOOTING: 
      maleeAttack = false; 
      region = Assets.instance.playerAssets.shootAniamtion.getKeyFrame(animationTimer); 
      if (Assets.instance.playerAssets.shootAniamtion.isAnimationFinished(animationTimer)){ 
       shoot = false; 
      } 
      break; 
     case RELOAD: 
      region = Assets.instance.playerAssets.reloadAnimation.getKeyFrame(animationTimer); 
      if (Assets.instance.playerAssets.reloadAnimation.isAnimationFinished(animationTimer)){ 
       reload = false; 
      } 
      break; 
     case MALEE_ATTACK: 
      region = Assets.instance.playerAssets.maleeAttackAnimation.getKeyFrame(animationTimer); 
      if (Assets.instance.playerAssets.maleeAttackAnimation.isAnimationFinished(animationTimer)) { 
       maleeAttack = false; 
      } 
      break; 
     default: 
      region = Assets.instance.playerAssets.idleAniamtion.getKeyFrame(animationTimer); 
      break; 
    } 

    animationTimer = currentState == previousState ? animationTimer + delta : 0; 
    previousState = currentState; 

    return region; 
} 

public State getState(){ 
    if ((body.getLinearVelocity().x > 1 || body.getLinearVelocity().x < -1 || body.getLinearVelocity().y > 1 || body.getLinearVelocity().y < - 1) && !reload && !shoot && !maleeAttack){ 
     return State.MOVING; 
    } 
    if (shoot && !reload){ 
     return State.SHOOTING; 
    } 
    if (reload && !maleeAttack){ 
     return State.RELOAD; 
    } 
    if (maleeAttack){ 
     return State.MALEE_ATTACK; 
    } 
    else { 
     return State.STANDING; 
    } 
} 

public Vector2 getMousePosition(){ 
    Vector2 mousePosition; 
    mousePosition = playScreen.getViewport().unproject(new Vector2(Gdx.input.getX(), Gdx.input.getY())); 
    return mousePosition; 
} 

public float getMouseAngle(){ 
    float angle = (float) Math.atan2(getMousePosition().y - body.getPosition().y, getMousePosition().x - body.getPosition().x); 
    return angle; 
} 

public void rotate(){ 
    setOrigin(getWidth()/2, getHeight()/2); 
    setRotation((float) (getMouseAngle() * (180/Math.PI))); 
    body.setTransform(body.getPosition(), getMouseAngle()); 
} 

}

+0

您使用的是視口還是虛擬屏幕? –

+0

是的,我使用的是ExtendViewport。 – misza

回答

0

您需要使用額外的數據信息TextureAtlas提供作爲AtlasRegion。

  1. 一個完整的動畫必須爲每個關鍵幀是相同的(寬度/高度)的大小。選擇最大的關鍵詞適合的尺寸。也要注意正確定位。每個關鍵幀都有相同的支點。

  2. 爲了避免在打包TextureAtlas時啓用「trim」功能而浪費空間。應該由任何TexturePacker工具支持。

  3. 紋理數據文件(libGDX)於是具有條目是這樣的:

walk_animation 
    rotate: false 
    xy: 794, 235 
    size: 86, 109 
    orig: 160, 170 
    offset: 37, 22 
    index: 5 
  • 使用在繪製的東西AtlasRegion正確的尺寸和位置:
  • float width = 400; // pick your size here 
    float height = 300; 
    
    float offsetPctX = atlasRegion.offsetX/atlasRegion.originalWidth; 
    float offsetPctY = atlasRegion.offsetY/atlasRegion.originalHeight; 
    
    float scaleWidth = (float) atlasRegion.packedWidth/atlasRegion.originalWidth; 
    float scaleHeight = (float) atlasRegion.packedHeight/atlasRegion.originalHeight; 
    
    float drawWidth = width * scaleWidth; 
    float drawHeight = height * scaleHeight; 
    
    float regionOffsetX = offsetPctX * width; 
    float regionOffsetY = offsetPctY * height; 
    
    float drawScaleX = 1; // adjust to your needs 
    float drawScaleY = 1; 
    
    
    float drawOriginX = 0; // adjust to tour needs 
    float drawOriginY = 0; 
    
    float drawRotation = false; 
    
    float x = 100 + offsetX + regionOffsetX; // adjust to your needs 
    float y = 100 + offsetY + regionOffsetY; 
    
    spriteBatch.draw(atlasRegion, x, y, drawOriginX, drawOriginY, drawWidth, drawHeight, drawScaleX, drawScaleY, drawRotation); 
    
    +0

    什麼是遙控器,我對此有錯誤。如果我有兩個動畫但尺寸不同,我可以使用這個嗎?一個更大,「跳」一點左上corrner。 – misza

    +0

    我刪除了rc。部分。 offsetX/Y只是您爲精靈設置的偏移號。不使用時將其保留爲0。這是我的其中一個項目的代碼,其中動畫幀有時具有不同的大小。 –

    0

    爲了避免調整紋理大小,只需創建一個用於設置邊界的變量大小。界限需要設置每一幀。

    public class Player extends Sprite { 
    
        private Body body; 
        private Vector2 size; 
    
        public Player(){ 
    
         this.size = new Vector2(getRegionWidth()/Constants.PPM, getRegionHeight()/Constants.PPM); 
        } 
    
        public void update(float delta){ 
    
         Vector2 position = body.getPosition(); 
    
         setRegion(getFrame(delta)); 
         setRotation(MathUtils.radDeg * body.getAngle()); 
         setBounds(position.x, position.y, size.x, size.y); 
         setOriginCenter(); 
        } 
    
        public void rotate(){ 
    
         this.body.setTransform(body.getPosition(), getMouseAngle()); 
        } 
    } 
    
    +0

    如果我設置綁定每一幀然後幀「跳」(setbouds(posistion.x,position.y,getWidth,getHeight)),如果我喜歡你,然後幀仍然調整大小,因爲邊界仍然是相同的大小。 – misza

    +0

    我曾嘗試使用精靈類,但不知何故,它不正確渲染。它創造了很多你不需要的開銷。只需使用batch.draw(),而不是比sprite.draw()更容易調試。 – Tejay