LibGDX Flip 2D Sprite Animation

I have an animation that I want to play flipped if the user presses the 'A' key on their keyboard. The animation is facing right in the file and is played normally until I try to flip the texture.

This is what happens when I try to flip the texture when the player's direction has changed:

As you can see, the animation plays fine in the beginning but when I change the player's direction it alternates between the flipped frame and the unflipped frame.

This is my player class:

package unit22.game;

import java.util.ArrayList;

import unit22.core.Utils;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;

public class Player {

    private PlayerState state = PlayerState.STANDING;
    private Direction direction = Direction.RIGHT;
    private int x = 0, y = 0, width = 0, height = 0;
    private PlayerInputProcessor inputProcessor;
    private String name;

    private ArrayList<Action> actions;
    private Animation standingAnim;
    private Animation movingAnim;
    private float stateTime;
    private SpriteBatch spriteBatch;

    private Action currentAction;
    private Animation currentAnimation;

    public Player(String name, int x, int y, int width, int height) {
        this.name = name;
        setBounds(x, y, width, height);

        if(getX() > 400) setDirection(Direction.LEFT);

        this.actions = new ArrayList<Action>();

        standingAnim = new Animation(0.06f, Utils.loadTextureAtlas("standing", "textures/characters/animations/" + name + "/").getRegions());
        //movingAnim = new Animation(0.06f, Utils.loadTextureAtlas("moving", "textures/characters/animations/" + name + "/").getRegions());

        stateTime = 0f;
        spriteBatch = new SpriteBatch();
    }

    public void update() {
        stateTime += Gdx.graphics.getDeltaTime();
        switch(state) {
            case STANDING:
                if(currentAnimation != standingAnim)
                    currentAnimation = standingAnim;
                break;
            case MOVING:
                if(currentAnimation != movingAnim)
                    currentAnimation = movingAnim;
                break;
            case ACTING:
                Animation anim = new Animation(0.06f, Utils.loadTextureAtlas(currentAction.getName(), "textures/characters/animations/" + getName() + "/").getRegions());
                if(currentAnimation != anim)
                    currentAnimation = anim;
                break;
        }

    }

    public void render() {
        TextureRegion currentFrame = currentAnimation.getKeyFrame(stateTime, true);

        if(getDirection() == Direction.LEFT) {
            currentFrame.flip(true, false);
        }

        System.out.println("Direction: " + direction + ", Flipped: " + currentFrame.isFlipX());

        spriteBatch.begin();

        spriteBatch.draw(currentFrame, x, y, width, height);

        spriteBatch.end();
    }

    public ArrayList<Action> getActions() {
        return actions;
    }

    public void addAction(Action action) {
        this.actions.add(action);
    }

    public void setActions(ArrayList<Action> actions) {
        this.actions = actions;
    }

    public void setInputProcessor(PlayerInputProcessor inputProcessor) {
        this.inputProcessor = inputProcessor;
    }

    public PlayerInputProcessor getInputProcessor() {
        return inputProcessor;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public Direction getDirection() {
        return direction;
    }

    public PlayerState getState() {
        return state;
    }

    public void setDirection(Direction direction) {
        this.direction = direction;
    }

    public void setState(PlayerState state) {
        this.state = state;
    }

    public int[] getBounds() {
        return new int[] {x, y, width, height};
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    public void setBounds(int x, int y, int width, int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public void setHeight(int height) {
        this.height = height;
    }

}

In my render method I am checking whether the player's direction is left and if it is then to flip the current animation frame.

This is how I am handling my input:

package unit22.screens;

import unit22.core.Game;
import unit22.core.Screen;
import unit22.game.Direction;
import unit22.game.Player;
import unit22.game.PlayerInputProcessor;

import com.badlogic.gdx.Gdx;

public class Playing extends Screen {

    Player player;

    public Playing(Game game, String name) {
        super(game, name);
    }

    @Override
    public void init() {


        player = new Player("misaka", 100, 100, 188, 380);

        player.setInputProcessor(new PlayerInputProcessor(player) {
            @Override
            public boolean keyTyped(char character) {
                if(getPlayer().getX() <= 14) getPlayer().setX(15);
                if(getPlayer().getX() + getPlayer().getWidth() >= 1024 - getPlayer().getWidth()) getPlayer().setX(1024 - getPlayer().getWidth() - 15);

                if(character == 'a' || character == 'A') {
                    getPlayer().setX((int)(getPlayer().getX() - (900 * Gdx.graphics.getDeltaTime())));
                    if(getPlayer().getDirection() == Direction.RIGHT) {
                        getPlayer().setDirection(Direction.LEFT);
                    }
                }

                if(character == 'd' || character == 'D') {
                    getPlayer().setX((int)(getPlayer().getX() + (900 * Gdx.graphics.getDeltaTime())));
                    if(getPlayer().getDirection() == Direction.LEFT) {
                        getPlayer().setDirection(Direction.RIGHT);
                    }
                }

                return super.keyTyped(character);
            }
        });

        getInputHandle().addProcessor(player.getInputProcessor());
    }

    @Override
    public void render(float delta) {
        super.render(delta);

        player.update();
        player.render();
    }

}

I've been trying to figure this problem out for a couple of hours now and haven't made any progress. Any idea why this would be happening?

Answers


The problem is here:

if(getDirection() == Direction.LEFT) {
    currentFrame.flip(true, false);
}

The flip method permanently flips the original TextureRegion that the Animation class is referencing. So you either need to make sure you flip it back each time after flipping and drawing it, or do this, which I think is simpler:

Never flip it but instead use a negative width when drawing it with SpriteBatch, like this:

boolean flip = (getDirection() == Direction.LEFT);
spriteBatch.draw(currentFrame, flip ? x+width : x, y, flip ? -width : width, height);

Need Your Help

How to get form input, using javascript and jquery

php javascript jquery html

I am using php for filling some data in below div tag

links not woking in horizontal menus

jquery html css

My horizontal links are not working properly after adding an auto-slider using JQuery

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.