Organized Structure of Rendering in Different Game "States" (LWJGL)

Hello! I am very new

There are three game “states” (stored as an enum) in my game. The overworld (where the player walks around) the battlescreen (where the player fights enemies) and the inventory
I am trying to organize this as nealty as possible

In my “GameDisplay” class (which makes the game window, which I have successfully done) I made a method called “render()” which is called in the game loop

private void render()
	{
		switch(state)
		{
		case OVERWORLD: 
			overworld.render();
			break;
		case BATTLESCREEN:
			battlescreen.render();
			break;
		case INVENTORY:
			inventory.render();
			break;
		}
	}

I like to think that I can handle each state in a separate class/object, but I’m not sure I can. I just tried to load textures
Here is the “overworld” class

Here it is:

public class Overworld {
	
	private int[][] dungeonMap;
	
	public Overworld()
	{		
		final Texture blueWallTex = loadTexture("BlueWall");

		DungeonGenerator dungeonGenerator = new DungeonGenerator(10,20,3);
		dungeonMap = dungeonGenerator.getDungeonMap();
	}
	
	public void render()
	{
		//to be implemented
	}
	
	private Texture loadTexture(String key)
	{
		try
		{
			return TextureLoader.getTexture("PNG", new FileInputStream(new File("res/"+key+".png")));
		} catch (FileNotFoundException e)
		{
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return null;
	}

}

I shouldn’t have a problem so early on in the coding process, but I do.
The program spits a stack trace back at me, specifically:

“Image based resources must be loaded as part of init() or the game loop. They cannot be loaded before initialisation.”

Is there a way to combat this? I really want to handle each game “state” in a different class, but it won’t seem to let me do that without creating a new display in each object, which seems silly.

Any ideas? Thank you

Exactly as the stack trace says, you cannot load images before OpenGL is loaded. You are loading the images in the constructor of your class.

Now I’m assuming you use Slick2D, so I suggest you create an init() method in all your states that you call from the init() method of your main class.

If you’re using Silck2D, it has utilities for states and such.
If you’re using only Slick-Util, and you want to do things from the ground up, then you’ll need to write your own states. It’s relatively simple to do with classes.

The basic idea:

Your Game class has a list of GameState objects, and keeps track of which one it’s currently showing. Depending on your game, you may want to load all the state’s resources during the init() of your game (like Slick2D). Or you might want to load and destroy resources as you enter/exit states (i.e. only keeping what’s necessary in memory). The Game class simply renders/updates whatever current GameState is selected.

How you decide to organize this is up to you. Maybe you’ll use enums? Or maybe you’ll use generic objects, to allow for an infinite number of states?

Maybe you’ll want a single game state to hold multiple “screens” – i.e. an InGameState which holds different “screens” for each level, or a MainMenuState which holds “screens” for options, help, credits, etc. It all depends on the complexity of your game and how you’d like to implement it.

Hi

Actually, I have already implemented something very similar, it looks like what davedes suggests but in more general as I use states to handle the weapons too. I use Fettle API which is really a tiny and simple API to create state machines. I don’t directly store the states, I store the transitions between them. I can detect whether I enter a state or whether I get out of another one. Each time I go to another state, I hide all others and I show only this one. Each state is bound to a controller that updates the model (think about MVC) and renders the view(s). You can put some memory managements in transitions as davedes suggests, for example to destroy direct NIO buffers. I use a kind of task manager to handle the progress of loading, some states are then only used to display a progress bar and load all data for the next one. My source code does not explicitly rely a lot on a specific binding so you might be able to reuse it. If you already use Slick2D, you don’t need my help, ra4king’s suggestion is more appropriate in this case.

A few things:

  1. I’ve never touched init() ever, this is a application, not an applet, so I don’t use init(), right?
  2. I’m using Slick-Util and not Slick 2D, but I could install that if necessary
  3. Which opengl initializations does it want? I’ve made another class that makes a blank window, and it uses these initializations
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,GameDisplay.DISPLAY_WIDTH,GameDisplay.DISPLAY_HEIGHT,0,1,-1);
glMatrixMode(GL_MODELVIEW);

But when I simply paste this in front of my texture-loading code (in the constructor or Overworld) I get a “null pointer exception” on “glMatrixMode(GL_PROJECTION)”

Is what I’m trying to do even possible? The Display is handled by a completely different class (the one that calls Overworld)

I don’t know if it’s necessary, but I’ll paste that class here in case it’s important
As is, it correctly makes a black window


public class GameDisplay {
	
