我如何最好地用Java实现战争迷雾?

问题描述 投票:3回答:1

你好,我是一个没有经验的程序员,这是我关于堆栈溢出的第一个问题!

我正在尝试在Java游戏中实现“战争迷雾”。这意味着我的大部分地图都从黑色开始,然后随着我的角色之一在地图各部分之间移动而显示出来。我在这里进行了搜索,发现了一些建议,并尝试自己进行调整。我的每种方法都可以使用,但是每种方法都会遇到严重的运行时问题。为了进行比较,在我进行任何战争迷雾之前,我都获得了250-300 FPS。

这是我的基本方法:

  1. 渲染我的背景和我的JPanel上的所有对象
  2. 创建黑色的BufferedImage(fogofwarBI)
  3. 确定我的地图上哪些区域需要显示
  4. 将我的fogofwarBI上的相关像素设置为完全透明
  5. 渲染我的fogofwarBI,从而用黑色覆盖透明屏幕的部分,并在透明区域中显示背景和对象。

为了初始化缓冲的图像,我在FogOfWar()类中做了以下操作:

    private BufferedImage blackBI =  loader.loadImage("/map_black_2160x1620.png");
    private BufferedImage fogofwarBI = new BufferedImage(blackBI.getWidth(), blackBI.getHeight(), BufferedImage.TYPE_INT_ARGB);

    public FogOfWar() {
        fogofwarBI.getGraphics().drawImage(blackBI,0,0,null);
    }

[在每次尝试中,我都是在“可见”地形的中间开始角色,即在我的地图中没有雾的部分(我的fogofwarBI将具有完全透明的像素)。

尝试1:setRGB

首先,如果角色移动了,我会在角色的视野中找到“新”坐标。即。并非角色视野范围内的每个像素,而是角色移动范围内视野范围边缘的像素。这是通过for循环完成的,最多可以遍历400个左右的像素。

我将这些x和y坐标都输入到我的FogOfWar类中。

我检查这些x,y坐标是否已经可见(在这种情况下,我不会为它们做任何事以节省时间)。我通过维护一组列表来进行此检查。其中每个列表包含两个元素:x和y值。集合是坐标列表的唯一集合。该Set开始为空,我将添加x,y坐标来表示透明像素。我使用Set来使集合保持唯一,并且因为我了解List.contains函数是执行此检查的快速方法。并且我将坐标存储在列表中,以避免将x和y混淆。

如果当前在我的fogofwarBI上给定的x,y位置不可见,我使用.setRGB添加将RBG设置为透明,然后将其添加到我的transparentPoints Set中,以便以后不再编辑坐标。

    Set<List<Integer>> transparentPoints = new HashSet<List<Integer>>();

    public void editFog(int x, int y) {

        if (transparentPoints.contains(Arrays.asList(x,y)) == false){
            fogofwarBI.setRGB(x,y,0); // 0 is transparent in ARGB
            transparentPoints.add(Arrays.asList(x,y));
        }
    }

然后我使用]渲染它

    public void render(Graphics g, Camera camera) {
        g.drawImage(fogofwarBI, 0, 0, Game.v_WIDTH, Game.v_HEIGHT, 
                    camera.getX()-Game.v_WIDTH/2, camera.getY()-Game.v_HEIGHT/2, 
                    camera.getX()+Game.v_WIDTH/2, camera.getY()+Game.v_HEIGHT/2, null);
    }

根据游戏机的位置,我基本上将我的fogofwarBI的正确部分应用于JPanel(800 * 600)。

结果:正常工作。穿越雾气时的FPS为20-30,否则为正常(250-300)。由于.setRGB功能,此方法很慢,每次我的游戏“滴答声”都可运行400次。]

尝试2:光栅

在这种尝试中,我创建了我的fogofwarBI的栅格以直接以数组格式播放像素。

    private BufferedImage blackBI =  loader.loadImage("/map_black_2160x1620.png");
    private BufferedImage fogofwarBI = new BufferedImage(blackBI.getWidth(), blackBI.getHeight(), BufferedImage.TYPE_INT_ARGB);

    WritableRaster raster = fogofwarBI.getRaster();
    DataBufferInt dataBuffer = (DataBufferInt)raster.getDataBuffer();
    int[] pixels = dataBuffer.getData();

    public FogOfWar() {
        fogofwarBI.getGraphics().drawImage(blackBI,0,0,null);
    }

然后,我的editFog方法如下所示:

    public void editFog(int x, int y) {
        if (transparentPoints.contains(Arrays.asList(x,y)) == false){
            pixels[(x)+((y)*Game.m_WIDTH)] = 0; // 0 is transparent in ARGB
            transparentPoints.add(Arrays.asList(x,y));
        }
    }

我的理解是,栅格与像素阵列处于(恒定吗?)通信中,因此我以与尝试1相同的方式呈现BI。

结果:正常工作。固定FPS约为15。我相信它会一直很慢(无论我的角色是否在雾中移动),因为在处理像素阵列时很快,但栅格一直在工作。

尝试3:较小的栅格

这是尝试2的变体。

我读过某个地方,使用.drawImage的10个输入版本不断调整BufferedImage的大小很慢。我还认为拥有2160 * 1620 BufferedImage的栅格可能会很慢。

因此,我尝试使“雾层”仅等于视图的大小(800 * 600),并根据当前像素是黑色还是在我的标准transparentPoints集中可见,使用for循环更新每个像素并基于我的相机位置。

因此,现在我的editFog类仅更新了不可见像素集,而我的渲染类如下所示:

    public void render(Graphics g, Camera camera) {

        int xOffset = camera.getX() - Game.v_WIDTH/2;
        int yOffset = camera.getY() - Game.v_HEIGHT/2;

        for (int i = 0; i<Game.v_WIDTH; i++) {
            for (int j = 0; j<Game.v_HEIGHT; j++) {
                if ( transparentPoints.contains(Arrays.asList(i+xOffset,j+yOffset)) ) {
                    pixels[i+j*Game.v_WIDTH] = 0;
                } else {
                    pixels[i+j*Game.v_WIDTH] = myBlackARGB;
                }
            }
        }

            g.drawImage(fogofwarBI, 0, 0, null);

    }

所以我不再需要即时调整我的fogofwarBI的大小,而是每次都更新每个像素。

结果:正常工作。FPS:恒定为1 FPS-效果最差!我猜想,不更新我的fogofwarBI的大小而缩小它的任何节省都将远远超过更新栅格中的800 * 600像素,而不是更新约400 *。

我的想法已经用尽了,我的互联网搜索都无法让我进一步尝试以更好的方式进行此操作。我认为必须有一种有效解决战争迷雾的方法,但也许我对Java或可用工具还不够熟悉。

关于我当前的尝试是否可以改善或我是否应该尝试其他尝试的指针,将不胜感激。

谢谢!

你好,我是一个没有经验的程序员,这是我关于堆栈溢出的第一个问题!我正在尝试在Java游戏中实现“战争迷雾”。这意味着我的大部分地图都从黑色开始,然后...

java render raster bufferedimage frame-rate
1个回答
0
投票

这是一个好问题。我对awt / swing类型的渲染并不熟悉,所以我只能尝试解释该问题的可能解决方案。

[从性能的角度来看,我认为在地图的较大部分中对FOW进行块化/栅格化是一个比使用基于像素的系统更好的选择。这将减少每个刻度的检查量,并且更新它还将占用较少的资源,因为仅一小部分窗口/地图需要更新。网格越大,检查越少,但是视觉上的损失越大。

© www.soinside.com 2019 - 2024. All rights reserved.