Large game areas

Started by
7 comments, last by NextEpisode1 13 years, 7 months ago
Basically i want to give the player the ability to move outside screen borders (so far in all my projects the screen was the actual play area), and i cant think of anything decent to accomplish that.

The principle i used so far is :

I got a matrix with nrs on it , and each nr corresponds to a sprite thats is loaded on the element's position a[0][0] will be the top left of the screen but i cant use same technique with larger play zones (imagine a static 20000x20000 matrix lol)

How should i handle the "ground" change when player moves outside borders?
#include <iostream>#include <string>int main(){ std::cout<<"I will kill your stack"; return main();}
Advertisement
I assume you're talking about a 2D grid. If so, when the player moves "offscreen," change the value of the subscripts for the upper-lefthand corner of the screen.

I.e., if the player is at the right edge of the screen and moves to the right (offscreen), change a[0][0] to a[1][0] and redraw the screen, keeping the player at the same screen position.

If the player is at the bottom of the screen and moves down, change a[0][0] to a[0][1] and redraw the screen.

Of course, before you allow the player to move, you must check that he won't move beyond the boundaries of the array.

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.

Quote:Original post by Buckeye
I assume you're talking about a 2D grid. If so, when the player moves "offscreen," change the value of the subscripts for the upper-lefthand corner of the screen.

I.e., if the player is at the right edge of the screen and moves to the right (offscreen), change a[0][0] to a[1][0] and redraw the screen, keeping the player at the same screen position.

If the player is at the bottom of the screen and moves down, change a[0][0] to a[0][1] and redraw the screen.

Of course, before you allow the player to move, you must check that he won't move beyond the boundaries of the array.


im not sure what you mean. if i understand right you suggest when the user moves i move the background not the player, but the problem still persists , for large game areas like 2k * 2k squares i will have a matrix with 400 k elements witch is an overkill (even if i dynamic allocate it)

What do u think about txt files that contain the level layout ,and when the player moves the matrix updates from there? but still im not sure that's the best way
#include <iostream>#include <string>int main(){ std::cout<<"I will kill your stack"; return main();}
So is the desired effect the map scrolling with the player or a slide transition zelda-style?
Quote:the problem still persists , for large game areas

Ah, I misunderstood the emphasis of your question. It was about the size of the array and not how to accomplish the scroll.

For large areas (more than you want to store in memory), initially load a reasonably sized array (from a file) centered on the player. When the player moves close to the edge of the loaded array, load another array (from a file) centered on the current position of the player. In a couple games of mine, I use a separate thread to load the arrays to limit stuttering of the display during loading.

When the thread has loaded the new array, I switch the arrays (just a pointer to the array), and continue rendering.

It takes some bookkeeping but, if memory isn't available, something like that must be done.

With regard to what is stored in the file, it depends on what you want to store. If you have a limited number of tiles to display (less than 257), the file can consist of a single byte per tile. Otherwise, you can store some type of information to describe the tile.

In either case, binary data would take less space and be quicker to load than reading text and interpreting it.

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.

Quote:Original post by F4113ND3MON
So is the desired effect the map scrolling with the player or a slide transition zelda-style?


i did not play zelda but the map scrolling seems good (diablo style)
#include <iostream>#include <string>int main(){ std::cout<<"I will kill your stack"; return main();}
Quote:Original post by Buckeye
Quote:the problem still persists , for large game areas

Ah, I misunderstood the emphasis of your question. It was about the size of the array and not how to accomplish the scroll.

For large areas (more than you want to store in memory), initially load a reasonably sized array (from a file) centered on the player. When the player moves close to the edge of the loaded array, load another array (from a file) centered on the current position of the player. In a couple games of mine, I use a separate thread to load the arrays to limit stuttering of the display during loading.

When the thread has loaded the new array, I switch the arrays (just a pointer to the array), and continue rendering.

It takes some bookkeeping but, if memory isn't available, something like that must be done.

With regard to what is stored in the file, it depends on what you want to store. If you have a limited number of tiles to display (less than 257), the file can consist of a single byte per tile. Otherwise, you can store some type of information to describe the tile.

In either case, binary data would take less space and be quicker to load than reading text and interpreting it.


Thats a way to solve it.

