我有我的游戏,在每个渲染循环中,它循环遍历地图中的所有块(128x128),这可能会导致很多延迟。当我第一次制作它时,我必须使其仅在屏幕上渲染块,否则它将立即崩溃。现在,我只在屏幕上渲染这些块,但是仍然循环浏览所有块以查看它们是否在屏幕上,这使我的fps约为2。

    for (int y = 0; y < 128; y++) {
        for (int x = 0; x < 128; x++) {
            Block b = LevelGen.getBlockAt(x, y);
            if (Forgotten.isInsideGameWindow(x * 30, y * 30)) {
                arg1.drawImage(b.getTexture(), x * 30, y * 30);
            }
        }
    }


有没有办法使它们不会遍历所有对象?

最佳答案

找出显示窗口的大小,然后仅迭代其中的块。

final int tile_size = 30;

final RectangleType displayWindow = Forgotten.getDisplayWindow ();

final int left = displayWindow.getLeft () / tile_size - 1;
final int right = displayWindow.getRight () / tile_size + 1;
final int top = displayWindow.getTop () / tile_size - 1;
final int bottom = displayWindow.getBottom () / tile_size + 1;

for (int y = top; y < bottom; ++y)
   for (int x = left; x < right; ++x)
       canvas.drawImage (LevelGen.getBlockAt (x,y).getTexture (),
                         x * tile_size, y * tile_size);


您可能还想弄清楚画布上实际要绘制的区域,而是保留要重新绘制的区域的“脏矩形”列表。每当图块发生变化,或者精灵/粒子/无论其经过其空间时,都将该图块添加到矩形中。即使您只使用一个放大的脏矩形来包含一帧中的所有更新,但即使您的游戏在任何时候都没有在屏幕上的所有位置上实际发生“填充物”,平均帧速率也会更高(但遭受大规模影响)

扩展:

      public class Map {
            private Rectangle dirtyRect = null;

            public void dirty (Rectangle areaAffected) {
                   if (null == dirtyRect) {
                        dirtyRect = areaAffected; return;
                   }
                   dirtyRect = new Rectangle ( Math.min (dirtyRect.getLeft (),
                                                         areaAffected.getLeft () ),
                                               Math.min (dirtyRect.getTop (),
                                                         areaAffected.getTop () ),
                                               Math.max (dirtyRect.getRight (),
                                                         areaAffected.getRight () ),
                                               Math.max (dirtyRect.getBottom (),
                                                         areaAffected.getBottom () ));
            }


然后使用脏矩形代替displayWindow进行常规绘制,如果没有任何更改,可以测试if (null == getDirtyRectangle ()) return;完全跳过绘制。

07-24 09:28