Jump to content

  • Log In with Google      Sign In   
  • Create Account


recommended ways of storing game entities and state game structure


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
15 replies to this topic

#1 mickd   Members   -  Reputation: 100

Like
0Likes
Like

Posted 13 March 2012 - 07:24 AM

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.

Sponsor:

#2 markr   Crossbones+   -  Reputation: 1653

Like
2Likes
Like

Posted 13 March 2012 - 09:50 AM

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.

#3 smr   Members   -  Reputation: 1552

Like
1Likes
Like

Posted 13 March 2012 - 09:54 AM

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.

#4 mickd   Members   -  Reputation: 100

Like
0Likes
Like

Posted 13 March 2012 - 06:42 PM

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 ;)

#5 smr   Members   -  Reputation: 1552

Like
1Likes
Like

Posted 14 March 2012 - 10:23 AM

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.

#6 Basfreak   Members   -  Reputation: 101

Like
0Likes
Like

Posted 14 March 2012 - 10:33 AM

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

#7 Postie   Members   -  Reputation: 863

Like
0Likes
Like

Posted 14 March 2012 - 08:24 PM

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.
Currently working on an open world survival RPG - For info check out my Development blog: ByteWrangler

#8 mickd   Members   -  Reputation: 100

Like
0Likes
Like

Posted 15 March 2012 - 05:09 AM

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.

#9 mickd   Members   -  Reputation: 100

Like
0Likes
Like

Posted 15 March 2012 - 05:19 AM

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).

#10 smr   Members   -  Reputation: 1552

Like
0Likes
Like

Posted 15 March 2012 - 08:31 AM

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.

#11 Zael   Members   -  Reputation: 154

Like
0Likes
Like

Posted 15 March 2012 - 11:15 AM

Something like ArrayList is typical. This will work well provided you don't have TOO many things.


I prefer LinkedList for this type of Collection, but you have to use it correctly to get the performance benefits it would offer. Granted the performance benefits would really only exist when inserting or removing elements.

#12 Postie   Members   -  Reputation: 863

Like
1Likes
Like

Posted 16 March 2012 - 07:45 PM

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).


Ah ok, that makes more sense.

One of the things I've learnt in the last 15 months working on my current project is that I only ever come up with the "right" design for something at first attempt about 1% of the time. Sometimes it's not bad but needs tweaks. Other times it's awful. My current game engine has evolved a lot as I've added new functionality and decided some part of the design was flawed. I've actually spent a fair bit of time rewriting existing code, but each iteration the system becomes better and more logical in my opinion. So I've learnt to not stress too much about having a perfect design from day one.

Generally speaking though, one of the metrics I use to tell if something isn't "right" in my code is that there are ALOT of interdependencies going on, ie many references to other classes that are passed through into other classes. There's not always an obvious elegant solution however. Sometimes you just have to live with it. :)
Currently working on an open world survival RPG - For info check out my Development blog: ByteWrangler

#13 mickd   Members   -  Reputation: 100

Like
0Likes
Like

Posted 17 March 2012 - 08:19 AM

Thanks for the replies!

I've already change my design slightly (still feels a bit off, but it's slowly getting better). I'll definitely just keep working on it to help discover more design flaws that I can work into fixing in the next iteration of the engine. It's been a great learning experience already.

Did you guys have any comments specific to storing textures? How would your draw functions in your various game entity classes access the textures? Should each class be storing a reference to it's own texture for binding and rendering? Should they be centralized in any specific way? Is it a bad idea to have a single class with static variables and functions to hold the texture files and control binding?

#14 Postie   Members   -  Reputation: 863

Like
1Likes
Like

Posted 17 March 2012 - 05:06 PM

I would definitely cache your textures. Creating and destroying Texture objects all the time is a great way to kill your frame rate. I like the idea of having a centralised Texture Cache that's responsible for creating and destroying Texture objects because I use an "on-demand" resource allocation strategy. Ie, on render, I'm checking if the resource is allocated or not, and creating it as required, rather than allocating everything on load. This also allows texture re-use if objects are using the same texture.

You can then get a bit more advanced with reference counts to deallocate textures that you haven't used in a while to manage your video memory a bit better.
Currently working on an open world survival RPG - For info check out my Development blog: ByteWrangler

#15 L. Spiro   Crossbones+   -  Reputation: 12196

Like
1Likes
Like

Posted 18 March 2012 - 12:18 AM

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

You may find this useful: General Game/Engine Structure


L. Spiro
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#16 mickd   Members   -  Reputation: 100

Like
0Likes
Like

Posted 18 March 2012 - 03:08 AM

@YogurtEmperor Not only did I find that useful, I read it when I found it on google from an old post you made! Thanks!

@Postie Yep, sometimes I feel as if I just need a confirmation from others that what I'm doing is within reason. Thanks as well!




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS