Making a 2D platform engine, wondering how to handle the ENTIRE level...

Started by
5 comments, last by ill 14 years, 9 months ago
OK, so I know a simple way to make a 2D game run fast is to just disable all the stuff far outside the game view and not even think about it, but with the engine I'm planning there will be some things that need to remain active at all times. Moving platforms for example, and AI that is currently doing something. This is how I've made games before but now I'm trying to have the entire level be processed quickly. So I've come up with some ideas and I'm wondering if there is an actual right way to do this kind of thing and if by any chance my way isn't that great before I start doing it. So the following is a basic description of how the engine will work. Basically the entire level will be subdivided into chunks slightly bigger than the view port. Each chunk keeps track of the objects inside it, and when an object moves it checks what level chunk it's in currently and puts it into the right one. The main game loop should go through the entire level taking care of each level chunk one by one. It only considers level chunks with active objects in them so if a level chunk just has some random item not being affected by physics or an AI controlled character that's currently idle, it'll skip over it. When a level chunk gets processed, all active objects within it have their game tick code executed, whatever it may by. Those objects only interact with other game objects in its level chunk, and the surrounding 8 level chunks that border it. Static level collisions are only considered by the ones in the object's level chunk. If the object intersects more than one level chunk with its bounding box, it also checks for collisions in those level chunks as well. If an active object modifies an inactive object in any way, that modified object becomes active to process the changes in the next game tick. Once an active object is processed it gets marked as processed so that if it somehow ended up in another game chunk by moving and is added to another game chunk, it won't get processed twice (or possibly even more times) in a game tick. The processed flag is a boolean value that toggles at every game tick and doesn't need to be reset before each game tick because it alternates values. So in one game tick only objects with the flag marked true are processed and then its set to false. Next game tick, only objects marked with false are processed and it's set to true and so on. (Wow I just thought of that while writing this heh) Active objects are anything that's doing something, like the player(active at all times), a bullet, an AI character that isn't just standing there, a moving platform that is actually moving, an item that is currently being affected by physics and not just laying on the ground, or anything at all with an active animation(my animation system will have it so code can be executed when a certain frame plays so if an animation is in progress that might potentially cause some code to execute, that needs to be active). Also all objects that are in viewable level chunks are active at all times so their drawing code can be processed and particles can be spewed from them or whatever is needed even if they are just lying there doing nothing. I've given this some considerable thought and thought of ways around a lot of problems that might arise so this is a pretty comprehensive list of how my engine should work for now. I haven't even started thinking about how I'm going to do collision detection and physics yet. I'm planning on doing an engine similar to Soldat where the game world is made of triangles not a tilebased game which is typical of 2D platformers. Basically I'm using SDL with OpenGL for graphics, FMODex for sound (because I like FMODex and know how to use it), writing it in C++ and hoping it'll be runnable on at least Windows, Linux, and Mac OSX. Currently I'm coding on Windows XP with Eclipse IDE and minGW because my laptop has an ATI Radeon 9600 which is no longer supported by ATI(bastards!!!) and as a result there are no working drivers for Ubuntu 9.04 that will give me Hardware graphics acceleration for working with OpenGL. I like coding on my laptop since it's much older than my desktop and I can make sure my games run on older lower end systems and don't require a Geforce 8600 to be runnable so I can't test the game on my Linux installation so I won't even bother writing it under Linux.
Advertisement
The "chunk" logic you're talking about sounds a lot like a flattened quadtree, which is in fact an ideal datastructure for spacial partitioning, especially if you may have lots of mostly empty space and a few areas with a lot going on. If you're working in 3D, the same concept applies, but it's an octtree because you have the extra dimension to deal with.

One thing you may want to consider is not updating areas that have active objects in them unless they're close to the player. Think of Super Mario Bros, for example -- goombas and turtles don't start moving until they're nearly onscreen. Not only does this save you on processing power; it also ensures that your obstacles are set up just so for when the player arrives. You wouldn't want all the enemies to have wandered off by the time the player gets there, after all.
Jetblade: an open-source 2D platforming game in the style of Metroid and Castlevania, with procedurally-generated levels
Yeah I know all about the Mario thing you just talked about, but the game is going to be a lot more complicated than that.

My enemies aren't really going to wonder off or anything either. Like all the AI and battles and stuff will in fact not happen unless it's started. One major issue with only updating areas around the player is things like moving platforms that move out of the active area get lost forever until the player moves near them again. And allied soldiers and things like that also get lost.

Also when the player flips a switch and for example, a platform from the other side of the level is supposed to move, it won't happen unless it's also active. And then it needs to interact with other objects in its way. Like if a big monster is supposed to be carried by the platform the platform itself needs to keep things active around it.

Also I was thinking about how a server would handle multiple players and this is the only logical way to handle for all the players.

The client itself would only really know about its surrounding near areas.

Single player can work the same way where there is a local server handling the game logic, and the client is the player's view of the level. I might rethink my idea about level chunks in the visible area having objects being active at all times since more of them would be visible if more players are connected to a server.

I'll take a look at that quadtree description.
Quote:Original post by ill
One major issue with only updating areas around the player is things like moving platforms that move out of the active area get lost forever until the player moves near them again. And allied soldiers and things like that also get lost.

Just give them a timer of some sort. When they're in an inactive zone they will only be updated for so long. For some objects, you may want to keep updating them for a very long time, or simply forever, regardless of where they are.

Quote:Also when the player flips a switch and for example, a platform from the other side of the level is supposed to move, it won't happen unless it's also active. And then it needs to interact with other objects in its way. Like if a big monster is supposed to be carried by the platform the platform itself needs to keep things active around it.

Going with the above suggestion, that switch could simply set the triggered platform's timer. Or perhaps mark the whole region/regions as active, for a while.


However... how expensive is it really going to be to update all your game objects? How much do you intend to have in an average level? In other words, is this really going to be a problem? For collision-detection, high-level culling (quadtree, grid, etc.) is often necessary due to exponential growth in the number of checks. But unless your game objects are very complicated, just updating all of them probably won't give you any trouble. It also lets you avoid those nasty border-cases that you'll likely run into. Don't make things more complicated than they need to be.
Create-ivity - a game development blog Mouseover for more information.
I think making things not update when outside the view was actually making it more complicated than having everything that needs to be updated get updated. I think it shouldn't be expensive at all to update most of these objects since a lot of them won't be active.

Also I was just thinking about how awesome the quad tree idea is since it'll greatly speed up the process since large numbers of areas won't ever even be considered.

I can also subdivide the gamechunks static collision areas into even smaller areas making less static collisions be checked.
If your game has 'cause and effect' dependant stuff going on offscreen then you will need to update those things all the time. Updating positions and velocities of offscreen objects shouldn't be too much of a problem. As far as gameplay goes, the best way to make this viable is just not to have stupidly big and complicated levels. Given that it's 2d, however, this shouldn't be a significant restriction.

Also don't worry too much about targeting 'old' hardware. By the time you're done there's a good chance that what you've been targeting will be deprecated.
Well by old hardware I mean my thinkpad laptop which isn't that old actually.

It just lets me know that my code isn't awfully inefficient and things like that.

This topic is closed to new replies.

Advertisement