1
\$\begingroup\$

I am making a 'simple' top-down space shooter in 2d using Libgdx. I have loaded the texture regions into arrays and created Animations inside my sprite, but when I call the getKeyFrame it seems to jump straight to the last frame in the spritesheet.

The spritesheet is 9 frames in total of a spaceship banking to the left (hence I have enabled FlipX for when turning the other way. But all works as I expected apart from that it just jumps to the last frame in the sequence rather than the gradual banking animation.

The class in question is below, please do let me know if you need to view the rest of the code:

package com.moneylife.spaceattackers.Sprites;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.Array;
import com.moneylife.spaceattackers.Screens.PlayScreen;

public class Player extends Sprite {
private PlayScreen playScreen;
private Animation bankRight, bankLeft;
private int totalFrames = 9;
private int frameWidth = 100, frameHeight = 100;
private float frameDuration = 0.3f;
private TextureRegion straightFlyingTextureRegion;

enum flyState { STRAIGHT, LEFT, RIGHT }
private flyState currentFlyState;

public Player(PlayScreen playScreen){
    super(new Texture("ship.png"));
    currentFlyState = flyState.STRAIGHT;
    this.playScreen = playScreen;
    Array<TextureRegion> frames = new Array<TextureRegion>();
    for (int i = 0; i < totalFrames; i++){
        frames.add(new TextureRegion(getTexture(), i * frameWidth, 0, frameWidth, frameHeight));
        bankLeft = new Animation(frameDuration, frames);
        frames.clear();
    }
    for (int i = 0; i < totalFrames; i++){
        TextureRegion region = new TextureRegion(getTexture(), i * frameWidth, 0, frameWidth, frameHeight);
        region.flip(true, false);
        frames.add(region);
        bankRight = new Animation(frameDuration, frames);
        frames.clear();
    }
    straightFlyingTextureRegion =  new TextureRegion(getTexture(),0,0,frameWidth, frameHeight);
    setPosition(playScreen.viewport.getWorldWidth() / 2 - frameWidth / 2,0);
    setRegion(straightFlyingTextureRegion);

    bankLeft.setPlayMode(Animation.PlayMode.NORMAL);
    bankRight.setPlayMode(Animation.PlayMode.NORMAL);
}

public void update(float dt){
    switch (currentFlyState){
        case STRAIGHT: {
            setRegion(straightFlyingTextureRegion);
            setSize(frameWidth, frameHeight);
            break;
        }
        case LEFT: {
            setRegion(bankLeft.getKeyFrame(frameDuration, false));
            break;
        }
        case RIGHT: {
            setRegion(bankRight.getKeyFrame(frameDuration, false));
            break;
        }
    }
    if (Gdx.input.isKeyPressed(Input.Keys.A)){
        currentFlyState = flyState.LEFT;
    }
    else if (Gdx.input.isKeyPressed(Input.Keys.D)){
        currentFlyState = flyState.RIGHT;
    }
    else
        currentFlyState = flyState.STRAIGHT;
    }
}

I beleive that the issue must be in the frames.add part (is it perhaps overwriting each frame with the other until the end??) but I cant figure out how to fix this. Can somebody please see what I am missing here?

EDIT: I have also tried moving " bankLeft = new Animation(frameDuration, frames); frames.clear();" moving that from the For loops to just below the for loop. But that meant I only got the 2nd frame in the animation only for some reason :S So my constructor now looks like this, but neither work as needed :(

    public Player(PlayScreen playScreen){
        super(new Texture("ship.png"));
    currentFlyState = flyState.STRAIGHT;
    this.playScreen = playScreen;
    Array<TextureRegion> frames = new Array<TextureRegion>();
    for (int i = 0; i < totalFrames; i++){
        frames.add(new TextureRegion(getTexture(), i * frameWidth, 0, frameWidth, frameHeight));
    }
    bankLeft = new Animation(frameDuration, frames);
    frames.clear();
    for (int i = 0; i < totalFrames; i++){
        TextureRegion region = new TextureRegion(getTexture(), i * frameWidth, 0, frameWidth, frameHeight);
        region.flip(true, false);
        frames.add(region);
    }
    bankRight = new Animation(frameDuration, frames);
    frames.clear();



    straightFlyingTextureRegion =  new TextureRegion(getTexture(),0,0,frameWidth, frameHeight);
    setPosition(playScreen.viewport.getWorldWidth() / 2 - frameWidth / 2,0);
    setRegion(straightFlyingTextureRegion);

    bankLeft.setPlayMode(Animation.PlayMode.NORMAL);
    bankRight.setPlayMode(Animation.PlayMode.NORMAL);
    setSize(frameWidth, frameHeight);
}
\$\endgroup\$
0
\$\begingroup\$
public TextureRegion getKeyFrame (float stateTime, boolean looping)

It doesn't take a 'frame time' - it takes the time now (and you should add delta time to it every frame).

Instead of calliing

setRegion(bankLeft.getKeyFrame(frameDuration, false));

change the frameDuration name for stateTime and make it 0f in constructor:

float stateTime = 0f;

in update call:

stateTime += dt;
setRegion(bankLeft.getKeyFrame(stateTime, false)); // for both cases

And you're ready to go! Also, move your new Animation, frames.add() and frames.clear() outside of loops.

Edit

Now I read it all. You can keep your frameDuration (make it final) - and pass it to the Animation's constructors, but make another variable like stateTime as I said. Here's your rewritten code: (I wrote //fix where I did a fix!)

public class Player extends Sprite {
private PlayScreen playScreen;
private Animation bankRight, bankLeft;
private int totalFrames = 9;
private int frameWidth = 100, frameHeight = 100;
private final float FRAME_DURATION = 0.3f; // each frame will last 0.3f
private final float stateTime = 0f; // fix
private TextureRegion straightFlyingTextureRegion;

enum flyState { STRAIGHT, LEFT, RIGHT }
private flyState currentFlyState;

public Player(PlayScreen playScreen){
    super(new Texture("ship.png"));
    currentFlyState = flyState.STRAIGHT;
    this.playScreen = playScreen;
    Array<TextureRegion> frames = new Array<TextureRegion>();
    for (int i = 0; i < totalFrames; i++){
        frames.add(new TextureRegion(getTexture(), i * frameWidth, 0, frameWidth, frameHeight));
    }
    bankLeft = new Animation(FRAME_DURATION, frames); // fix
    frames.clear();

    for (int i = 0; i < totalFrames; i++){
        TextureRegion region = new TextureRegion(getTexture(), i * frameWidth, 0, frameWidth, frameHeight);
        region.flip(true, false);
        frames.add(region);
    }
     bankRight = new Animation(FRAME_DURATION, frames); // fix
    frames.clear();

    straightFlyingTextureRegion =  new     TextureRegion(getTexture(),0,0,frameWidth, frameHeight);
    setPosition(playScreen.viewport.getWorldWidth() / 2 - frameWidth / 2,0);
    setRegion(straightFlyingTextureRegion);

    bankLeft.setPlayMode(Animation.PlayMode.NORMAL);
    bankRight.setPlayMode(Animation.PlayMode.NORMAL);
}

public void update(float dt){

    stateTime += dt; // fix
    switch (currentFlyState){
    case STRAIGHT: {
        setRegion(straightFlyingTextureRegion);
        setSize(frameWidth, frameHeight);
        break;
    }
    case LEFT: {
        setRegion(bankLeft.getKeyFrame(stateTime, false)); // fix
        break;
    }
    case RIGHT: {
        setRegion(bankRight.getKeyFrame(stateTime, false)); // fix
        break;
    }
}
if (Gdx.input.isKeyPressed(Input.Keys.A)){
    currentFlyState = flyState.LEFT;
\$\endgroup\$
  • \$\begingroup\$ Thanks so much for the answer. As it happens I did notice this needs to be 'stateTime' when making call to getKeyFrame . I figured it out late last night (/this morning lol) and hadn't had time to type it up here. By the way I also had to reset the stateTime variable each time the flyState goes back to STRAIGHT I had to put line stateTime = 0f; in that (luckily I didnt need animation for that :D ) \$\endgroup\$ – Big T Larrity Oct 30 '16 at 13:01
  • \$\begingroup\$ Well done! Read the whole GDX github wiki about implementing animations and rendering, there have alot of examples ;) And place and upvote if you like the answer! :D Good luck \$\endgroup\$ – Jacob Oct 30 '16 at 15:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.