如何在 Java 中为 2D 游戏构建平铺地图?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/622832/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to build a Tiled map in Java for a 2D game?
提问by Click Upvote
Not sure how to approach this problem.
不知道如何解决这个问题。
Basically, I want a Pixel -> Tile representation of a 400x400 window. Each coordinate on the screen, e.g 120x300should be part of a tile. My smallest sprite is 4 pixels, so we can say that 1 tile = 4 pixels. The player and enemy sprites are all 20 x 20, so each player/bad guy will occupy 5 tiles.
基本上,我想要一个 400x400 窗口的 Pixel -> Tile 表示。屏幕上的每个坐标,例如120x300应该是图块的一部分。我最小的精灵是 4 像素,所以我们可以说 1 块 = 4 像素。玩家和敌人的精灵都是 20 x 20,所以每个玩家/坏人将占据 5 格。
Then I want to use this Map class to:
然后我想使用这个 Map 类来:
Retrieve the x/y coordinates of a player/monster sprite by suppling the index/id of the tile.
Knowing where the boundaries are, so it doesn't move the sprite beyond
400x400, thus hiding it.Collision detection, knowing whether a tile is vacant or not.
通过提供图块的索引/id 来检索玩家/怪物精灵的 x/y 坐标。
知道边界在哪里,所以它不会将精灵移到 之外
400x400,从而隐藏它。碰撞检测,知道瓷砖是否空置。
How can this be done? Talking specifically about the x,y->tile or tile index->x,y conversion (for drawing the sprites appropriately) here.
如何才能做到这一点?在这里专门讨论 x,y->tile 或 tile index->x,y 转换(用于适当地绘制精灵)。
回答by Steve B.
Firstly, split out the concept of a pixel, which is just concerned with representation, with a tile, which is an actual game object with constraints it places on the game.
首先,将只与表示有关的像素的概念与图块分开,图块是实际的游戏对象,并在游戏中设置了约束。
I find a good way to disentangle things like this is to start out sketching out the rough API of what you want. Something like:
我发现解决此类问题的一个好方法是开始勾勒出您想要的粗略 API。就像是:
public class Board {
public Board (int width, int height){.. }
public boolean isOccupied(int x, int y){.. }
public void moveTo(Point from, Point to) { ..
(maybe throws an exception for outofbounds )
where all internal units of the board are in tiles, not pixels. Then pixel information can be derived from the board independantly from the tile representation with a bit of internal multiplication-
电路板的所有内部单位都在瓦片中,而不是像素。然后可以通过一些内部乘法独立地从图块表示中从板中导出像素信息 -
public Point getPixelPosition(int xTilePos, int yTilePos, int pixelsPerTile)..
The tiles can be internally represented as a 2d array or a single array, in which case you'd use some kind of internal representation scheme to map your array to the board squares, thus the mod arithmetic.
瓷砖可以在内部表示为 2d 数组或单个数组,在这种情况下,您将使用某种内部表示方案将您的数组映射到棋盘方块,因此是 mod 算法。
回答by MarkusQ
Short answer: Multiplication and Modulo operations.
简短回答:乘法和模运算。
But if this is stumping you, I'd suggest you do a serious math refresher before trying to write a game.
但是,如果这让您感到困惑,我建议您在尝试编写游戏之前认真进行数学复习。
Also your statement
还有你的说法
My smallest sprite is 4 pixels, so we can say that 1 tile = 4 pixels. The player and enemy sprites are all 20 x 20, so each player/bad guy will occupy 5 tiles.
我最小的精灵是 4 像素,所以我们可以说 1 块 = 4 像素。玩家和敌人的精灵都是 20 x 20,所以每个玩家/坏人将占据 5 格。
doesn't work out for any reasonable geometry. If by "1 tile = 4 pixels" you mean that the tiles are 2x2, then a player takes 100, not five. If you mean they are 4x4 then players take 25, which still isn't 5.
不适用于任何合理的几何图形。如果“1 块 = 4 像素”表示这些块是 2x2,那么玩家需要 100,而不是 5。如果你的意思是他们是 4x4,那么玩家拿 25,这仍然不是 5。
回答by Jens Schauder
/** size of a tile in pixel (for one dimension)*/
int TILE_SIZE_IN_PIXEL = 4;
/** size of a piece in tiles (for one dimension)*/
int PIECE_SIZE_IN_TILE = 5;
public int tileToPixel(int positionInTiles){
return TILE_SIZE_IN_PIXEL * positionInTiles;
}
/** returns the tile coordinate to which the given tile coordinate belongs
Note: tileToPixel(pixelToTile(x)) only returns x if x is the upper or left edge of a tile
*/
public int pixelToTile(int positionInPixel){
return positionInPixel / TILE_SIZE_IN_PIXEL;
}
You'll probably want methods operating on two arguments (x and y at) as well.
您可能还需要对两个参数(x 和 y at)进行操作的方法。
For the ID->piece conversion and vice versa you have various approaches available. Which one to choose depends on the exact requirements (speed, size of game ...). So make sure that you are hiding the implementation details, so you can change them later on.
对于 ID->piece 转换,反之亦然,您可以使用多种方法。选择哪一个取决于确切的要求(速度、游戏大小......)。因此,请确保您隐藏了实现细节,以便以后可以更改它们。
I'd start with a real easy solution:
我会从一个真正简单的解决方案开始:
public class Piece{
/** x position measured in tiles */
private int x;
/** y position measured in tiles */
private int y;
/** I don't think you need this, but you asked for it. I'd pass around Piece instances instead */
private final Long id;
public void getX(){
return x;
}
public void getY(){
return y;
}
public void getID(){
return id;
}
}
public class Board(){
private Set<Long,Piece> pieces = new HashMap<Piece>(pieces);
public Piece getPieceOnTile(int tileX, int tileY){
for(Piece piece:pieces){
if (isPieceOnTile(piece, tileX, tileY)) return piece;
}
}
private boolean isPieceOnTile(piece, tileX, tileY){
if (piece.getX() < tileX) return false;
if (piece.getX() > tileX + PIECE_SIZE_IN_TILE) return false;
if (piece.getY() < tileY) return false;
if (piece.getY() > tileY + PIECE_SIZE_IN_TILE) return false;
return true;
}
}
Hope that gets you started. All code is writen without a compiler nearby so it will include typos and of course bugs, which may be distributed under the creative commons license.
希望这能让你开始。所有代码都是在附近没有编译器的情况下编写的,因此它会包含错别字,当然还有错误,这些可能是在知识共享许可下分发的。
The approach of keeping the pieces in a set should work well if there are not to many pieces. It should work better than a 2D array as long as most board area does not contain a piece. The whole thing currently assumes there are no overlapping pieces. If you need those getPieceOnTile must return a Collection of pieces. A set if order does not matter, a List if it does.
如果碎片不多,将碎片放在一个集合中的方法应该很有效。只要大多数棋盘区域不包含棋子,它就应该比二维数组工作得更好。整个事情目前假设没有重叠的部分。如果需要那些 getPieceOnTile 必须返回一个 Collection 件。一个集合如果顺序无关紧要,一个列表如果它不重要。

