1

我想创建一个 cookie-cutter 类型的类,它采用源矩形并动态地遍历精灵表中的每一帧,直到每个图像都被剪掉用于动画。当精灵表中的每个帧大小相同时,我可以做到这一点,但几乎不可能在具有相同帧大小的动画中找到具有任何复杂性的精灵表。例如:

具有恒定帧大小的简单精灵表

就像我想要的那样被剪切和动画,但是:

具有可变帧大小的更复杂的位图

由于它的帧大小可变,因此变得有趣(因为我的程序目前假设所有帧的大小都相同)。有没有办法在某种程度上感知精灵表中每个单独帧的帧大小,或者这是一个失败的原因?

当前创建“cookie切割器”源框架的代码:

// Indirect Variable Sets (Sprite Animation and Sprite Sheet Cuts)
    framesPerRow = frameCount/spriteSheetRows;
    spriteWidth = bmp.getWidth() / framesPerRow;    // cut the sheet into pieces based on 
                                                    // sprite width: frames/row ratio
    spriteHeight = bmp.getHeight()/spriteSheetRows; // cut the sheet horizontally into pieces based on
                                                    // total height : total rows ratio

    setSourceRect(new Rect(0, 0, spriteWidth, spriteHeight));
    setFramePeriod(1000 / fps);                     // set the framePeriod based on desired fps

然后在我的更新方法中使用它:

public void update(long gameTimeInMillis){
    // If the game time has been longer than the frame period...
    // the reason that we need frameTicker is so that we can use our variable (frameTicker)
    // to keep track of the last time that the frame was updated (relative to our game)
    if (gameTimeInMillis > frameTicker + framePeriod){
        frameTicker = gameTimeInMillis;             // set last update time (current time)
        // increment the animation frame
        currentFrame++;

        // Get current column in sprite sheet:
        // this works like this, imagine we are at frame 20, and we have 5 frames per row
        // 20%5 = 0 so we are at the end of the row, if we are at frame 22, 22%5 = 2, etc.
        frameColumn = currentFrame%framesPerRow;

        // if we are at our max frame count (note, we start at 0) then reset our animation
        if(currentFrame >= frameCount){ 
            currentFrame = 0;                   
        }

        // increment the sprite sheet row if we are at the end of the row
        if(frameColumn == 0){
            currentRow++;
        }

        // if we are at our max rows (note, we start at 0) then reset our animation rows
        if(currentRow >= spriteSheetRows){
            currentRow = 0;
        }

        // define the "cookie cutter" sourceRectangle for our sprite sheet
        this.sourceRect.left = frameColumn * spriteWidth;
        this.sourceRect.right = this.sourceRect.left + spriteWidth;
        this.sourceRect.top = currentRow * spriteHeight;
        this.sourceRect.bottom = this.sourceRect.top + spriteHeight;
        Log.d(TAG, "Top coordinates = " + currentRow);
    }
}

因为我不是艺术家,所以我的目标是使用预渲染的精灵表,以便我可以在 2D 动画环境中提高我的技能。问题是,我发现的大多数精灵表似乎都有可变帧,这使得它们对我来说相当无用,除非我能找到一种更精确地切割它们的方法(或另一种切割方法,是否有我缺少的 API 工具? )

4

2 回答 2

0

您可以添加一些元数据以与定义像素位置以及工作表中每个帧的宽度/高度的精灵表一起使用。这比拥有一个完美的网格更费力,但它将使您能够按原样使用更多种类的精灵表。例如(不按比例)如果你去获取第 1 帧,你会发现它是从 128 像素位置开始的 16x32,你可以根据整张纸的宽度/高度来计算纹理坐标。这听起来很混乱,但一旦你开始工作,它应该会给你更多的灵活性,并且可以在各种精灵表中重复使用。

否则,您可以使用 Gimp 将单个帧剪切并粘贴到网格上。或者,将帧切割成单独的图像,所有图像都具有相同的宽度/高度,然后使用 ImageMagick 之类的工具将单独的图像组合成一个精灵表。我不记得实际的命令,但我使用命令行中的 ImageMagick 将 Reiner 的一些 Tilesets 组装成精灵表。ImageMagick 将连接目录中的所有图像,您甚至可以告诉它为您调整它们的大小,以便您可以从更高分辨率的图像开始,并在需要时将它们强制为 2 的幂。

于 2014-02-16T02:37:56.980 回答
0

您可以将精灵存储为 s 数组Rect。(说真的,您不想将它们存储在二维数组中。)

Rect[] frames = new Rect[TOTAL_NUMBER_OF_FRAMES];

现在,计算机无法知道如何裁切您的纸张。最简单的方法可能是拥有一个如下所示的文本文件:

x,y,width,height
x,y,width,height
x,y,width,height

这将允许您使用具有不同宽度和高度的奇怪精灵表。这也意味着您可以拥有没有精灵的图像位(例如,当每个帧周围有边框或您不想使用的帧时)。使用文件 IO 将它们放入数组中。(请注意,您可能希望将 BitMapFactory 选项设置为不缩放位图)。

您可以使用以下方法绘制第 n 帧:

canvas.drawBitmap(bmp, frames[n],
    new RectF(x, y, x + frames[n].width(), y + frames[n].height()),
    paint);
于 2016-03-18T21:57:50.847 回答