您可以只保留一个 Image 并使用 Graphics 对象的 drawImage 方法的重载来指定在哪里绘制图像的哪一部分:
g.drawImage(image, x1, y1, x2, y2, srcX1, srcY1, srcX2, srcY2);
参见 [javadoc](http://slick.cokeandcode.com/javadoc/org/newdawn/slick/Graphics.html#drawImage(org.newdawn.slick.Image, float, float, float, float, float,浮动,浮动,浮动))
第一个参数是图片的实例。接下来的两个参数定义屏幕上渲染开始的点。 X2 和 y2 定义了渲染的终点。通常 x2 是 x1 + spriteWidth 并且 y2 是 y1 + spriteHeight,但是您可以更改这些值以绘制不同大小的精灵。
最后四个参数的作用相同,但它们定义了将在屏幕上绘制的精灵表区域。
如果我们以您的示例为例,我们想从第三行绘制第二个图块,调用将如下所示:
int tileWidth = 8;
int tileHeight = 8;
int sourceX = 40;
int sourceY = 8; //as its the sec
int drawX = 34;
int drawY = 65;
g.drawImage(image, drawX, drawY, drawX + tileWidth, drawY + tileHeight
, sourceX, sourceY, sourceX + tileWidth, sourceY + tileHeight);
当我使用 spritesheet 时,我在一些(非常罕见的情况下,主要是测试)和一个 sprite 类中有硬编码值,其中存储了源 x1、x2、y1 和 y2 值。我可以将一堆它们打包在列表或地图中,这样我就有了一个精灵索引。通常我会以某种方式生成定义,然后序列化列表,因此如果需要,我可以简单地重新加载该列表。
这是我的 XML 定义的一个简短示例(我将宽度和高度而不是 x2 和 y2 值存储在 xml 中,因为我发现它更易于阅读并且更便于手动编辑。反序列化后我计算 x2和 y1 值):
<spriteSheet imageName="buildings" name="buildings">
<sprite name="1x2 industry 01" spriteX="0" spriteY="0" width="50" height="112"/>
<sprite name="1x2 quarters 01" spriteX="50" spriteY="0" width="50" height="112"/>
<sprite name="1x1 spaceport 01" spriteX="243" spriteY="112" width="51" height="56"/>
...
</spriteSheet>