在切换到另一个之前等待动画完成?

问题描述:

我使用keyupkeyDown来替换我的游戏精灵的不同动画。在keyDown上,精灵根据按下什么键来切换动画,当keyUp时,精灵切换回空闲动画。它适用于较小的动画,如走路,但当动画稍长时,只要释放按键,精灵就会返回闲置动画,而无需完成上一个动画。我如何实现这一点?我尝试阅读libgdx的动画文档,但方法isAnimationFinished不是我所需要的。在切换到另一个之前等待动画完成?

package com.mygdx.game; 

import com.badlogic.gdx.ApplicationAdapter; 
import com.badlogic.gdx.Gdx; 
import com.badlogic.gdx.Input; 
import com.badlogic.gdx.InputProcessor; 
import com.badlogic.gdx.graphics.GL20; 
import com.badlogic.gdx.graphics.OrthographicCamera; 
import com.badlogic.gdx.graphics.g2d.Animation; 
import com.badlogic.gdx.graphics.g2d.SpriteBatch; 
import com.badlogic.gdx.graphics.g2d.TextureAtlas; 
import com.badlogic.gdx.maps.tiled.TiledMap; 
import com.badlogic.gdx.maps.tiled.TiledMapRenderer; 
import com.badlogic.gdx.maps.tiled.TmxMapLoader; 
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer; 

public class MyGdxGame extends ApplicationAdapter implements InputProcessor { 
    private SpriteBatch batch; 
    private TextureAtlas textureAtlas; 
    private Animation animation; 
    private Animation animation2; 
    private Animation animation3; 
    private Animation currentAnimation; 
    private float elapsedTime = 0; 
    TiledMap tiledMap; 
    OrthographicCamera camera; 
    TiledMapRenderer tiledMapRenderer; 


    int[] pos = {30,30}; 
    int acc = 0; 
    int acc_cam = 0; 

    @Override 
    public void create() { 
     batch = new SpriteBatch(); 
     textureAtlas = new TextureAtlas(Gdx.files.internal("Wolverine.txt")); 
//  textureAtlas = new TextureAtlas(Gdx.files.internal("spritesheet.atlas")); 
//  textureAtlas2 = new TextureAtlas(Gdx.files.internal("spritesheet(copy).atlas")); 
//  animation = new Animation(1/7f, textureAtlas.getRegions()); 
//  animation2 = new Animation(1/7f, textureAtlas2.getRegions()); 
     animation = new Animation(1/7f, textureAtlas.findRegions("Standing")); 
     animation2 = new Animation(1/7f, textureAtlas.findRegions("Walking")); 
     animation3 = new Animation(1/15f, textureAtlas.findRegions("Attcak_Stand")); 
     currentAnimation = animation; 

     camera = new OrthographicCamera(); 
     camera.setToOrtho(false, 640, 480); 


     tiledMap = new TmxMapLoader().load("Tiled_tilesheet2.tmx"); 
     tiledMapRenderer = new OrthogonalTiledMapRenderer(tiledMap); 


     Gdx.input.setInputProcessor(this); 
    } 

    @Override 
    public void dispose() { 
     batch.dispose(); 
     tiledMap.dispose(); 
     textureAtlas.dispose(); 
    } 

    @Override 
    public void render() { 

     pos[0] += acc; 
     camera.translate(acc_cam,0); 

     Gdx.gl.glClearColor(0, 0, 0, 1); 
     Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 

     camera.update(); 
     tiledMapRenderer.setView(camera); 
     tiledMapRenderer.render(); 
     batch.begin(); 

     //sprite.draw(batch); 
     elapsedTime += Gdx.graphics.getDeltaTime(); 
     batch.draw(currentAnimation.getKeyFrame(elapsedTime, true), pos[0],pos[1]); 
     batch.end(); 
    } 

    @Override 
    public void resize(int width, int height) { 
    } 

    @Override 
    public void pause() { 
    } 

    @Override 
    public void resume() { 
    } 

    @Override 
    public boolean keyDown(int keycode) { 
     if (keycode == Input.Keys.RIGHT) { 
      currentAnimation = animation2; 
      if(pos[0]>320){acc_cam+=2;} 
      else{acc += 2;} 

     } 
     else if(keycode == Input.Keys.Z){ 
      currentAnimation = animation3; 

     } 
     return true; 

    } 

    @Override 
    public boolean keyUp(int keycode) { 
     currentAnimation = animation; 
     acc_cam=0; 
     acc = 0; 

     return false; 
    } 

    @Override 
    public boolean keyTyped(char character) { 
     return false; 
    } 

    @Override 
    public boolean touchDown(int screenX, int screenY, int pointer, int button) { 
     return false; 
    } 

    @Override 
    public boolean touchUp(int screenX, int screenY, int pointer, int button) { 
     return false; 
    } 

    @Override 
    public boolean touchDragged(int screenX, int screenY, int pointer) { 
     return false; 
    } 

    @Override 
    public boolean mouseMoved(int screenX, int screenY) { 
     return false; 
    } 

    @Override 
    public boolean scrolled(int amount) { 
     return false; 
    } 
} 

在完成当前动画(如回调)时,Animation类没有办法通知您。 isAnimationFinished()会告诉你,如果PlayMode#NORMAL中的动画完成,我相信你的动画设置为你的构造函数不会指示它们LOOP。

您的渲染代码总是绘制一个基于键输入设置的动画。所以这就是为什么当前动画会突然停止,因为您正在告诉它立即切换。

我不知道你的各种动画(长度,何时调用等)的计划是。您可能需要重构代码以确定要完成哪些动画,以及这与您的其他动画或关键输入策略如何相关,等等。一个简单的解决方案可能是基于某些键输入设置“下一个动画”,并让您的代码检查当前动画以查看它是否完成(使用isAnimationeFinished - 您必须在每帧中执行此操作)。如果完成,则将下一个动画换成当前动画。如果你循环动画,你也必须将其纳入你的逻辑。

另一种选择是编写自己的回调/监听器代码来告诉你动画何时完成。向下滚动(几乎在最后)这篇文章的一些想法:http://www.rengelbert.com/tutorial.php?id=179

也可能有其他几个选项,但都取决于你想如何过渡你的动画,只有你知道,因为一些你的动画非常短暂,持续很长时间,并且基于你在游戏中创建的输入而改变。