How to implement a procedural loading system?

Started by
3 comments, last by Buckeye 9 years, 6 months ago

Hello! I was pondering a while ago about how i load the levels in past iterations of a simple game engine i have written. For it to work smoothly, i separated the whole map in different sections, and every time you enter in a new section, all of its tiles will load, while the tiles of the previous sections will be deleted. Now, this works since each section is pretty small, so the game doesn't have to load so much Data. But i was thinking, what about large maps, not divided by areas. I thought in a method of procedural loading. I mean, there would be a circle, with a significant radius, where the player would be in the center. And everything inside this radius would work. For the sake of simplicity, it doesn't actually need to be a circle, it can be a rectangle as well. So everytime the player moves, so does this area, so a whole new line of Tiles are loaded, while a whole line of tiles are discarded. Now, i wonder two things: 1- How could this system be implemented?? In a way that, how can i organize the world tiles so that i wouldn't have to check all of them to see if they are part of the rectangles. And 2- Wouldn't this take too much time with the memory management?? Would i have to implement a new Memory management system? And if so, how practical is this?? Do any of you have a different method for achieving the same thing?? Thank you very much.

Advertisement

Grid can be preferred if you have unitized chunks (areas/zones) of your world you load as your player moves. The chunks on disk ('rolled out' is an old term) lie dormant until they are needed to interact with the player. There may be some general bookkeeping needed for the entire map (all areas) which usually is far less data and can be kept in memory. Sometimes changes which were supposed to have happened can be 'caught up' for the newly loaded areas.

The areas/chunks can also be irregularly sized/shaped if that is the nature of your game world map. (A regular grid is easiest to program for but a, irregular network of area nodes could likewise be done ).

With grids you have a square 'window' with the player in the center of the grid which then moves, and as you said you adds a row (or 2 if youve moved diagonally). A good sized grid all around the player (like 7x7 9x9 15x15 etc..) so the outer edge has adaquate time to load before the player gets close enuf to interact with whats in that terrain.

You can have a Level of Detail (LOD) mechanism where certain tiers of interaction are run in each zone/are/chunk - where NPCS/objects too far away to be seen or interacted with can be dormant or even a staged loading (like you only load coarse level of detail for the scenery when its very far away then the full detail when its close enuf to be seen and NPCs behavior code doesnt have to be loaded or run or only run in a generalized fashion when far away - shifting to full detail when sufficiently close.

Ive actually done such a system for a continuous world and the most complicated part was the edges of the areas/zones where objects/NPC could cross over between areas of high/low detail and have to adjust (remember that many could interact with other objects/the terrain and not just the player). Some objects are only local (dont move around) and are pretty simple in their behavior, and other 'significant' ones need to operate in their full AI behavior all of the time (to act properly) and cross the area boundries constantly.

When I did my system I actually had the 'simple' objects live in the data chunk (an offset system with a heap in a memory block) and they loaded directly into memory (or were written to disk) largely intact and requiring minimum conversion/translation/allocation/constructor/destructor into running data. I also had 3 LOD tiers of terrain data, as many of the outer grid zones/areas never did get interacted with fully (all depends on which way the player moves) but could be seen from a distance. Some areas of the map were even procedurally generated so didnt have to be kept as full detail (like ocean zones) and others (filler terrain) could be generated into full detail (including plants/animals) on-the-fly from world seed data and contained fairly generic content (as compared to game plot specific zones which had to be hand crafted).

--------------------------------------------[size="1"]Ratings are Opinion, not Fact

I see! Well, it sounds practical enough, but, would it be needed for a finite 2D map? I mean, surely it is important for 3D worlds, where each objects has such a level of detail that can drain the memory pretty fast, but i am uncertain about a 2D game. I wouldn't want to develop a mechanic which will do more harm than good.

I see! Well, it sounds practical enough, but, would it be needed for a finite 2D map? I mean, surely it is important for 3D worlds, where each objects has such a level of detail that can drain the memory pretty fast, but i am uncertain about a 2D game. I wouldn't want to develop a mechanic which will do more harm than good.

Depends on the game, the map, and depends on the load times. If you do not like your current load times and you want a 'seamless' feel to the game, then it may be worth investigating. If the load times are sufficiently short, or can be entirely front loaded, like Space Pirates and Zombies, which loads all its assets up front once, and then has no load times while the game is running, then it may not be an issue to just load levels discretely.


Would i have to implement a new Memory management system?

If your current memory management scheme does not detect an "out of memory" condition and does not handle it gracefully, then you need a memory management system now that handles errors.

As ferrous mentions, the approach you decide on should reflect the needs of your program. There are several approaches you can consider:

1. Load/discard data as needed. If load times become intolerable, try another approach. I.e., don't optimize and rewrite code until you need to.

2. Memory map your data file and let the operating system take care of swapping disk contents in and out of memory.

3. Load data for the current area, plus areas surrounding the current location that aren't immediately needed but which the character may choose to enter. As the character moves, needed data will always be available. When a new area is entered, discard areas "behind" the current area and load in areas "ahead" of the current area. Loading in those surrounding areas need not be done all at once. Load just a portion of the data at a time, reducing the time of any single disk access. N.B., this may cause the disk to spin up and down - which can be annoying.

4. Implement approaches 2 and 3 in a separate thread and check signals to see if needed data has been loaded.

5. Allocate a large chunk of memory on the heap. Load needed data into a portion of that chunk, keeping track of what area it represents, where, when and how much memory of the main "chunk" was used. When more data is needed, check if the needed data was previously loaded. If so, continue from there. Otherwise, check if sufficient room is available in your "chunk" to load the new data. If so, allocate the room from your chunk and load it. If not, free the oldest allocations or data farthest from the current area until room has been created.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

This topic is closed to new replies.

Advertisement