	final static public int DISPLAY_WIDTH = 600;
	final static public int DISPLAY_HEIGHT = 400;
	
	//The states the game can be in
	/*private static enum State
	{
		OVERWORLD, BATTLESCREEN, INVENTORY;
	}
	private State state = State.OVERWORLD;*/
	
	//Making an object for each of the states the game can be in
	//Overworld overworld = new Overworld();
	//BattleScreen battlescreen = new BattleScreen();
	//Inventory inventory = new Inventory();
	
	//Constructor
	public GameDisplay()
	{
		try
		{
			Display.setDisplayMode(new DisplayMode(DISPLAY_WIDTH,DISPLAY_HEIGHT));
			Display.setTitle("Dungeon Crawler");
			Display.create();
		} 
		catch (LWJGLException e)
		{
			e.printStackTrace();
		}
				
		//OpenGl Initializations
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(0,DISPLAY_WIDTH,DISPLAY_HEIGHT,0,1,-1);
		glMatrixMode(GL_MODELVIEW);
		
		//The Loop that runs the window
		while(!Display.isCloseRequested())
		{
			Display.update();
			Display.sync(30);
			
			//render();
		}
		
		Display.destroy();
	}
	
	/*private void render()
	{
		switch(state)
		{
		case OVERWORLD: 
			overworld.render();
			break;
		case BATTLESCREEN:
			battlescreen.render();
			break;
		case INVENTORY:
			inventory.render();
			break;
		}
	}*/
}

If you haven’t already, add to the rest of your imports. That should solve some of your problems.


import static org.lwjgl.opengl.GL11.*;

You might want to set vsync on insted of using Display.sync().

So,


