我正在尝试将此spritesheet加载到缓冲图像数组中(每个sprite为一个BufferedImage):
我在photoshop上打开了这个文件。宽度为500,高度为666.因此根据我的计算,我需要循环64次(8行和8列),对于每个精灵,它的宽度为500/8(62.5),高度为666/8 (83.25)。由于getSubImage仅接受int参数,因此我被迫将宽度设置为62,将高度设置为83(我认为这就是它截断我的图像的原因)。
以下是加载精灵的代码(我将它们放在JFrame中以显示结果)。
public class Test{
public static void main(String [] args){
BufferedImage[] sprites = null;
int width = 62;
int height = 83;
try {
BufferedImage buff = ImageIO.read(Test.class.getResourceAsStream("cyclop.gif"));
sprites = new BufferedImage[64];
int rows = 8;
int cols = 8;
for (int i = 0; i < rows; i++){
for (int j = 0; j < cols; j++){
sprites[(i * cols) + j] = buff.getSubimage(i * width, j * height, width, height);
}
}
} catch (IOException e) {
e.printStackTrace();
}
JFrame frame = new JFrame();
frame.getContentPane().setLayout(new FlowLayout());
for(BufferedImage bf : sprites)
frame.getContentPane().add(new JLabel(new ImageIcon(bf)));
frame.pack();
frame.setVisible(true);
}
}
哪个输出:
我有点迷失(我第一次这样做)关于如何加载BufferedImage中的每个精灵。有什么想法吗?
答案 0 :(得分:1)
基本上你for-loop
中的逻辑是错误的......
您将width
乘以当前行(i
)和height
乘以当前列(j
)
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
sprites[(i * cols) + j] = buff.getSubimage(i * width, j * height, width, height);
}
}
应该更像......
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
sprites[(i * cols) + j] = buff.getSubimage(j * width, i * height, width, height);
}
}
(我将高度增加到第95行)
现在,显然,你有一个问题,因为精灵的大小不同,是的。我建议创建一个简单的查找文件,其中包含行/列作为键和单元格的宽度/高度,甚至可能是x / y,因此您可以直接选择精灵,但这取决于您。 ..
答案 1 :(得分:1)
这是一个非常快速编写(可能很脏)的C解决方案,用于定位自包含,非重叠的精灵。我使用PNG阅读器获取RGBA格式的数据,并仅检查alpha。
它的工作原理如下:
minx,y
必须增加1并且maxx,y
减少 - 但这会发生在坐标到大小的位置计算精灵矩形可能不重叠! (他们不会,在这张图片中,但更好地确保它在其他任何地方都没有发生。)
为清楚起见,输出列表可以在x,y坐标上排序;我要离开那个,把它翻译成Java,给你。该程序假设一张纸上可能有64张或更少的图像(struct bounds_t[64]
);确保它尽可能大。
C代码(明显的PNG库结构和标题遗漏):
struct bounds_t {
int x,y,wide,high;
};
int alphaAt (struct pngdata_t *sheet, int x, int y)
{
if (x >= 0 && x < sheet->wide && y >= 0 && y < sheet->high)
return sheet->data[4*sheet->wide*y + 4*x + 3];
return 0;
}
void floodFindBounds (struct pngdata_t *sheet, int startx, int starty, struct bounds_t *dest)
{
int x,y;
int hit;
int minx = startx,miny = starty,maxx = startx,maxy = starty;
while (maxx < sheet->wide && alphaAt (sheet, maxx+1,miny))
maxx++;
while (maxy < sheet->high && alphaAt (sheet, minx,maxy+1))
maxy++;
do
{
hit = 0;
for (x=minx; x<=maxx; x++)
{
if (alphaAt (sheet, x,miny))
hit |= 1;
}
for (y=miny; y<=maxy; y++)
{
if (alphaAt (sheet, minx,y))
hit |= 2;
}
for (x=minx; x<=maxx; x++)
{
if (alphaAt (sheet, x,maxy))
hit |= 4;
}
for (y=miny; y<=maxy; y++)
{
if (alphaAt (sheet, maxx,y))
hit |= 8;
}
if (hit & 1) miny--;
if (hit & 2) minx--;
if (hit & 4) maxy++;
if (hit & 8) maxx++;
} while (hit);
minx++;
miny++;
dest->x = minx;
dest->y = miny;
dest->wide = maxx-minx;
dest->high = maxy-miny;
}
void wipeout (struct pngdata_t *sheet, struct bounds_t *wipe)
{
int x,y;
for (y=wipe->y; y<=wipe->y+wipe->high; y++)
for (x=wipe->x; x<=wipe->x+wipe->wide; x++)
sheet->data[4*sheet->wide*y + 4*x + 3] = 0;
}
int main (void)
{
struct pngdata_t *sheet;
struct bounds_t fullList[64];
int x,y;
int n_in_list = 0;
sheet = read_png ("monster.png");
if (!sheet)
{
printf ("unable to read sprite sheet\n");
return 0;
}
printf ("ready to process\n");
printf ("size: %d x %d\n", sheet->wide, sheet->high);
printf ("pixel #0 = %d,%d,%d,%d\n", sheet->data[0],sheet->data[1],sheet->data[2],sheet->data[3]);
for (y=0; y<sheet->high; y++)
{
for (x=0; x<sheet->wide; x++)
{
if (alphaAt (sheet,x,y) != 0)
{
floodFindBounds (sheet, x,y, &fullList[n_in_list]);
wipeout (sheet, &fullList[n_in_list]);
n_in_list++;
}
}
}
printf ("found %d sprites:\n", n_in_list);
for (x=0; x<n_in_list; x++)
printf (" %d,%d,%d,%d\n", fullList[x].x,fullList[x].y,fullList[x].wide,fullList[x].high);
return 0;
}