如何使用 Slick-Utils 从 Java 中的 spritesheet 加载纹理?
How can I load textures from a spritesheet in Java using Slick-Utils?
我正在使用 LWJGL 和 Slick Utils 创建游戏。我正在尝试将动画纹理加载为包含在单个 PNG 图像中的一组帧。
我试图弄清楚如何使用 Slick 获取子图像,但到目前为止,我所能找到的关于该主题的所有方法都是在 Slick 之外使用 BufferedImages 进行操作的方法。我想知道是否有办法使用 Slick Utils 库执行此操作,因为到目前为止我项目中的所有图像加载代码都使用 Slick。
当然,Slick 提供了一种方法来做到这一点。如果您查看 org.newdawn.slick.SpriteSheet.initImpl()
和后来的 org.newdawn.slick.SpriteSheet.getSprite()
,您会注意到如何使用 org.newdawn.slick.Image.getSubImage()
快速提取现有图像的特定部分。
SpriteSheet.java
protected void initImpl() {
if (subImages != null) {
return;
}
int tilesAcross = ((getWidth()-(margin*2) - tw) / (tw + spacing)) + 1;
int tilesDown = ((getHeight()-(margin*2) - th) / (th + spacing)) + 1;
if ((getHeight() - th) % (th+spacing) != 0) {
tilesDown++;
}
subImages = new Image[tilesAcross][tilesDown];
for (int x=0;x<tilesAcross;x++) {
for (int y=0;y<tilesDown;y++) {
//extract parts of the main image and store them in an array as sprites
subImages[x][y] = getSprite(x,y);
}
}
}
/**
* Get a sprite at a particular cell on the sprite sheet
*
* @param x The x position of the cell on the sprite sheet
* @param y The y position of the cell on the sprite sheet
* @return The single image from the sprite sheet
*/
public Image getSprite(int x, int y) {
target.init();
initImpl();
if ((x < 0) || (x >= subImages.length)) {
throw new RuntimeException("SubImage out of sheet bounds: "+x+","+y);
}
if ((y < 0) || (y >= subImages[0].length)) {
throw new RuntimeException("SubImage out of sheet bounds: "+x+","+y);
}
//Call Image.getSubImage() to get a portion of the image
return target.getSubImage(x*(tw+spacing) + margin, y*(th+spacing) + margin,tw,th);
}
您应该可以将其用作参考。我记得曾经将与 Slick 捆绑在一起的 Tiled 渲染器完全移植到 Java2D,使用旧的好 PixelGrabber 来提取精灵。
如果您决定使用 SpriteSheet
,您可以在 org.newdawn.slick.tiled.Layer.render()
中找到使用示例:
Layer.java
public void render(int x, int y, int sx, int sy, int width, int ty,
boolean lineByLine, int mapTileWidth, int mapTileHeight) {
for (int tileset = 0; tileset < map.getTileSetCount(); tileset++) {
TileSet set = null;
for (int tx = 0; tx < width; tx++) {
if ((sx + tx < 0) || (sy + ty < 0)) {
continue;
}
if ((sx + tx >= this.width) || (sy + ty >= this.height)) {
continue;
}
if (data[sx + tx][sy + ty][0] == tileset) {
if (set == null) {
set = map.getTileSet(tileset);
set.tiles.startUse();
}
int sheetX = set.getTileX(data[sx + tx][sy + ty][1]);
int sheetY = set.getTileY(data[sx + tx][sy + ty][1]);
int tileOffsetY = set.tileHeight - mapTileHeight;
//Call SpriteSheet.renderInUse() to render the sprite cached at slot [sheetX, sheetY]
set.tiles.renderInUse(x + (tx * mapTileWidth), y
+ (ty * mapTileHeight) - tileOffsetY, sheetX,
sheetY);
}
}
if (lineByLine) {
if (set != null) {
set.tiles.endUse();
set = null;
}
map.renderedLine(ty, ty + sy, index);
}
if (set != null) {
set.tiles.endUse();
}
}
}
SpriteSheet.java
public void renderInUse(int x,int y,int sx,int sy) {
//Draw the selected sprite at (x,y), using the width/height defined for this SpriteSheet
subImages[sx][sy].drawEmbedded(x, y, tw, th);
}
希望对您有所帮助。
我正在使用 LWJGL 和 Slick Utils 创建游戏。我正在尝试将动画纹理加载为包含在单个 PNG 图像中的一组帧。
我试图弄清楚如何使用 Slick 获取子图像,但到目前为止,我所能找到的关于该主题的所有方法都是在 Slick 之外使用 BufferedImages 进行操作的方法。我想知道是否有办法使用 Slick Utils 库执行此操作,因为到目前为止我项目中的所有图像加载代码都使用 Slick。
当然,Slick 提供了一种方法来做到这一点。如果您查看 org.newdawn.slick.SpriteSheet.initImpl()
和后来的 org.newdawn.slick.SpriteSheet.getSprite()
,您会注意到如何使用 org.newdawn.slick.Image.getSubImage()
快速提取现有图像的特定部分。
SpriteSheet.java
protected void initImpl() {
if (subImages != null) {
return;
}
int tilesAcross = ((getWidth()-(margin*2) - tw) / (tw + spacing)) + 1;
int tilesDown = ((getHeight()-(margin*2) - th) / (th + spacing)) + 1;
if ((getHeight() - th) % (th+spacing) != 0) {
tilesDown++;
}
subImages = new Image[tilesAcross][tilesDown];
for (int x=0;x<tilesAcross;x++) {
for (int y=0;y<tilesDown;y++) {
//extract parts of the main image and store them in an array as sprites
subImages[x][y] = getSprite(x,y);
}
}
}
/**
* Get a sprite at a particular cell on the sprite sheet
*
* @param x The x position of the cell on the sprite sheet
* @param y The y position of the cell on the sprite sheet
* @return The single image from the sprite sheet
*/
public Image getSprite(int x, int y) {
target.init();
initImpl();
if ((x < 0) || (x >= subImages.length)) {
throw new RuntimeException("SubImage out of sheet bounds: "+x+","+y);
}
if ((y < 0) || (y >= subImages[0].length)) {
throw new RuntimeException("SubImage out of sheet bounds: "+x+","+y);
}
//Call Image.getSubImage() to get a portion of the image
return target.getSubImage(x*(tw+spacing) + margin, y*(th+spacing) + margin,tw,th);
}
您应该可以将其用作参考。我记得曾经将与 Slick 捆绑在一起的 Tiled 渲染器完全移植到 Java2D,使用旧的好 PixelGrabber 来提取精灵。
如果您决定使用 SpriteSheet
,您可以在 org.newdawn.slick.tiled.Layer.render()
中找到使用示例:
Layer.java
public void render(int x, int y, int sx, int sy, int width, int ty,
boolean lineByLine, int mapTileWidth, int mapTileHeight) {
for (int tileset = 0; tileset < map.getTileSetCount(); tileset++) {
TileSet set = null;
for (int tx = 0; tx < width; tx++) {
if ((sx + tx < 0) || (sy + ty < 0)) {
continue;
}
if ((sx + tx >= this.width) || (sy + ty >= this.height)) {
continue;
}
if (data[sx + tx][sy + ty][0] == tileset) {
if (set == null) {
set = map.getTileSet(tileset);
set.tiles.startUse();
}
int sheetX = set.getTileX(data[sx + tx][sy + ty][1]);
int sheetY = set.getTileY(data[sx + tx][sy + ty][1]);
int tileOffsetY = set.tileHeight - mapTileHeight;
//Call SpriteSheet.renderInUse() to render the sprite cached at slot [sheetX, sheetY]
set.tiles.renderInUse(x + (tx * mapTileWidth), y
+ (ty * mapTileHeight) - tileOffsetY, sheetX,
sheetY);
}
}
if (lineByLine) {
if (set != null) {
set.tiles.endUse();
set = null;
}
map.renderedLine(ty, ty + sy, index);
}
if (set != null) {
set.tiles.endUse();
}
}
}
SpriteSheet.java
public void renderInUse(int x,int y,int sx,int sy) {
//Draw the selected sprite at (x,y), using the width/height defined for this SpriteSheet
subImages[sx][sy].drawEmbedded(x, y, tw, th);
}
希望对您有所帮助。