你好,我是一个没有经验的程序员,这是我关于堆栈溢出的第一个问题!
我正在尝试在Java游戏中实现“战争迷雾”。这意味着我的大部分地图都从黑色开始,然后随着我的角色之一在地图各部分之间移动而显示出来。我在这里进行了搜索,发现了一些建议,并尝试自己进行调整。我的每种方法都可以使用,但是每种方法都会遇到严重的运行时问题。为了进行比较,在我进行任何战争迷雾之前,我都获得了250-300 FPS。
这是我的基本方法:
为了初始化缓冲的图像,我在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游戏中实现“战争迷雾”。这意味着我的大部分地图都从黑色开始,然后...
这是一个好问题。我对awt / swing类型的渲染并不熟悉,所以我只能尝试解释该问题的可能解决方案。
[从性能的角度来看,我认为在地图的较大部分中对FOW进行块化/栅格化是一个比使用基于像素的系统更好的选择。这将减少每个刻度的检查量,并且更新它还将占用较少的资源,因为仅一小部分窗口/地图需要更新。网格越大,检查越少,但是视觉上的损失越大。