But in case of a "Player in center" view , il have to update the map and the npc's on it each time the player moves and im pretty afraid that the input buffer could not handle the "pressure".

Isn't there a tutorial somewhere? lol

#include <iostream>#include <string>int main(){ std::cout<<"I will kill your stack"; return main();}
Just stream in the map data in sections, like a quilt. Google Maps does this very same thing.

I streamed map sections in a very old game of mine -- Even running in 16bit DOS mode, on a 4x86 running at 66Mhz, and pulling the map from a 3.5" floppy disk and a map with 3 layers there was no noticeable slowdown or stutter. Each screen consisted of 20x15 tiles, 3 layers, one byte each -- so 900 bytes per screen. I loaded 9 screens (3x3 grid) worth of data, and when I crossed the border between "screens" I would simply shift these grids so that the one the player was in was in the center of the 3x3 grid, update the grid origin and load the 3 or 5 (diagonal movement) that needed to be loaded (which were all still entirely off-screen at that point.

You can save reloading a ton of data by loading data into chunks, rather than a single array and then shuffling pointers to the chunks -- you could do the single contiguous array and memcopy bytes to move things around too, but its a little tricky, and you can avoid the memcopy by the chunking method -- if you make map chunks a power of two in size (they don't have to be screen size) then it also fits well with other modern techniques like Quad-Trees.

The above is the simple and straight-forward method, if you want something a little more modern, I would recommend storing the map in chunks on-disk, along with a simple graph structure that describes which chunks are next to one another. Then, when you step into a new chunk, you check the graph and load its neighbors. Each chunk can be loaded into a cache, and each chunk has a 'last-used' number associated with it -- when you load a new chunk, it's 'last used' number starts at 0, and all the other chunks' 'last used' numbers get incremented. When you reach the maximum number of chunks you want to have loaded at any one time (to control memory use) you simply replace the chunk with the highest 'last used' number. You could also just randomly evict any chunk that is not the current chunk, or a neighboring chunk, and still keep redundant loads down pretty low. The benefit to this approach is that you decide exactly how much memory you want to spend on caching map data, and it will keep the most-likely to be seen chunks in memory.

throw table_exception("(? ???)? ? ???");

Quote:Original post by Ravyne
Just stream in the map data in sections, like a quilt. Google Maps does this very same thing.

I streamed map sections in a very old game of mine -- Even running in 16bit DOS mode, on a 4x86 running at 66Mhz, and pulling the map from a 3.5" floppy disk and a map with 3 layers there was no noticeable slowdown or stutter. Each screen consisted of 20x15 tiles, 3 layers, one byte each -- so 900 bytes per screen. I loaded 9 screens (3x3 grid) worth of data, and when I crossed the border between "screens" I would simply shift these grids so that the one the player was in was in the center of the 3x3 grid, update the grid origin and load the 3 or 5 (diagonal movement) that needed to be loaded (which were all still entirely off-screen at that point.

You can save reloading a ton of data by loading data into chunks, rather than a single array and then shuffling pointers to the chunks -- you could do the single contiguous array and memcopy bytes to move things around too, but its a little tricky, and you can avoid the memcopy by the chunking method -- if you make map chunks a power of two in size (they don't have to be screen size) then it also fits well with other modern techniques like Quad-Trees.

The above is the simple and straight-forward method, if you want something a little more modern, I would recommend storing the map in chunks on-disk, along with a simple graph structure that describes which chunks are next to one another. Then, when you step into a new chunk, you check the graph and load its neighbors. Each chunk can be loaded into a cache, and each chunk has a 'last-used' number associated with it -- when you load a new chunk, it's 'last used' number starts at 0, and all the other chunks' 'last used' numbers get incremented. When you reach the maximum number of chunks you want to have loaded at any one time (to control memory use) you simply replace the chunk with the highest 'last used' number. You could also just randomly evict any chunk that is not the current chunk, or a neighboring chunk, and still keep redundant loads down pretty low. The benefit to this approach is that you decide exactly how much memory you want to spend on caching map data, and it will keep the most-likely to be seen chunks in memory.


As they say when playing starcraft GG . thanks
#include <iostream>#include <string>int main(){ std::cout<<"I will kill your stack"; return main();}

This topic is closed to new replies.

Advertisement