【问题标题】:How to build a Tiled map in Java for a 2D game?如何在 Java 中为 2D 游戏构建平铺地图?
【发布时间】:2009-03-08 00:57:56
【问题描述】:

不知道如何解决这个问题。

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

那我想用这个 Map 类来:

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

  • 知道边界在哪里,所以它不会将精灵移动到400x400之外,从而隐藏它。

  • 碰撞检测,知道瓷砖是否空着。

如何做到这一点?这里专门讨论 x,y->tile 或 tile index->​​x,y 转换(用于适当地绘制精灵)。

【问题讨论】:

    标签: java algorithm 2d tiles


    【解决方案1】:

    首先,将仅与表示有关的像素概念与图块分开,图块是实际的游戏对象,并在游戏中设置了约束。

    我找到了一个解决此类问题的好方法,那就是开始勾勒出你想要的粗略 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)..
    

    瓷砖可以在内部表示为二维数组或单个数组,在这种情况下,您可以使用某种内部表示方案将您的数组映射到棋盘方格,从而使用 mod 算法。

    【讨论】:

    • getPixelPosition() 的一些代码,我会接受你的回答 :)
    • Geez ClickUpvote 提示一下。使用屏幕作为模型并不是一个好的设计。使用内存模型。颜色和位置是一个独立的属性。您还可以使用内存模型来存储其他属性。以fastgraph.com/qfrip.html为例
    • 在不知道 x,y 属性的情况下,如何在屏幕上绘制精灵以指示其从一个图块移动到另一个图块?!
    • 绘制图像时需要提供 x,y 属性
    • 从代表您所在区域的二维数组开始。该区域的值可以代表一个友军、敌人甚至是背景图块。现在如果 t[x,y]=z 然后 blit tile z 到屏幕 pos x,y。也许用 20x20 的瓷砖进行缩放。相同的 t[x,y]=z 但使用 z20 并在 x*20,y*20 屏幕上绘图。
    【解决方案2】:

    简答:乘法和模运算。

    但是,如果这让您感到难过,我建议您在尝试编写游戏之前认真复习一下数学。

    还有你的陈述

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

    不适用于任何合理的几何形状。如果“1 块 = 4 像素”是指块为 2x2,则玩家拿走 100,而不是 5。如果你的意思是他们是 4x4,那么玩家需要 25,这仍然不是 5。

    【讨论】:

    • Tile=pixels / 4. Small sprite(4x4)= 4/4 = 1 tile。大精灵 (20 x 20) = 20 / 4=5。不?让我感到困惑的是如何根据图块索引(例如 5)检索 x,y 坐标。你能给我举个例子吗?
    • 没有。 20 像素 x 20 像素 = 400 方形像素。一个 4x4 的图块是 16 个正方形像素。 400/16 = 400 平方像素区域内的 25 个 4x4 瓦片。
    【解决方案3】:
    /** 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->piece 转换,反之亦然,您有多种方法可用。选择哪一个取决于确切的要求(速度、游戏大小......)。因此,请确保您隐藏了实现细节,以便以后可以更改它们。

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

    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 必须返回一个 Collection of pieces。如果顺序无关紧要,则为 set,如果需要,则为 List。

    【讨论】:

    • 谢谢,但你能告诉我如何根据瓷砖编号确定 x.y 坐标吗?这是我一直想不通的
    • 这就是 tileToPixel 方法的用途
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-01
    相关资源
    最近更新 更多