0

我正在将位图动画添加到我的简单 2D android 游戏引擎中(如果您还可以调用它的话.. :D)并且我正面临以预定义的 FPS/速率循环帧的问题。

我现在所做的只是使用 System 获取 currentTimeMillis 并将其用作参考,但我很确定这不是最好的决定。我想我可以将当​​前帧传递给绘图方法并将其用于绘图方法。

目前我有你从中获取可绘制对象的对象,我在渲染器上使用它,如下所示:

canvas.drawBitmap(animation.getDrawable(), (int)x, (int)y, null);

并且 getDrawable() 返回动画的当前帧或唯一的帧,如果它的静止图像和这里的代码

        if(frames.size() > 1) {
            long current = System.currentTimeMillis();
            if (currentFrame == frames.size() - 1 && frameDirection == 1) {
                frameDirection = -1;
            } else if (currentFrame == 0 && frameDirection == -1) {
                frameDirection = 1;
            }
            if ((current - lastFrame) > delay) {
                currentFrame += frameDirection;
                lastFrame = current;
            }
        }
        return frames.get(currentFrame);

在我看来,这看起来很糟糕而且效率低下。我能做些什么呢?将当前帧传递给 getDrawable 的唯一方法是或者应该如何完成?

4

1 回答 1

1

如果我理解正确,您想为您的游戏引擎创建一个动画类吗?

在我的游戏引擎中,我有一个名为 的类SpriteSheetAnimation,当调用 update 方法时,它基本上会遍历动画的每一帧——我相信你会理解它背后的逻辑,你会找到一种使用它的方法:

public class SpriteSheetAnimation extends GameObjectTemplate {

    int animationSheetLength;
    int animationSheetHeight;
    int columns;
    int rows;
    Rect srcRect;

    int left;
    int bottom;
    int lengthOfSpriteInSheet;
    int heightOfSpriteInSheet;

    boolean repeatAnimation;
    boolean animationCompleted;
    boolean animationStarted;

    Bitmap bitmap;

    /**
     * You input a bitmap and the number of sprites (by defining the number of rows and columns), and this class will
     * take care of animating the sheet. 
     * 
     */

    public SpriteSheetAnimation(WorldTemplate world, Bitmap animationSheet, int amountOfRows, int amountOfColumns) {
        super(world);
        this.animationSheetLength = animationSheet.getWidth();
        this.animationSheetHeight = animationSheet.getHeight();
        this.columns = amountOfColumns;
        this.rows = amountOfRows;
        this.lengthOfSpriteInSheet = this.animationSheetLength/this.columns;
        this.heightOfSpriteInSheet = this.animationSheetHeight/this.rows;
        srcRect = new Rect();

        left = 0;
        bottom = this.heightOfSpriteInSheet;

        repeatAnimation = false;
        animationCompleted = false;
        animationStarted = false;

        this.bitmap = animationSheet;
        this.drawShapesOfSprites = true;

        this.gameObjectShape.addRectangle(new Rect(0, 0, 0 + this.heightOfSpriteInSheet, 0 + this.lengthOfSpriteInSheet));

    }

    @Override
    public void defineGameObjectPositionShape() {
        this.gameObjectShape.addRectangle(new Rect());

    }

    /**
     * <b><i>public Rect getSrcRect()</i></b>
     * <br>
     * Since: API 1
     * <br>
     * <br>
     * Retrieve the rect that will cover the current source of the sheet.
     * 
     * @return 
     * The current rect that will cover the current source of the sheet.
     *
     */

    public Rect getSrcRect() {
        return srcRect;
    }

    /**
     * <b><i>public Rect getDstRect()</i></b>
     * <br>
     * Since: API 1
     * <br>
     * <br>
     * Retrieve the rect where the bitmap will be scaled to fit into.
     * 
     * @return 
     * The current rect where the bitmap will be scaled to fit into.
     *
     */

    public Rect getDstRect() {
        return this.getGameObjectPositionRect();
    }

    /**
     * <b><i>public void repeatAnimation(boolean repetition)</i></b>
     * <br>
     * Since: API 1
     * <br>
     * <br>
     * This method will set if the animation should be repeated or not.
     * 
     * @param state 
     * <br><br>
     * 1. True = The animation will repeat once completed and keep on doing so.
     * <br><br>
     * 2. False = The animation will play only once.
     *
     *      
     */

    public void repeatAnimation(boolean repetition) {
        this.repeatAnimation = repetition;
    }

    /**
     * <b><i>public boolean isAnimationFinished()</i></b>
     * <br>
     * Since: API 1
     * <br>
     * <br>
     * Retrieve if the animation has finished.
     * 
     * @return 
     * If the animation has finished.
     *
     */

    public boolean isAnimationFinished() {
        return animationCompleted;
    }

    /**
     * <b><i>public boolean hasBeenStarted()</i></b>
     * <br>
     * Since: API 1
     * <br>
     * <br>
     * Retrieve if the animation has started.
     * 
     * @return 
     * If the animation has started.
     *
     */

    public boolean hasBeenStarted() {
        return animationStarted;
    }

    /**
     * <b><i>public void render()</i></b>
     * <br>
     * Since: API 1
     * <br>
     * <br>
     * This method will render the animation (the current picture of the sheet).
     *
     */

    public void render() {
        world.game.getGraphics().getCanvasGameScreen().drawBitmap(this.bitmap, this.getSrcRect(), this.getGameObjectPositionRect(), null);
    }

    /**
     * <b><i>public void update()</i></b>
     * <br>
     * Since: API 1
     * <br>
     * <br>
     * This method will update the animation.
     *
     */

    @Override
    public void update() {
        // Every update will advance to the next frame of the animation
        // Set if animation has started
        if(!animationStarted) {
            animationStarted = true;
        }

        // Set the frame
        srcRect.set(left, (bottom - this.heightOfSpriteInSheet), (left + this.lengthOfSpriteInSheet), bottom);
        // Change the location, so the next time the frame is set, it will be set accordingly
        left = left + this.lengthOfSpriteInSheet;

        if(left == this.animationSheetLength && bottom == this.animationSheetHeight) {
            if(repeatAnimation == true) {
                left = 0;
                bottom = 0;
            }
            else {
                animationCompleted = true;
            }
        }

        if(left == this.animationSheetLength) {
            bottom = bottom + this.heightOfSpriteInSheet;
            left = 0;
        }

    }


}

我希望这对您有所帮助并帮助您入门。

于 2012-08-31T15:45:05.753 回答