如何在Java中为2D游戏构建Tiled地图?

时间:2009-03-08 00:57:56

标签: java algorithm 2d tiles

不确定如何处理此问题。

基本上,我想要一个Pixel - > 400x400窗口的平铺表示。屏幕上的每个坐标,例如120x300应该是图块的一部分。我最小的精灵是4个像素,所以我们可以说1个tile = 4个像素。玩家和敌人的精灵都是20 x 20,所以每个玩家/坏人将占据5个牌。

然后我想将这个Map类用于:

  • 通过提供图块的索引/ ID来检索玩家/怪物精灵的x / y坐标。

  • 知道边界的位置,因此它不会将精灵移动到400x400之外,从而隐藏它。

  • 碰撞检测,了解瓷砖是否空置。

如何做到这一点?这里特别谈论x,y-> tile或tile索引 - > x,y转换(适当地绘制精灵)。

3 个答案:

答案 0 :(得分:4)

首先,将一个与像素有关的像素的概念与一个瓦片分开,瓦片是一个实际的游戏对象,它对游戏施加了约束。

我找到了一个很好的方法来解开这样的事情,就是开始勾勒出你想要的粗略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 )

其中电路板的所有内部单元都是瓷砖,而不是像素。 然后像素信息可以独立于图块表示从板上导出,并带有一些内部乘法 -

  public Point getPixelPosition(int xTilePos, int yTilePos, int pixelsPerTile)..

瓷砖可以在内部表示为2d数组或单个数组,在这种情况下,您可以使用某种内部表示方案将数组映射到电路板方块,从而模拟算术。

答案 1 :(得分:1)

简短回答:乘法和模运算。

但如果这让你很难过,我建议你在尝试写游戏之前先做一个严肃的数学复习。

也是你的陈述

  

我最小的精灵是4像素,所以我们   可以说1瓦= 4像素。该   玩家和敌人的精灵都是20 x   20,所以每个球员/坏人都会占据   5个瓷砖。

不适用于任何合理的几何体。如果通过“1 tile = 4像素”表示图块是2x2,那么玩家需要100而不是5。如果你的意思是他们是4x4,那么玩家需要25,但仍然不是5。

答案 2 :(得分:1)

/** 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;
}

你可能也希望方法在两个参数(x和y at)上运行。

对于ID->片段转换,反之亦然,您可以使用各种方法。选择哪一个取决于具体要求(速度,游戏规模......)。因此,请确保隐藏实现细节,以便稍后更改它们。

我从一个真正简单的解决方案开始:

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;
    }
}

希望能让你开始。所有代码都是在附近没有编译器的情况下编写的,因此它将包括拼写错误,当然还有错误,这些错误可能会在创意公共许可证下分发。

如果没有很多碎片,那么将碎片保持在一组中的方法应该很好。只要大多数电路板区域不包含一块,它应该比2D阵列更好。整个事情目前假设没有重叠的部分。如果你需要那些getPieceOnTile必须返回一个片段集合。订单无关紧要,如果是,则为List。