使用Slick2d渲染大量图像的最佳方法?

时间:2018-07-11 17:47:06

标签: java 2d slick2d

所以我正在尝试使用Slick2d制作自上而下的2D游戏。

我有一个世界对象,该对象痛疼一个包含块列表的块列表。这些瓦片是渲染的东西。我将磁贴位置存储在Vector2f中。每个块也都有一个Vector2f位置。这是我当前的工作代码:

主要:

users: {
    uid1: {
        Clients: {
            Johnny Sherman: "Apple",
            Tyler Huan: "Microsoft",
            //...
        }
    }
}

渲染器类:

public class Main extends BasicGame {
public static Main instance;
private Renderer renderer;
private long lastFrameTime;
private float delta;

public Main() {
    super("Test");
}

public static void main(String[] arguments) {
    try {
        instance = new Main();
        AppGameContainer app = new AppGameContainer(instance);
        app.setDisplayMode(1240, 720, false);
        app.setShowFPS(true);
        app.start();
        app.setAlwaysRender(true);
    } catch (SlickException e) {
        e.printStackTrace();
    }
}

@Override
public void init(GameContainer container) throws SlickException {
    renderer = new Renderer(new World(), new Player());
    for(Chunk chunk : renderer.getWorld().getChunks()) {
        System.out.println(chunk.getPosition().x + "," + 
chunk.getPosition().y + "," + chunk.getTiles().size());
    }

}

@Override
public void update(GameContainer container, int delta)
        throws SlickException {
    long currentFrameTime = getCurrentTime();
    this.delta = (currentFrameTime - lastFrameTime)/1000f;
    lastFrameTime = currentFrameTime;
    renderer.move();
}

public void render(GameContainer container, Graphics g)
        throws SlickException {
    renderer.update(g);
}

public float getFrameTimeSeconds() {
    return delta;
}

private static long getCurrentTime() {
    return Sys.getTime()*1000/Sys.getTimerResolution();
}

public Renderer getRenderer() {
    return renderer;
}
}

该代码工作得不错,但问题是帧速率为4-5 fps。 我有一个尝试将纹理缝合在一起并像这样渲染它们的想法,这是我的新渲染器代码:

public class Renderer {
World world;
Player player;

public Renderer(World world, Player player) {
    this.world = world;
    this.player = player;
}

public World getWorld() {
    return world;
}

public void setWorld(World world) {
    this.world = world;
}

public Player getPlayer() {
    return player;
}

public void setPlayer(Player player) {
    this.player = player;
}

public void update(Graphics g) {
    for (int i = 0; i < 2; i++) {
        for (int i2 = 0; i2 < 2; i2++) {
            Vector2f pos = player.getPos();
            Chunk chunk = world.getChunk(new Vector2f((int) Math
                    .floor(pos.x / 16) + i, (int) Math.floor(pos.y / 16)
                    + i2));
            if (chunk != null) {
                for (Tile tile : chunk.getTiles()) {
                    if (tile.getPos().x < player.getPos().x + 
((Display.getWidth() / 2) + 64 + 50) &&
                            tile.getPos().x > player.getPos().x - 
((Display.getWidth() / 2) + 64 + 50) &&
                            tile.getPos().y < player.getPos().y + 
((Display.getHeight() / 2) + 64 + 50) &&
                            tile.getPos().y > player.getPos().y - 
((Display.getHeight() / 2) + 64 + 50))
                    g.drawImage(tile.getTexture().getScaledCopy(64, 64), 
(pos.x - tile.getPos().x)*64+Display.getWidth(),
                            (pos.y - 
tile.getPos().y)*64+Display.getHeight());
                }
            }
        }
    }
}

public void move() {
    Vector2f pos = player.getPos();
    if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
        pos.y += 1 * Main.instance.getFrameTimeSeconds();
    } else if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
        pos.y -= 1 * Main.instance.getFrameTimeSeconds();
    }

    if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
        pos.x += 1 * Main.instance.getFrameTimeSeconds();
    } else if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
        pos.x -= 1 * Main.instance.getFrameTimeSeconds();
    }
    int width = Display.getWidth();
    int height = Display.getHeight();
    Vector2f npos2;
    Vector2f constant = new Vector2f((int) Math.floor((width / 2 - 
pos.x)/256), (int) Math.floor((height / 2 - pos.y)/256));
    Vector2f npos = constant;
    if (world.getChunk(npos) == null) {
        npos2 = npos;
        npos2.x += 1;
        //Right
        if (world.getChunk(npos2) == null) {
            for (int i = 0; i < 2; i++) {
                System.out.println("Generating new chunk! (1) " + npos2.x + 
", " + npos2.y + ", Player: x: " + player.getPos().x + ", y: " + 
player.getPos().y);
                npos.x += i;
                world.generateChunk(npos);
            }
        }
        npos2.x -= 1;
        npos2.y -= 1;
        //Down
        if (world.getChunk(npos2) == null) {
            for (int i = 0; i < 2; i++) {
                System.out.println("Generating new chunk! (2) " + npos2.x + 
", " + npos2.y + ", Player: x: " + player.getPos().x + ", y: " + 
player.getPos().y);
                npos.y -= i;
                world.generateChunk(npos);
            }
        }
    }
    npos = constant;
    if (world.getChunk(npos) == null) {
        npos2 = npos;
        npos2.x -= 1;
        //Left
        if (world.getChunk(npos2) == null) {
            for (int i = 0; i < 2; i++) {
                System.out.println("Generating new chunk! (3) " + npos2.x + 
", " + npos2.y + ", Player: x: " + player.getPos().x + ", y: " + 
player.getPos().y);
                npos.x -= i;
                world.generateChunk(npos);
            }
        }
        npos2.x += 1;
        npos2.y += 1;
        //Up
        if (world.getChunk(npos2) == null) {
            for (int i = 0; i < 2; i++) {
                System.out.println("Generating new chunk! (4) " + npos2.x + 
", " + npos2.y + ", Player: x: " + player.getPos().x + ", y: " + 
player.getPos().y);
                npos.y += i;
                world.generateChunk(npos);
            }
        }
    }
}
}

