在 Java 中使用遮罩图像的十六进制进行地图碰撞时出现问题

Problems making map collision using the hex of a mask image in Java

我在制作游戏时想到了使用十六进制颜色代码使用 png 图像作为掩码与地图上的对象发生碰撞。为此,代码将扫描此遮罩的每个像素,如果某个像素具有特定颜色,则会在其位置生成一个不可见的方块。但是,由于我用作遮罩的图像非常大 (1582 x 1146),代码使用了太多的 cpu 功率(我认为是 cpu,不太确定)来扫描每个像素和游戏都以 1 FPS 的速度运行。

public class World {
    private Tile[] tiles;
    private static int WIDTH = 1582, HEIGHT = 1146;

    public World(String path) {
        try {
            BufferedImage map = ImageIO.read(getClass().getResource(path));
            int[] pixels = new int[map.getWidth() * map.getHeight()];
            tiles = new Tile[map.getWidth() * map.getHeight()];
            map.getRGB(0, 0, map.getWidth(), map.getHeight(), pixels, 0, map.getWidth());
            for (int xx = 0; xx < map.getWidth(); xx++) {
                for (int yy = 0; yy < map.getHeight(); yy++) {
                    int pixelAtual = pixels[xx + (yy * map.getWidth())];
                    if (pixelAtual == 0xfffcff00) //Pixel's hex verification
                    {
                        tiles[xx + (yy * WIDTH)] = new TileWall(xx, yy, Tile.TILE_WALL); //Invisible tile wall
                    }
                    /*else if (pixelAtual == )  Adding another tile
                        tiles[xx + (yy * WIDTH)] = new  TileWall(xx, yy, Tile.TILE_WALL);
                    } */
                    else {
                        tiles[xx + (yy * WIDTH)] = new TileFloor(xx, yy, Tile.TILE_FLOOR); //Invisible tile floor, just to complete the array
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void render(Graphics g) {
        for (int xx = 0; xx < WIDTH; xx++) {
            for (int yy = 0; yy < HEIGHT; yy++) {
                Tile tile = tiles[xx + (yy * WIDTH)];
                tile.render(g);
            }
        }
    }
}

我觉得这种十六进制扫描的方法写起来简单实用。有没有其他方法可以在游戏中添加碰撞?

小注:有 https://gamedev.stackexchange.com/ ,您可能会在其中找到解决此类问题的有用资源。

碰撞检测可能是一个具有挑战性且实际上在计算上也具有挑战性的主题,会消耗大量 运行 时间和内存。但是,它也可以相当简单。这取决于您的要求和游戏设计。更改游戏设计以使碰撞检测更易于实现通常是有用的,尽管这当然是相对于您寻求制作哪种有趣、有趣或有利可图的游戏的权衡。

您描述的方式听起来有点像基于光栅的碰撞检测,其中由像素定义的区域(如果在 3D 中,它将是由体素定义的体积)用于碰撞检测。一种更常见的方法是使用几何方法代替碰撞检测 - 由 4 个点定义的矩形、由中心和半径定义的圆、多边形等。这些通常可以提供良好的结果并且足以满足一个人的需要,它们通常允许相当快的碰撞检测,尽管它们可能更难实现。也就是说,在不同的地方有可用的文章和学习资源。这样的算法,因此使用基于几何形状的碰撞检测应该仍然很容易获得。

基于矩形的碰撞检测非常容易实现。基于圈子的仍然相当容易。基于凸多边形的更复杂,但有相关资源,例如此答案中的链接:2D Polygon Collision Detection .

可能还有用于碰撞检测的库,这也可能是一个不错的方法。游戏引擎和游戏库通常提供这些。在线搜索一个,如果您使用的是游戏引擎,则可能有可用的组件或插件。

附带说明一下,有些游戏引擎和库支持基于光栅的碰撞检测,例如 GameMaker。但是由于它(如您的示例)可能非常或非常慢,因此必须小心。

注册。循环,它可能很慢是有道理的:在最坏的情况下,它可能必须遍历所有像素。 1582 x 1146 给出了最坏的情况 1812972。假设您不创建对象,而只是让它由一个带有布尔值或类似值的数组表示,那么这可能会在一个框架中多次 运行(每次您检查碰撞),并且一个框架可能然后每秒执行多次。这一切每秒都会增加一个很大的负担。有多种方法可以优化此类事情,对于实时游戏,减少每帧花费的时间可能很重要,但也是一项挑战。尽管如此,将游戏设计和要求更改为强度较低的东西可能会有用(这又是一种权衡)。

最后一点,如果我正确理解您的代码,您可以使用对象来表示单个像素。如果您是面向对象编程的新手,您可能已经被引导相信对象通常有利于直接对您的领域进行建模。这是一个非常普遍的初学者信念(在各种教学 materials 中也很常见),但它并不普遍。对于实时游戏,性能通常很重要,以不同的方式使用对象而不是使用它们直接对域建模可能是一个好主意,因为对象的某些用法可能会产生相当大的 运行 时间开销。对于其他情况,其他问题可能会发挥作用。例如,您可能被教导可以使用 class 来描述 Animal 类型,然后子类型可以是 DogCat。这是一个非常直接的建模(并且易于教学)。然而,在实践中,用单个数据 class 描述所有种类的动物可能更合适,例如,如果你想描述很多很多动物并且它们没有不同的功能,只有属性。如果您尝试像一些教学 material 可能建议的那样使用子类型来描述所有这些动物,您最终可能会得到非常多的子类型,它们之间的差异很小,非常多 class es 花费超过他们给你带来的好处。相对于只有一个数据的发展 class。我希望这最后一部分是清楚的,尽管我不确定我说得有多清楚。