recommended ways of storing game entities and state game structure

Started by
14 comments, last by mickd 12 years, 1 month ago
I'm working on a very simple 2d tile-based game for educational purposes and have a question about how the game entities should be stored and drawn, and a question about the design of a state based game.

For the first question:

The simplest way seems to be just to store them in a List structure (for example, a list of Monsters) but my concerns start to arise when you potentially have a list of thousands of monsters on the map.

When displaying the monsters, you would only need to draw the ones that are visible on the screen (within a set amount of tiles from the player). Would there be a better way than to iterate over the list every frame to calculate which monsters are close enough to the player to be drawn, then draw them?

For the second question:

I currently have a ResourceManager class which has a static reference to a KeyHandler and a MouseHandler class, amongst other things. This is currently allowing me to easily call the key and mouse handlers from any of my states, since I can just go ResourceManager.getKeyHandler(). Is this bad practice? If so, any suggestions? I've actually got a very similar thing with an EntityManager which has static calls to retrieve things like the current Player class and list of Npcs/Monsters, etc.

Thanks for any input, it will be greatly appreciated.
Advertisement
Something like ArrayList is typical. This will work well provided you don't have TOO many things.

Presumably you're iterating the list to carry out logic on each monster or whatever (e.g. an overridden method called tick() which does not do anything on the base class).

This works fine until you have a HUGE amount of things.

Then you'd need to make some kind of active/inactive system.

Suppose you have several lists - one for each "zone" on the map. Each monster can be on their own zone list, as well as on an "active" list. Once the player goes sufficient far away, monsters can be "frozen" - removed from the active list.

Once the player goes nearer, you can "reactivate" the zone that was "frozen".

It is of course, additional maintenance to do and quite easy to get wrong. If you allow monsters to move between zones, you need to take care of ensuring that they appear only on the zone-list of the zone they're currently in.

So I'd say, YAGNI, and do the simplest thing which could possibly work.

---

If you're like to have, say, 1M monsters in your game, you will probably need this optimisation.

Depending on whether the game is "naturally" split into zones, levels etc, you may not need this optimisation.

For example, if your dungeon has "floors" which monsters can't easily (or perhaps, at all) travel between, you only need to consider the current floor's worth of monsters. This way you might avoid the problem.
No, iterating over the entire list every update is not the most efficient way to solve the problem when not every entity needs to be updated every frame, but it will probably not cause you any performance issues in a simple game. This especially applies if you add a flag to each entity and any that do not need to be updated constantly could be ignored based on the status of the flag.

However, if it bothers you, you can keep a list of all entities, and then a separate list of entities that are currently relevant and update only those. If you look at each entity as a task in a system, then your game simulation becomes a kernel and you could manage tasks similarly. I'm not going to get into that here because task scheduling is huge and there's no one right way to do it.
Thanks guys! I think that answers my first question completely! Just one follow up on markr, is tick() another way of saying update(dt)? For my purposes, I think I'll keep it as simple as possible for now, and if I do come by any problems, I'll implement a system similar to your suggestions.

Also, I would love some extra input on the second question ;)
For your second question:

When you say "resource" do you mean assets or system resources? If you mean assets, then I think it's a little strange for an asset manager to hold references to system devices like the mouse and keyboard.

I think the most strict developers would advise against storing those references as public properties on other managers and instead use the dependency injection paradigm to share those references only with those objects that need them. Doing that will ensure that any class that needs a reference to your keyboard handler will have one.

The simplest way to implement this fancy idea of "dependency injection" is to simply require it as part of the constructor:


class SomeClassRequiresKeyboard {
public SomeClassRequiresKeyboard(KeyboardHandler keyboardHandler) {
if (keyboardHandler == null) {
throw new ArgumentNullException("keyboardHandler");
}
this.keyboardHandler = keyboardHandler;
}
}


This does make your software a little more verbose because of all the additional code to make sure your objects are where they need to be, but it does also make your code more understandable because dependencies are explicit.
Regarding your first question: you can also check which entities are in range when moving your player and than set a flag on them to not update, e.g. entity.inRange=false
I'm not sure why many of your classes would need a reference to the Key or Mouse handlers. To my mind, there should be a single part of your code concerned with handling mouse or keyboard input (somewhere in your user interface layer), which then sets gamestates or something similar to act on that input. It'll be easier to maintain if all your input is centralised somewhere.
[size="2"]Currently working on an open world survival RPG - For info check out my Development blog:[size="2"] ByteWrangler
Thanks for the replies everyone. It really does help get me thinking.

The resource manager initially also had the player class in it (which I moved to the entity manager), but at the moment I have the world class, the game engine and mouse/keyboard handlers. I'll have a think how I want to redesign things to hopefully make more sense. I really don't like the way I've done things (which is why I decided to ask here), but for the time-being that was the simplest way I could think of doing it. So at the moment it does kind of include both system resources and game resources.

Does this mean in general when writing a game people pass references of what each class needs as they create the class? It gets pretty messy since I feel as if so many different classes need access to so many different other classes (but that's probably a huge design flaw I currently have).

Are there classes that you guys (when writing a game, simple or complex) generally have shared with the whole system?

What about with texture handling? At the moment I have a texture manager which basically just holds a public static reference to the sprites atlas for binding and getting the correct texture coordinates in the sprite atlas.

I'm not sure why many of your classes would need a reference to the Key or Mouse handlers. To my mind, there should be a single part of your code concerned with handling mouse or keyboard input (somewhere in your user interface layer), which then sets gamestates or something similar to act on that input. It'll be easier to maintain if all your input is centralised somewhere.


Oh, I should have probably been more specific about this but the keyHandler and mouseHandler classes just hold a hashmap of which keys were pressed (for the keyHandler) and which location on the screen was clicked (for the mouseHandler). They don't handle the events (the JPanel uses key bindings and a mouse listener to do this), more so just store what event was triggered. Every game state would need access to these since I have to be able to processEvents in each game state. Same with each component of the screen (inventory, etc).
One approach would be to instead of giving the player access to the keyboard and mouse, create instead an interface called Controller or something like that. You could then create an implementation of this Controller that uses the keyboard. This way the player knows nothing about keyboards or mice. It just knows how to follow commands coming from this controller.

An added benefit of this that you could implement different types of controllers, like ScriptedController, NetworkPlayerController, AiController, etc. that could be used for multiplayer, controlling AI entities, demo playback, etc.

This topic is closed to new replies.

Advertisement