问题在于,不仅当我在瓷砖上四处移动太多时,程序都会崩溃,而且我只能得到1 fps,这根本不好。所以我的问题是,以适当的帧速率实现此目标的最佳方法是什么?

使用第二种方法使程序崩溃时出错:

public class Renderer {
World world;
Player player;

public Renderer(World world, Player player) {
    this.world = world;
    this.player = player;
}

public World getWorld() {
    return world;
}

public void setWorld(World world) {
    this.world = world;
}

public Player getPlayer() {
    return player;
}

public void setPlayer(Player player) {
    this.player = player;
}

public void update(Graphics g) {
    for (int i = 0; i < 2; i++) {
        for (int i2 = 0; i2 < 2; i2++) {
            Vector2f pos = player.getPos();
            Chunk chunk = world.getChunk(new Vector2f((int) Math
                    .floor(pos.x / 16) + i, (int) Math.floor(pos.y / 16)
                    + i2));
            if (chunk != null) {
                Image image = null;
                try {
                    image = new Image(4096, 4096);
                } catch (SlickException e1) {
                    e1.printStackTrace();
                }
                Graphics ig = null;
                try {
                    ig = image.getGraphics();
                } catch (SlickException e) {
                    e.printStackTrace();
                }
                for (Tile tile : chunk.getTiles()) {
                    if (tile.getPos().x < player.getPos().x + 
((Display.getWidth() / 2) + 64 + 50) &&
                            tile.getPos().x > player.getPos().x - 
((Display.getWidth() / 2) + 64 + 50) &&
                            tile.getPos().y < player.getPos().y + 
((Display.getHeight() / 2) + 64 + 50) &&
                            tile.getPos().y > player.getPos().y - 
((Display.getHeight() / 2) + 64 + 50))
                    ig.drawImage(tile.getTexture().getScaledCopy(64, 64), 
(pos.x - tile.getPos().x)*64+Display.getWidth(),
                            (pos.y - 
tile.getPos().y)*64+Display.getHeight());
                }
                ig.flush();
                g.drawImage(image, chunk.getPosition().x*256 - pos.x, 
chunk.getPosition().y*256-pos.y);
            }
        }
    }
}

public void move() {
    Vector2f pos = player.getPos();
    if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
        pos.y += 1 * Main.instance.getFrameTimeSeconds();
    } else if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
        pos.y -= 1 * Main.instance.getFrameTimeSeconds();
    }

    if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
        pos.x += 1 * Main.instance.getFrameTimeSeconds();
    } else if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
        pos.x -= 1 * Main.instance.getFrameTimeSeconds();
    }
    int width = Display.getWidth();
    int height = Display.getHeight();
    Vector2f npos2;
    Vector2f constant = new Vector2f((int) Math.floor((width / 2 - 
pos.x)/256), (int) Math.floor((height / 2 - pos.y)/256));
    Vector2f npos = constant;
    if (world.getChunk(npos) == null) {
        npos2 = npos;
        npos2.x += 1;
        //Right
        if (world.getChunk(npos2) == null) {
            for (int i = 0; i < 2; i++) {
                System.out.println("Generating new chunk! (1) " + npos2.x + 
", " + npos2.y + ", Player: x: " + player.getPos().x + ", y: " + 
player.getPos().y);
                npos.x += i;
                world.generateChunk(npos);
            }
        }
        npos2.x -= 1;
        npos2.y -= 1;
        //Down
        if (world.getChunk(npos2) == null) {
            for (int i = 0; i < 2; i++) {
                System.out.println("Generating new chunk! (2) " + npos2.x + 
", " + npos2.y + ", Player: x: " + player.getPos().x + ", y: " + 
player.getPos().y);
                npos.y -= i;
                world.generateChunk(npos);
            }
        }
    }
    npos = constant;
    if (world.getChunk(npos) == null) {
        npos2 = npos;
        npos2.x -= 1;
        //Left
        if (world.getChunk(npos2) == null) {
            for (int i = 0; i < 2; i++) {
                System.out.println("Generating new chunk! (3) " + npos2.x + 
", " + npos2.y + ", Player: x: " + player.getPos().x + ", y: " + 
player.getPos().y);
                npos.x -= i;
                world.generateChunk(npos);
            }
        }
        npos2.x += 1;
        npos2.y += 1;
        //Up
        if (world.getChunk(npos2) == null) {
            for (int i = 0; i < 2; i++) {
                System.out.println("Generating new chunk! (4) " + npos2.x + 
", " + npos2.y + ", Player: x: " + player.getPos().x + ", y: " + 
player.getPos().y);
                npos.y += i;
                world.generateChunk(npos);
            }
        }
    }
}
}

更新: 我没有运气,但是看看其他能够渲染数百张图像而又不丢很多帧的2D游戏,我认为有某种方法可以大大加快我的代码的速度。我不会渲染屏幕图块,而只会尝试渲染所需的数量。

更新#2: 我切换到libgdx,现在它像一个魅力一样运行。对于我的目的,libgdx中包含的批处理渲染效果更好。

0 个答案:

没有答案