程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Libgdx之Animation 動畫

Libgdx之Animation 動畫

編輯:JAVA綜合教程

Libgdx之Animation 動畫


一個好的游戲總歸需要動畫,Libgdx提供了Animation類來管理控制動畫。
Animation: 儲存了一組TextureRegion,然後順序播放。例如在主角奔跑、跳躍的時候都需要用到Animation。每一個TextureRegion都是一幀,多幀組成了一組動畫。

Animation的簡單說明

這裡寫圖片描述    這裡寫圖片描述
上面的兩幅圖來自官方的wiki。 每個紅色方框代表這一幀動畫,代表了一個角色的一個跑步過程。我們將會用TextureRegion中split方法來切割這個圖片。
在Animation中有一個參數 frameDuration 這個代表了每一幀圖片在屏幕上顯示的時間。1/frameDuration 就是幀率,也就是一秒鐘顯示多少幅圖片。

Animationd 播放模式

NORMAL:這個不用說了,就是正常的播放模式。 REVERSED:反向播放,從後向前播放,這個就像人物倒退的跑。 LOOP:持續播放,這個比較常用。 LOOP_REVERSED:持續倒退播放。 LOOP_PINGPONG: 向前播放幾張圖片,再向後播放幾幀圖片。
這裡要注意一下,默認的初始化方法中只有一個是要初始化播放模式的,其余的默認都是PlayMode.NORMAL。這時可以通過setPlayMode方法來設置或者要通過獲取關鍵幀的時候指定public TextureRegion getKeyFrame (float stateTime, boolean looping),如果此處設置為true,那麼就設置PlayMode.LOOP

stateTime 的說明

在很多示例代碼中都設置了這個stateTime,現在說說我的理解,stateTime就是一個時間計數器,初始化為stateTime=0

    /** Returns the current frame number.
     * @param stateTime
     * @return current frame number */
    public int getKeyFrameIndex (float stateTime) {
        if (keyFrames.length == 1) return 0;

        int frameNumber = (int)(stateTime / frameDuration);
        switch (playMode) {
        case NORMAL:
            frameNumber = Math.min(keyFrames.length - 1, frameNumber);
            break;
        case LOOP:
            frameNumber = frameNumber % keyFrames.length;
            break;
        case LOOP_PINGPONG:
            frameNumber = frameNumber % ((keyFrames.length * 2) - 2);
            if (frameNumber >= keyFrames.length) frameNumber = keyFrames.length - 2 - (frameNumber - keyFrames.length);
            break;
        case LOOP_RANDOM:
            int lastFrameNumber = (int) ((lastStateTime) / frameDuration);
            if (lastFrameNumber != frameNumber) {
                frameNumber = MathUtils.random(keyFrames.length - 1);
            } else {
                frameNumber = this.lastFrameNumber;
            }
            break;
        case REVERSED:
            frameNumber = Math.max(keyFrames.length - frameNumber - 1, 0);
            break;
        case LOOP_REVERSED:
            frameNumber = frameNumber % keyFrames.length;
            frameNumber = keyFrames.length - frameNumber - 1;
            break;
        }

        lastFrameNumber = frameNumber;
        lastStateTime = stateTime;

        return frameNumber;
    }

通過源碼可以指定stateTime計算從開始播放動畫開始,我們要計算經過多少個FPS時我們應該顯示下一幀動畫。

下面是測試代碼

private static final String TAG = AnimationTest.class.getSimpleName();

    private static final int FRAME_COLS = 6; // 用來做動畫的圖片有6*5
    private static final int FRAME_ROWS = 5; // #2

    Animation walkAnimation; // 定義Animation對象,用來裝載TextureRegion
    Animation reverseWalkAnimation;
    Texture walkSheet; // 裝載6*5的圖片
    TextureRegion[] walkFrames;
    SpriteBatch spriteBatch;
    TextureRegion currentFrame; // 記錄關鍵幀,即當前要在batch畫出的TextureRegion
    Vector2 postion;
    Direction direction;

    float stateTime; // 記錄動畫時間

    @Override
    public void create() {
        walkSheet = new Texture(Gdx.files.internal("sprite-animation1.png")); // #9
        TextureRegion[][] tmp = TextureRegion.split(walkSheet, walkSheet.getWidth() / FRAME_COLS, walkSheet.getHeight() / FRAME_ROWS); // #10
        walkFrames = new TextureRegion[FRAME_COLS * FRAME_ROWS];
        int index = 0;
        for (int i = 0; i < FRAME_ROWS; i++) {
            for (int j = 0; j < FRAME_COLS; j++) {
                walkFrames[index++] = tmp[i][j];
            }
        }
        walkAnimation = new Animation(0.025f, walkFrames); // #11
        spriteBatch = new SpriteBatch(); // #12
        postion = new Vector2(50, 50);
        direction = Direction.RIGHT;
        stateTime = 0f; // #13

        Gdx.app.log(TAG, "frameDuration=" + walkAnimation.getFrameDuration());
        Gdx.app.log(TAG, "frameDuration=" + walkAnimation.getAnimationDuration());
    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(0.39f, 0.58f, 0.92f, 1.0f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);// #14

        stateTime += Gdx.graphics.getDeltaTime(); // #15
        if (direction == Direction.RIGHT) {
            postion.x += 50 * Gdx.graphics.getDeltaTime();
            walkAnimation.setPlayMode(PlayMode.LOOP);
        } else if (direction == Direction.LEFT) {
            postion.x -= 50 * Gdx.graphics.getDeltaTime();
            walkAnimation.setPlayMode(PlayMode.REVERSED);
        }

        if (postion.x + walkFrames[0].getRegionWidth() > Gdx.graphics.getWidth() - 50) {
            direction = Direction.LEFT;
        } else if (postion.x < 50) {
            direction = Direction.RIGHT;
        }
        currentFrame = walkAnimation.getKeyFrame(stateTime, true); // #16
        spriteBatch.begin();
        spriteBatch.draw(currentFrame, postion.x, postion.y); // #17
        spriteBatch.end();
    }

    @Override
    public void dispose() {
        walkSheet.dispose();
    }

    enum Direction {
        LEFT, RIGHT
    }

動畫比較難展示,大家自己來運行就可以。下面是log輸出

AnimationTest: frameDuration=0.025
AnimationTest: frameDuration=0.75

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved