LibGDX翻转二维精灵动画
LibGDX Flip 2D Sprite Animation
我有一个动画,我想在用户按下键盘上的 'A' 键时翻转播放。动画在文件中面向右侧并正常播放,直到我尝试翻转纹理。
这是当我尝试在玩家方向改变时翻转纹理时发生的情况:
如您所见,动画一开始播放得很好,但当我改变播放器的方向时,它会在翻转帧和未翻转帧之间交替。
这是我的播放器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;
}
}
在我的渲染方法中,我正在检查玩家的方向是否向左,如果是则翻转当前动画帧。
这是我处理输入的方式:
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();
}
}
我已经尝试解决这个问题几个小时了,但没有取得任何进展。知道为什么会这样吗?
问题出在这里:
if(getDirection() == Direction.LEFT) {
currentFrame.flip(true, false);
}
flip
方法永久翻转动画 class 引用的原始 TextureRegion。所以你要么需要确保每次翻转和绘制后都将其翻转回来,要么这样做,我认为这更简单:
不要翻转它,而是在使用 SpriteBatch 绘制时使用负宽度,如下所示:
boolean flip = (getDirection() == Direction.LEFT);
spriteBatch.draw(currentFrame, flip ? x+width : x, y, flip ? -width : width, height);
我知道这个问题很老,但我认为这是更好的解决方案
currentFrame = walkAnimation.getKeyFrame(stateTime, true);
if(!currentFrame.isFlipX())
currentFrame.flip(true, false);
batch.draw(currentFrame, 0,0,0,0);
如果有人仍然想知道,否定 scaleX 或 scaleY 就像一个魅力,并且不会损害性能(例如 TextureRegion.flip 会)。
示例:
draw(region, x, y, originX, originY, width, float height,
(flip ? -1 : 1) * scaleX, float scaleY, float rotation);
我使用下面的代码(在 kotlin
中)翻转我的动画序列:
if (this.position <= 0f)
{
this.speed = - this.speed
this.position = 0.0f
this.runAnimation.keyFrames.forEach {
it.flip(true, false)
}
}else if(this.position >= SCREEN_WIDTH / SCALE - width)
{
this.speed = - this.speed
this.position = SCREEN_WIDTH / SCALE - width
this.runAnimation.keyFrames.forEach {
it.flip(true, false)
}
}
this.game.batch.begin()
this.game.batch.draw(currentFrame, this.position, 40f)
this.game.batch.end()
每次翻转序列时,确保循环每一帧并翻转每一帧:
this.runAnimation.keyFrames.forEach { it.flip(true, false) }
请记住,帧会永远翻转,所以如果你想return返回,你应该再次翻转(flip = true
)!
我有一个动画,我想在用户按下键盘上的 'A' 键时翻转播放。动画在文件中面向右侧并正常播放,直到我尝试翻转纹理。
这是当我尝试在玩家方向改变时翻转纹理时发生的情况:
如您所见,动画一开始播放得很好,但当我改变播放器的方向时,它会在翻转帧和未翻转帧之间交替。
这是我的播放器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;
}
}
在我的渲染方法中,我正在检查玩家的方向是否向左,如果是则翻转当前动画帧。
这是我处理输入的方式:
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();
}
}
我已经尝试解决这个问题几个小时了,但没有取得任何进展。知道为什么会这样吗?
问题出在这里:
if(getDirection() == Direction.LEFT) {
currentFrame.flip(true, false);
}
flip
方法永久翻转动画 class 引用的原始 TextureRegion。所以你要么需要确保每次翻转和绘制后都将其翻转回来,要么这样做,我认为这更简单:
不要翻转它,而是在使用 SpriteBatch 绘制时使用负宽度,如下所示:
boolean flip = (getDirection() == Direction.LEFT);
spriteBatch.draw(currentFrame, flip ? x+width : x, y, flip ? -width : width, height);
我知道这个问题很老,但我认为这是更好的解决方案
currentFrame = walkAnimation.getKeyFrame(stateTime, true);
if(!currentFrame.isFlipX())
currentFrame.flip(true, false);
batch.draw(currentFrame, 0,0,0,0);
如果有人仍然想知道,否定 scaleX 或 scaleY 就像一个魅力,并且不会损害性能(例如 TextureRegion.flip 会)。
示例:
draw(region, x, y, originX, originY, width, float height,
(flip ? -1 : 1) * scaleX, float scaleY, float rotation);
我使用下面的代码(在 kotlin
中)翻转我的动画序列:
if (this.position <= 0f)
{
this.speed = - this.speed
this.position = 0.0f
this.runAnimation.keyFrames.forEach {
it.flip(true, false)
}
}else if(this.position >= SCREEN_WIDTH / SCALE - width)
{
this.speed = - this.speed
this.position = SCREEN_WIDTH / SCALE - width
this.runAnimation.keyFrames.forEach {
it.flip(true, false)
}
}
this.game.batch.begin()
this.game.batch.draw(currentFrame, this.position, 40f)
this.game.batch.end()
每次翻转序列时,确保循环每一帧并翻转每一帧:
this.runAnimation.keyFrames.forEach { it.flip(true, false) }
请记住,帧会永远翻转,所以如果你想return返回,你应该再次翻转(flip = true
)!