Display.setDisplayMode(new DisplayMode(DISPLAY_WIDTH, DISPLAY_HEIGHT);
Display.setTitle("Dungoen Crawler");
Display.setVSyncEnabled(true);
Display.create();

Then you can increase Display.sync() to somewhere higher than 60, like 75, to cover for computers that are a little older and don’t support vsync.

  1. The init() function should contain the code you need to initiate OpenGL and the display window. It has nothing to do with applets except naming the method the same.

  2. If you want to use Slick2D you will have to discard all that code that you have there and follow the tutorials offered on the Slick2D website. Slick-util works fine for writing LWJGL applications, however.

Slick2D is easier and more Java2D like, but if you are a beginner in Java game programming you REALLY should just stick to Java2D.

  1. You might also want to enable transparency with the following before the rest of your OpenGL initialization code.

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Other than that it looks pretty good.

That import had been there. It really just doesn’t seem to want to accept the opengl initializations I put in the Overworld class (in the constructor)
(Also thanks for the vsync and transparency tips, I put them in)

Is there another way anyone knows of to separate the rendering of the display in different classes?

  1. Generally “init()” is a method you define that loads images, sounds, setups up orthographic projection, and so forth.
  2. Slick-Util is a small subset of Slick2D. It’s basically a couple of core classes extracted from the full library. If you want to keep learning OpenGL, stick with Slick-Util, or use another library like LibGDX. If your main goal is to just make a game, then you might find it easier to use Slick2D, LibGDX or another high-level library.
  3. Game states has nothing to do with OpenGL initialization. It’s just a matter of object-oriented design: moving what you have now (a switch statement) into classes.

You should also enable texturing: glEnable(GL11.GL_TEXTURE_2D) before rendering.

And regarding your game loop, it looks a little empty. Why 30 FPS cap? I’d suggest reading up on the basics:
http://www.koonsolo.com/news/dewitters-gameloop/

[quote]but if you are a beginner in Java game programming you REALLY should just stick to Java2D.
[/quote]
Nah, I disagree. IMO Java2D is much harder to use than Slick2D for a beginner. And aside from the obvious performance gains of using Slick2D (OpenGL vs software rendering*) you also get a lot of features related to game development, which obviously Java2D does not include. Things like game states (hence this thread), Tiled integration, bitmap fonts, themable UIs, basic pathfinding utilities, OGG decoding/streaming, etc.

  • You can enable hardware acceleration in Java2D with a JVM switch. Unfortunately, it’s unreliable – some users report a decrease in performance, others report no change, etc.

Nah, I disagree. IMO Java2D is much harder to use than Slick2D for a beginner. And aside from the obvious performance gains of using Slick2D (OpenGL vs software rendering*) you also get a lot of features related to game development, which obviously Java2D does not include. Things like game states (hence this thread), Tiled integration, bitmap fonts, themable UIs, basic pathfinding utilities, OGG decoding/streaming, etc.
[/quote]
Slick2D has a lot of code that you don’t understand until you’ve gained a bit more experience. Java2D, on the other hand, is simple and easy to understand from the start. Slick2D may have better performance, but it doesn’t really matter at beginner stage. With Java2D, you just need some imports to be set up, but with Slick2D you have to download LWJGL, tell it where it has its natives, and then download Slick2D and install it. There are also a lot more tutorials on Java2D, compared to Slick2D which has only a handful to a dozen tutorials.

Overall Java2D is better for when you’re just starting out.

Slick2D has a lot of code that you don’t understand until you’ve gained a bit more experience. Java2D, on the other hand, is simple and easy to understand from the start. Slick2D may have better performance, but it doesn’t really matter at beginner stage. With Java2D, you just need some imports to be set up, but with Slick2D you have to download LWJGL, tell it where it has its natives, and then download Slick2D and install it. There are also a lot more tutorials on Java2D, compared to Slick2D which has only a handful to a dozen tutorials.

Overall Java2D is better for when you’re just starting out.
[/quote]
Exactly! This (and the reason that there are more graphical features in Java2D than Slick2D) is why I still say Java2D is the perfect beginner playground.

Hi,

I think your problem here is that you instanciate your state classes in the attributes declaration which happens before the GameDisplay constructor is called … you should do this in the GameDisplay constructor after the init of the Display instead.

so just declare your attributes :


   private Overworld overworld;
   private BattleScreen battlescreen;
   private Inventory inventory;

and then in the GameDisplay constructor, instanciate them just before your game loop.

Thank you! Looking back on it, it seems so obvious. I don’t even need any opengl initialization code in the Overworld class

Thanks to everybody too, I’m looking into all of your suggestions

[quote=“Sickan,post:9,topic:38994”]
It all depends on what degree of “beginner” we’re talking about here. Something simple like tic-tac-toe doesn’t require a game loop, and in that situation I can understand Java2D/Swing.

But when it comes to sprite rendering and a game loop, things that even basic games (pong, space invaders, asteroids) will want to utilize, Java2D will only complicate a beginner’s life.

I see beginners doing android games all the time, and that requires even more setup than LWJGL. Seriously, adding a single native library is not the high barrier to entry people some people think it is.

One real problem with OpenGL development in general is the error messages, or the lack thereof. Setup instructions really should be using the debug library for development (I’m guilty of this too, but the debug lib isn’t even in maven repos, so I can’t do much about it in my instructions).

The people who begin Java games with Android are probably writing a lot of code that they don’t understand, just like those that start with Slick2D.

And no, adding a native library isn’t much. But it’s yet another step you have to make to set up your project to even BEGIN to write your code. And a lot of the motivation from writing games, at least for me, is the instant results.

If enabling a single plugin or pasting in a pom snippet or configuring a system property sucks all the energy out of your project, your motivation is even more tenuous than mine. Sorry, but I’d point at things like lack of good documentation as barriers to entry, not basic setup steps shared with nearly every other library in existence.

Okay, okay. Nevermind. The setup thing was a bad point.

I still think that Java2D is better for beginners than Slick2D, and so far you have only disproven my arguments without coming with any of your own.

I have to say that I’m happy I can even have this much of a discussion. There is no such thing on the Minecraft forums, except for things like how much $s graphic cards cost. And I’m not going to buy a new graphics card soon.

[quote=“Sickan,post:17,topic:38994”]
Ok then, let’s use a practical example. I dare you to come up with something this simple and beginner-friendly without using Slick2D. :slight_smile:

Task: Allow user to move a sprite smoothly across the screen at 60+ FPS – if it hits the left or right bounds of the window then play a sound.

What does it test? Game loop, input handling, image loading/rendering, and sound loading/playback. All the functions you need to make a great 2D game.

Slick Code

Your turn. :slight_smile:

How will a beginner learn how to make game loops with Slick2D? Boiler-plate isn’t always bad you know. Java2D is super simple and beginner friendly yet forces them to learn basic structures.

I win. Let’s end this argument. ;D

As a beginner, 99% of the game loops that you will be copy + pasting will go right over your head. ::slight_smile:

Who cares if they don’t learn game loops on their first game? They will learn it when they are ready – assuming they even want to learn it! You can write games without having to learn how to write the perfect game loop, in the same way that you can use a JFrame without knowing exactly what is going on under the hood.

ra4king – where is the “super simple” and “beginner friendly” Java2D code which produces the test I asked for? :wink: