Java libGDX不同大小的动画帧

时间:2017-07-03 18:02:30

标签: java android animation libgdx 2d-games

如何处理不同尺寸的相框?如果我在构造函数中设置了setBounds(0,0,100,100),那么一些帧会更小但如果我更新它,那么帧会向左和向上移动。如何使每一帧都在同一个地方?

你可以看到它 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());
}

}

2 个答案:

答案 0 :(得分:0)

您需要使用TextureAtlas提供的其他数据信息作为AtlasRegion。

  1. 每个关键帧的一个完整动画应具有相同的(宽度/高度)大小。选择最大的keyfarme适合的大小。还要注意正确定位。每个关键帧都有相同的轴心点。

  2. 为了避免在打包TextureAtlas时浪费空间,请启用“修剪”功能。应该有任何TexturePacker工具支持。

  3. 纹理数据文件(对于libGDX)则有如下条目:

  4. walk_animation
      rotate: false
      xy: 794, 235
      size: 86, 109
      orig: 160, 170
      offset: 37, 22
      index: 5
    
    1. 使用AtlasRegion以正确的大小和位置绘制内容:
    2. 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);
      

答案 1 :(得分: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() );
    }
}