My friend and I have started creation of a 2D adventure game. It will be top-down in the style of pokemon or zelda (just the perspective). We have been discussing methods of creating a large world-map that the player can traverse without straining the memory capabilities of our machine.

Our first impulse was to create a large map and a circle around the player in which content will be loaded. We figured this won't hold for long and decided to partition the map into sections. First we had four large sections, but realized we could simply break it down into many tiny sections.

I played some Zelda from the SNES and saw that, during the shift of a map, the content could be loaded just then. What I mean is, instead of just checking a rectangular area for data to load, we simply section the map into many tiny chunks that load and de-load data as we move from map-portion to map-portion.

Today, he told me he wanted to create a simply 2D array map[WIDTH][HEIGHT] that contains data about every grid in the game and is a constant save-to-disk operation for data that we don't need.

I'm not sure about these ideas and thought that I might as it here. Any links, resources or tutorials on the subject would be greatly appreciated as well as direct answers to our question on how to do it efficiently.

Windows with C++ using SFML so far (SFML is subject to change; C++ is not). We are not aiming for portability atm.
–
IAENov 3 '10 at 22:09

2

If you're going for old-school Zelda on the NES used 1-screen only maps. Small maps help players focus the scope of their intent (i.e. in a dungeon, you're dealing with your room only. In diablo, monsters didn't move up&down floors) and allow them to feel completion if they've searched the entire area that open-space games like FAllout3 and Oblivion don't give you.
–
Stephen FurlaniNov 4 '10 at 12:49

4 Answers
4

First off, estimate your map size. Don't just assume that a "big world" is not going to fit in memory. Nowadays, a map taking upwards of 10 mb in memory is absolutely acceptable, and you can stuff a LOT in 10 mb in a simple tile-based 2D world.

If you have a really large world, the most robust solution is indeed use map chunks. Split your world into fixed-size chunks (say, 64x64). Load chunks on-the-fly as player moves around, keeping at least one chunk loaded in all directions (i.e. load the chunk the player is in and all its neighbors).

As for unloading chunks, you can choose between several strategies. Eagerly unloading means you unload and save to disk all chunks the moment player moves sufficiently far away; but you can also delay unloading to improve performance (saving chunk, as any disk access, is a costly operation).

Some illustrative math: 10MB of Tile*s gets you a square with 1619 tiles per side. The original Zelda's maps were 256 tiles on the long side and less than half that on the short side - so your map could be more than 36x larger than the first Zelda's with that memory usage. Are you really prepared to make that much content? (No.)
–
user744Nov 4 '10 at 16:18

Personally, I'd build the map using a designated tile-editor like TileEd. This approach yields several benefits:

Uses less resources. You just have to load a tile-sheet and data-file with indexes to build a potentially endless map.

Since you'll have your map divided into really small chunks (depending on your tile-size), you can easily add/remove rows/columns while the character is moving through the world.

Having a data-file that describes your map also allows you to add terrain-information easily. This allows for different tile-types like walls or lakes (i.e. obstacles) or a swamp where movement of the character could be slowed down...

Last but not least, a tile-based map is also much easier to edit and tweak later on because you can always fire up the editor, change some things and save a new data-file.

I suggest you avoid loading bits of the map during gameplay to prevent lag. As mentioned previously, this should not be necessary as you'll probably be able to keep the tile-sheet in memory. When the character enters another part of the "world" you could swap the tile-sheet with a different one (eg. snow-tiles replaced with desert-tiles).

Blitting the tiles to screen is probably the fastest way to render your map. I don't know SFML, but from the docs on their site you should be looking into the Sprite class or use the Copy function of the Image class.

Update: I just read some of the SFML docs and you should definitely use Drawable or Sprite instead of manipulating images for the sake of performance. Apparently there's a Tiled SFML loader out there. That's probably a good way to get something up and running fast.

Start by making the map the size required to tell the story you wish the game to tell. Test on the machine with the minimum spec required for people to play your game. If it is too slow, profile and optimize.

Unless you're planing on re-building ultima-online (Fallout 3, or Oblivion), there's no reason the world needs to be seamless. Baldur's Gate and Icewind Dale are two games that come to mind that implement effective maps that do not detract from gameplay.

Granted, you've got a lot more computing horsepower than they did so loading screens should be minimal, but even Fallout and Oblivion have loading screens for some things.

All I can tell you is that for me, I'm writing a small Obj-C lib for the iPhone that takes a 32x32 tileset and draws it into an NSImage. I get about 10fps this way, and I probably should be using OpenGL, but I only need to re-draw if the character moves out of the rect.

You should split the map up into 9 screen-sizes (for me it's 960x640 blocks) so if the character moves out of the center block, I re-draw the 9-screens into a large image (about 1.2MB - gives a lot of room under the 20MB limit on iPhone 3G). That happens fairly slowly (much slower than 10fps) so the re-drawing is not noticeable during play.

I'll likely move to OpenGL ES at some point, but for now it works fine.

[EDIT]

Allow me to clarify.

The drawing algorithm for the 9-screen background takes 0.1 seconds (10fps flat-out). Unless your player can traverse an entire screen in less than a tenth of a second, the redrawing should be imperceptible during play.

Just because 10fps is acceptable for your game doesn't make it a good idea, especially on a device with power constraints like an iPhone. You could be doing zero redraws, let the GPU side handle rasterization, and actually let the program spend some time sleeping, so the phone doesn't get hot or run out of battery life.
–
user744Nov 4 '10 at 16:06

@Joe Wreschnig...??? I said it draws on demand, when the player moves the screen, otherwise the background image for the UIImageView doesn't get redrawn, thus saving processing power. Your comment doesn't make sense.
–
Stephen FurlaniNov 4 '10 at 17:14

I'm not making a claim about the fps your game requires. I'm saying, OpenGL can provide 60fps for such a thing trivially (really, you don't even talk about "redraws" with static scenes and OpenGL) - if you only need 10fps then using OpenGL lets you not waste battery power for the other "50 frames". Your drawing method is wasteful in a world with GPU acceleration. That's probably OK on a PC, but not when you're draining a battery.
–
user744Nov 4 '10 at 17:42

@Joe, I'm still not sure what you're saying. It draws an image. Then the image is left alone until the player reaches a boundary, and then re-draws a new image. How does that waste battery life? It only "draws" on demand, and the rest of the time the view is drawn using UIImageView's native drawing algorithm.
–
Stephen FurlaniNov 5 '10 at 11:35