Pregunta

I'm working on a basic LWJGL game to prepare for the Ludum Dare this weekend.

I have barely any code, but as soon as I implemented Textures in my grid, I've been getting terrible FPS!

Here's some of my code:

The Screen class (used to render the game) (Scroll down to the drawGrid() method)

package game;

import game.blocks.Block;
import game.entities.EntityLiving;
import game.entities.Human;
import game.world.Grid;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.newdawn.slick.opengl.Texture;

public class Screen {

//Screen Constructor
public Screen() {
    try {
        Display.setDisplayMode(new DisplayMode(Game.WIDTH*2,Game.HEIGHT*2));
        Display.create();
        init();
        while(!Display.isCloseRequested()) {
            render();
        }
        Display.destroy();
    } catch (LWJGLException e) {
        e.printStackTrace();
        System.exit(0);
    }
}

//OpenGl Initialization
public void init() {
    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();
    GL11.glOrtho(0, Game.WIDTH, Game.HEIGHT, 0, 1, -1);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    GL11.glEnable(GL11.GL_TEXTURE_2D);
}

public void render() {
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
    Display.sync(60);
    Grid grid = new Grid();
    drawGrid(grid);
    drawEntity(new Human(64,64));
    Display.update();
    System.out.println("render");
}

public void drawEntity(EntityLiving e) {
    Texture tex = e.getTexture();
    tex.bind();
    GL11.glColor4f(1, 1, 1, 1);
    GL11.glBegin(GL11.GL_QUADS);
    GL11.glTexCoord2f(0,0);
    GL11.glVertex2f(e.getX(),e.getY());
    GL11.glTexCoord2f(1,0);
    GL11.glVertex2f(e.getX()+e.getWidth(),e.getY());
    GL11.glTexCoord2f(1,1);
    GL11.glVertex2f(e.getX()+e.getWidth(),e.getY()+e.getHeight());
    GL11.glTexCoord2f(0,1);
    GL11.glVertex2f(e.getX(),e.getY()+e.getHeight());
    GL11.glEnd();
}

public void drawGrid(Grid grid) {
    Block[][] level = grid.getGrid();
    for(int i = 0; i < Grid.WIDTH; i++) {
        for(int j = 0; j < Grid.HEIGHT; j++) {
            Texture tex = level[i][j].getTexture();
            tex.bind();
            GL11.glBegin(GL11.GL_QUADS);
            GL11.glTexCoord2f(0,0);
            GL11.glVertex2f(i*16,j*16);
            GL11.glTexCoord2f(1,0);
            GL11.glVertex2f(i*16+16,j*16);
            GL11.glTexCoord2f(1,1);
            GL11.glVertex2f(i*16+16,j*16+16);
            GL11.glTexCoord2f(0,1);
            GL11.glVertex2f(i*16,j*16+16);
            GL11.glEnd();
        }
    }
}

}

The Grid Class

package game.world;

import game.Game;
import game.blocks.Block;
import game.blocks.Grass;

public class Grid {

public static final int HEIGHT=Game.HEIGHT/16;
public static final int WIDTH=Game.WIDTH/16;
public Block[][] grid;

public Grid() {
    grid = new Block[WIDTH][HEIGHT];
    for(int i = 0; i < WIDTH; i++) {
        for(int j = 0; j < HEIGHT; j++) {
            grid[i][j] = new Grass();
        }
    }
}

public Block[][] getGrid() {
    return grid;
}
}

The Block Class

package game.blocks;

import java.io.IOException;

import org.lwjgl.opengl.GL11;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;

public class Block {
public Texture tex;
public Block(String texname) {
    try {
        tex = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/images/blocks/" + texname + ".png"), GL11.GL_NEAREST);
    } catch (IOException e) {
        e.printStackTrace();
        System.exit(0);
    }
}
public Texture getTexture() {
    return tex;
}
}

Let me know if I should include anymore code. Thanks.

¿Fue útil?

Solución

Going from those vertex coordinates I'm guessing you're making a tile based game and that Grass is a type of Block. These are the main things I can see that will slow down rendering:

  1. Creating many textures in memory (one for each Block)
  2. Changing texture too often (every Block)
  3. No buffering strategy to cache mesh (the world in this case)

I highly suggest stitching all your Block textures together into one sprite sheet then using glTexCoord2f to define that particular texture's location in the larger one. This will allow you almost never to change texture while rendering the world. However currently you are loading said texture for every block; I suggest you make some sort of texture manager (maybe it can manage sub-textures too), this will allow you to simply load the texture once then in each Block can define the sub-textures location for the renderer. Altogether that will drastically reduce used memory which is always good and will give a big improvement to the frame rate.

Depending on how big the resulting mesh is that you're drawing each frame (in this case would be WIDTH X HEIGHT X 4) in vertices, it will take longer to pass to OpenGL, also if this mesh is never changing there is no point in re-creating it each frame, for this there are a number of ways to buffer it into graphics memory, such as display lists (which I personally think are the easiest to implement) or Vertex Buffer Objects which are even faster but require deeper knowledge.

Otros consejos

Try/Catch statement && while loop too much loads

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top