在 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 个点定义的矩形、由中心和半径定义的圆、多边形等。这些通常可以提供良好的结果并足以满足人们的需求,并且它们通常允许相当快速的碰撞检测,尽管它们可能更难实现。也就是说,在不同的地方有文章和学习资源可用于此类算法,因此使用基于几何形状的碰撞检测仍然应该相当容易。

基于矩形的碰撞检测非常容易实现。基于圆圈的仍然相当容易。基于凸多边形的更复杂,但有这方面的资源,例如此答案中的链接: 二维多边形碰撞检测 .

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

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

Reg. 循环,它确实很慢是有道理的:在最坏的情况下,它可能必须遍历所有像素。1582 x 1146给出了最坏情况1812972.假设您不创建对象,而只是让它由带有布尔值或类似值的数组表示,那么这可能会在帧中运行多次(每次检查冲突),然后帧可能会每秒执行多次。这一切每秒都会成倍增加,造成巨大的负担。有多种方法可以优化这些东西,对于实时游戏来说,减少每一帧花费的时间可能很重要,也是一个挑战。不过,将游戏设计和要求更改为不那么密集的东西可能是有用的(这又是一种权衡)。

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

最新更新