How to handle huge maps?

Started by
3 comments, last by GameDev.net 18 years, 9 months ago
Hi, I am making a hexagonal game, but instead of using small images and then paint the hexes, I want to use real map images that I will draw on the background, and then I'll draw the hex borders, units and decorations on it. The problem is my map is going to be quite large, about 10x15 meters. Each image will be 24 bit, so obviously I can't keep them all in the memory. Since the player will mostly watch the part of the map that will belong to him, I decided to cut the image into segments and then load the images I need, while keep the rest on the disk. Let's say a segment is 500x500 pixels, then I would be needing 4 segments on an average screen resolution. But what next? If the player scrolls to some other part of the screen, then I cannot allow that he has to wait a few seconds until the images get loaded. I guess I could also load the "surrounding" images, then I'd have around 20 images in memory, while the majority of images won't be loaded. Anyway, I am looking for ideas how to do this in the most optimal way. Reading images from the disk takes about 1/4 of a second, which can (perhaps) get ignored by the player in case he jumps to a remote part of the map, but if he scrolls up 20 pixels he shouldn't experience anything.
Advertisement
This is a fun one - lots of scope for solutions [grin]

My advice would be to look into spreading the actual loading out over various frames. To keep it simple, say the image is 1MB in total, over 1 second (say 50 frames maybe?) you load in 1/50th of the image each frame (~21KB). It'll slow down a bit during the loading, but it won't be a sudden stop-start type loading and hence won't be so noticeable.

I'd design your texture/image pool such that you can make use of as much memory as possible. That is, dont fix it to a specific size (e.g. 25MB) - instead enumerate the underlying system and take advantage of it [smile] My system has 1GB SysMem and 128mb VRam so use it - but maintain scaleability for those with lesser/greater systems. The reasoning for this is that you'll either have less loading to perform (overall), or because more data is in storage you can spend more time loading stuff as the "close" data is likely to already be in the cache.

I've not tried it myself, but I've been told that putting the data-loading into a seperate thread works well as you don't stall your main thread on IO waiting.

hth
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

That idea about putting the IO in a separate thread is interesting, I would never had thought of it myself. [grin]

The problem with updating the screen is that I don't do it in the way most games do (drawing as many times as possible, using 100% of the CPU), but instead I do updates only when necessary. For example, when a unit moves, or the map gets scrolled, only then is the map redrawn. This way the game uses 100% of the CPU only for a few seconds and then it returns to 5-10%, so it should be ideal when you're doing something in the background (scan for viruses) and you want to kill time. At least that's the idea... [wink]

So I cannot really do updating on a frame basis, it would have to be immediate.
How much would cutting the image into really small segments (50x50) help? This would solve the immediate feeling when the player scrolls only a few pixels, but I guess it would take longer when I need to read in an entire screen.
Loading in a seperate thread is probably ideal if the game itself dosn't hover at 100%.

The idea should be to keep a large enough buffer space around the screen so that any region scrolled into will be available while the next region over can be loaded from the HDD.

As jollyjeffers suggests, if you have plenty of RAM, take advantage of this and make the buffer region larger.
Try to arrange your disk accesses so they occur sequentially. and if possible try to cluster data together in the file. The effect you want to achieve here is to keep the head movement of the drive as small as possible. You also want to read in as much relevant data as possible without an intervening seek operation. This will reduce the lag as the seek operation is the slowest component in a hard disk access.
The separate thread concept is a good one and if you put some smarts into it like taking a request and breaking it down to a bunch of file accesses – then you can sort the accesses before loading them. If the file system is not fragmented, this would be a great speed increase. Even without a defragged drive, this can be beneficial as the O/S usually reads in blocks and/or sometimes performs a read-ahead and thus accesses grouped together on the drive can really benefit.from this action.
The problem with the segment size is that there is a break even point where too small of a segment can cause too many seek operations (depending on how you organize your data and what data it is). Too large of course will result in simply wasting time reading. The trick here is (I think) that the reading is much more faster than the seeking plus the fact that most drives cluster data naturally and thus going too small will result in another problem – the O/S reading in a whole cluster and you only use part of it. Then you are wasting time again.
It's been too long – what's the average size in bytes for a typical hard drive “cluster”? Arrange your data accordingly using the above guidelines. I'm no expert in this field – I'm also in a hurry to leave for an event.
Think about this, good luck, and may the force of GameDev.net be with you :)

This topic is closed to new replies.

Advertisement