首页 > 解决方案 > 在 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);
            }
        }
    }
}

我认为这种十六进制扫描方法易于编写且实用。有没有其他方法可以在游戏中添加碰撞?

标签: javacollision-detection

解决方案


小提示:有https://gamedev.stackexchange.com/,您可能会在其中找到这些类型问题的有用资源。

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

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

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

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

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

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

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


推荐阅读