• Advertisement
Sign in to follow this  

Large-scale 2D city - good design approaches?

This topic is 4553 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi! I'm in the process of designing a game which I hope is going to be a sci-fi 2D stealth action title where the main character will be able to move around the world in a similar way to spiderman in the Xbox game (Spiderman 2), but in only 2 dimensions of course (side-scroller like view).. I'm planning on building a VERY large city but to do so would require areas with dimensions that span into the 10s of 1000s of pixels.. So i'm wondering.. Considering I plan on using DirectX 8.1 (or higher) for the required performance of a 2D game of the kind of scale i'm hoping for, what would be the best approach of designing an engine suitable of coping with such a huge 2D worldspace, running at a reasonable framerate AND allowing the player/avatar to move around the map in a seamless fashion (similar to the kind of seamlessness we see in games like GTA for example)..? I have alot of (artistic) ideas that should allow me to create the volume of artwork/2D content necessary to accomodate such a vast environment which include re-usability and a simplified artistic style so thats not a problem.. My real concern is figuring out how best to design an engine capable of giving me the kind of performance I would need for this kind of game..? Any ideas would be most appreciated..

Share this post


Link to post
Share on other sites
Advertisement
I would try breaking the world down into tiles, and only rendering the tiles which are visible to the camera at the moment. In a 2D game, that's not very hard to do. The bigger problem that I've run into when I've tried anything with huge worlds is memory consumption. Your tiles need to be small enough that you can create small alleys, etc, but yet large enough that you don't need 10's of billions of them. ~4.5 billion would be the max for a game, IMHO, otherwise your indexes and counters would have to be 64 bit, which is a fairly large performance hit. Also, you may (or may not) want to implement your own method for pulling map data off the disk as the player moves around. Having the entire city in memory at one time isn't feasible, and I wouldn't want to rely on the OS swapping.

Good luck. I'd love to see your game when it's done. I have a special place in my heart for 2D stuff.

Share this post


Link to post
Share on other sites
Well....

Some form of dynamic loading? Surley you could open up a file, and read from it when you need, aka as your scrolling around the world, load the bits you need. Like instead of loading it all into memory at once, load it up as you need it.

Not sure how this would be achieved though, but you can always try it :)

Gu'luck :)

Cyas.

Share this post


Link to post
Share on other sites
Asheh's suggestion is part of what I was trying to say earlier, but couldn't fit into words.

It actually isn't very hard, on a conceptual level. The width and height of the map are known, and the size of tile structures on disk is known, so it'd be simple to calculate the offset into your data file of any given tile. The steps I would use are:

1) Calculate the tile the player is on

2) Calculate which tiles are in view

3) Allocate room in memory for the tiles which are in view (freeing the memory allocated on the cycle before this one)

4) Calculate the offsets into the file of the tiles in view

5) Load the tiles

6) Render

A note about #3 is that if your camera height and field of view are constrained to a certain range (say, 100 meters above the ground and 80 degree FoV), then it would be easy to figure out the maximum number of tiles that can be in view at any given time, and allocate enough room at program initialization, rather than allocating/freeing every frame. I would STRONGLY suggest doing this, as it should provide a fairly large speedup.

There are also a few optimizations, such as only fetching (from disk) the tiles that have just come into view, and just shuffling the ones that were already in view into their new locations.

On a conceptual level, it's pretty simple, and should work fairly well... How it works once you really start coding it... I dunno.

Share this post


Link to post
Share on other sites
Well all that loading of the tiles from disk is very time consuming. You'd need a really small form of map files and some quick loading procedures.

How big exactly is this world going to be and how many different tiles will you have along with sprites?

You could divide the world up into smaller sets of tiles. The tile images would be loaded into memory upon startup. And your array for the map section loaded would be just a quick number pointing to your table of tile images. For instance,

1 Grass.png
2 Road.png
3 Sidewalk.png
4 tree.png
5 car.png
6 dog.png
7 cat.png
8 beerbottle.png

you might want to consider compressing the map array so instead of allocating 16bits for every integer you would only use 3bits in this case since there are only 8 different tile types. You could make yourself a bit stream instead of using an array. It doesn't seem like much but when you have thousands of tiles that have no pattern of values it will come in handy.

The sections of tiles you divide your world up into has to do with how much memory you actually use and how well it performs. So if your holding 65025 tiles in memory or a map thats only about 255x255 and your game runs pretty quick then you could risk loading a larger amount of memory. But say your character gets closer to the edge of the region in memory you could open another thread that will start loading the region he's closest to into memory. I dunno if any of this will help or if I'm just confusing you.

Share this post


Link to post
Share on other sites
sure you could do that. But it'd limit you to 8 types of tiles, and it'd be perfectly flat. No hills, no curbs. No nothing. I wouldn't play that. And the penalty for reading off the disk isn't as much as you'd think. You're only reading when new tiles come into view (assuming you optimize it that way). That's not a very large problem.

Share this post


Link to post
Share on other sites
Well, that was just an example of course you wouldn't limit yourself to only 8 tile types. But to not waste that much space on storing numbers as just one means of compressing the data and reading from disk is not as expensive and operation as it once was but it still can eat up some time so if you find that you need to optimize that those operations compressing your data in memory and loading the map file by sectors would certain do that.

Another option that would be quiet involved would be to time how long it takes to do the reading from disk of a bunch of tiles and then scale how many tiles are loaded in memory by both the available memory and how much processor time you take up while loading.

Share this post


Link to post
Share on other sites
ehh... that's getting a bit elaborate, imho. It's not like a 2D game is going to have mega-problems with FPS anyways.

Share this post


Link to post
Share on other sites
Yeah, you'll definitely have to use tiles, and I would definitely consider zoning the map off into demand-loadable sections. 4.5 Billion tiles is WAY too much, considering most people have around 512 megabytes of ram installed. At 4.5 billion tiles, even if you only had two tile types, thus enabling you sqeeze eight map cells into one byte, you'd still consume about 90Mb. Of course having only two tile types would make an awefully dull game. Bare minimum would be 256 tiles I think, which would mean your map would consume 4.5 billion bytes of memory. You could reduce this with some sort of compression algorithm, such as RLE. Even then it's highly unlikely that you'd keep the size down to something manageable.

Share this post


Link to post
Share on other sites
Thanx for the replies people!

Well I was thinking I would need quite a few different tiles in order to give me enough variety to make the cityscape look.. well.. "pretty"..

Also I was considering spliting the entire city into districts and then having each district occupy a large area.. That way the player could seamlessly move around a single district (which would have assets made up of a reasonable number of different/unique tile in the tileset, re-used of course..) and then moving from one district to the next would require some kind of load sequence..

An example would be the player gets on a train and the train moves along the area until it gets to the load sequence.. Here the train is just moving along a repeated track (made up of a reasonably small tileset) but whilst this is happening the data for the next area could be being loaded from the disc in the background..

What do you guys think? good/bad idea? and how implementable would it be considering i'm working solo on this project (at the moment)..?

Share this post


Link to post
Share on other sites
Don't use individual pictures for each tile, use a tileset instead and use a bit of math to get the position it works better.

Also you could have different tilesets (IE a spring and winter tileset)... So if you change enviroments completely you could simply switch the tileset you load (That should cut down on the amount of overall different tiles IMHO).


Additionally you need to take into account layers (Background, Foreground, Game objects). When I have done this in the past, I use every other byte and tile=(curbyte*numlayer+curlayer)... The drawing engine should draw the background then the other layers all the way to the top most layer. (So basically you take into account layering ;)).

BTW from experience I can tell you that scrolling is kind of hard lol.

That is all I can think of right now....

Share this post


Link to post
Share on other sites
Quote:
Original post by shadowisadog
Don't use individual pictures for each tile, use a tileset instead and use a bit of math to get the position it works better.

Also you could have different tilesets (IE a spring and winter tileset)... So if you change enviroments completely you could simply switch the tileset you load (That should cut down on the amount of overall different tiles IMHO).


Additionally you need to take into account layers (Background, Foreground, Game objects). When I have done this in the past, I use every other byte and tile=(curbyte*numlayer+curlayer)... The drawing engine should draw the background then the other layers all the way to the top most layer. (So basically you take into account layering ;)).

BTW from experience I can tell you that scrolling is kind of hard lol.

That is all I can think of right now....


Thnx for the tips!

I've played around with scrolling a little in the past and so I kinda know what to expect in that department..

Your idea of layering was also what I had in mind so thnx also for that!

lastly I was just wondering how long it would take around about to get a reasonable working demo up and running provided I was implementing everything detailed in this thread so far, oh and assuming all the artwork for the engine was done of course (placeholder artwork at least..)..?

I was thinking, or hoping, to get a working demo up and running in around 2 months-ish.. Do you think thats a realistic expectation or am I in for a much longer graft?

I'm asking because I wanna try and scale the project to make it finishable and also give me enough time to fully document everything aswell (its for my portfolio)...

Share this post


Link to post
Share on other sites
Well in two months you should get SOMETHING working... If it is what you want or not, that is a different story.

Chances are you will write it all out and end up forgetting to add something or realize you need to add scripting to make it easier on yourself.... (I recommend lua but I have just learned of AngelScript and it seems quite promissing as I like OOP).

Well I guess whether or not you will get it done , depends on how much you work on it ;).

BTW to get the tile position from your tilemap I would use:

TileX=(TileVal%TileAcross)*TileWidth;
TileY=Floor(TileVal/TileAcross)*TileHeight;

If you ignore the *TileWidth or *TileHeight you will get when TileVal=0 and the TileAcross=4 then CellX=0 CellY=0 and when TileVal=3 you will get 3,0. However when TileVal=4 you will get 0,1 and TileVal=5 you get 1,1.

Multiply by the width and height of the tile and you get the position in the image ;).

Share this post


Link to post
Share on other sites
Well, are you really expecting to create a map with 4.5 billion tiles all by hand? :P Really, making a whole district is hard enough with a basic level editor. Of course it depends on the size of the tiles, but if they're too big the map won't be interesting anyway.

Let me give you a bit of perspective: ever played Starcraft? Remember the biggest map available? It was a pain in the ass to traverse it from one side to the other. It was enough to accomodate 8 player bases, all of their expansions, and still have a LOT of empty space.

This map was 256x256 tiles, each tile was 32x32 pixels and that was about the size of a human in this game. Assuming each tile takes one byte, with just 1mb of memory, which is pretty acceptable, your map is 1000x1000 tiles!! That's equivalent to 16 of the biggest maps ever in Starcraft! It's more than you'll ever need.

Of course, this abundance of resources wasn't true back in the good ol' days, when making 2D RPGs and rogue-likes was still an art. So there were all sorts of techniques to account for this.
A very simple one is to break up the world map in reasonable areas, where the player will spend a while, like districts. When loading an area, store how much time it took in a variable for later reference. The basic idea is that, given the player's velocity and an estimate of how much time it takes to load an area, you can easily calculate the distance from the edge when you should start loading the next area (distance = velocity * time). This loading happens in the background, and seamlessly with the rest of the game (for example, in a seperate thread as suggested). This is of course an estimate, and you should throw in a margin of error. By the time the player gets to the edge, no matter how slow or fast his computer is, the next area is neatly loaded and ready to go!

Share this post


Link to post
Share on other sites
Quote:
Original post by Jotaf
Well, are you really expecting to create a map with 4.5 billion tiles all by hand? :P Really, making a whole district is hard enough with a basic level editor. Of course it depends on the size of the tiles, but if they're too big the map won't be interesting anyway.

Let me give you a bit of perspective: ever played Starcraft? Remember the biggest map available? It was a pain in the ass to traverse it from one side to the other. It was enough to accomodate 8 player bases, all of their expansions, and still have a LOT of empty space.

This map was 256x256 tiles, each tile was 32x32 pixels and that was about the size of a human in this game. Assuming each tile takes one byte, with just 1mb of memory, which is pretty acceptable, your map is 1000x1000 tiles!! That's equivalent to 16 of the biggest maps ever in Starcraft! It's more than you'll ever need.

Of course, this abundance of resources wasn't true back in the good ol' days, when making 2D RPGs and rogue-likes was still an art. So there were all sorts of techniques to account for this.
A very simple one is to break up the world map in reasonable areas, where the player will spend a while, like districts. When loading an area, store how much time it took in a variable for later reference. The basic idea is that, given the player's velocity and an estimate of how much time it takes to load an area, you can easily calculate the distance from the edge when you should start loading the next area (distance = velocity * time). This loading happens in the background, and seamlessly with the rest of the game (for example, in a seperate thread as suggested). This is of course an estimate, and you should throw in a margin of error. By the time the player gets to the edge, no matter how slow or fast his computer is, the next area is neatly loaded and ready to go!


Thanx for the pointers!

However i'd just like to clarify that it wasn't actually myself who suggested having 4.5 billion tiles..

I like your ideas for calculating the time taken to load an area with respect to the velocity of the character in motion.. I was wondering though.. Since i'm planning on building the game for directX 8.0 (or higher) hardware, do you think that the added hardware acceleration will give me enough speed to allow the/some avatars to move rather swiftly around an area (when I say swiftly I mean "Devil May Cry" kind of swift..)..?

Share this post


Link to post
Share on other sites
Quote:
Original post by ArchangelMorph
Thanx for the pointers!

However i'd just like to clarify that it wasn't actually myself who suggested having 4.5 billion tiles..

I like your ideas for calculating the time taken to load an area with respect to the velocity of the character in motion.. I was wondering though.. Since i'm planning on building the game for directX 8.0 (or higher) hardware, do you think that the added hardware acceleration will give me enough speed to allow the/some avatars to move rather swiftly around an area (when I say swiftly I mean "Devil May Cry" kind of swift..)..?


I'm sorry if it sounded like I was saying that the suggestion about 4.5 billion tiles is dumb :)
Actually, it is (LOL) but you know that it's waaay too easy to go unrealistic with these things! Throwing a number in this regard is always a fuzzy matter. I hope my Starcraft example gave you some perspective.

If you're planning on using this technique, there is a point when the player can move faster than the time it takes the game to load a new map. This would happen on slower computers, or if the size of each area wasn't set within reasonable parameters. Usually the faster the player, the bigger the areas have to be. It's fairly obvious that you shouldn't let the player enter an area that didn't have enough time to load!

However, I hope my exameple gave you some insight. Implementing a dynamic system like this, however simple it was for me to explain, is NOT easy! It's highly educational so if you're interested, be my guest ;) But as I said, your PC has more than enough resources for your game to work perfectly without this system.

Share this post


Link to post
Share on other sites
Quote:
Original post by Jotaf
Quote:
Original post by ArchangelMorph
Thanx for the pointers!

However i'd just like to clarify that it wasn't actually myself who suggested having 4.5 billion tiles..

I like your ideas for calculating the time taken to load an area with respect to the velocity of the character in motion.. I was wondering though.. Since i'm planning on building the game for directX 8.0 (or higher) hardware, do you think that the added hardware acceleration will give me enough speed to allow the/some avatars to move rather swiftly around an area (when I say swiftly I mean "Devil May Cry" kind of swift..)..?


I'm sorry if it sounded like I was saying that the suggestion about 4.5 billion tiles is dumb :)
Actually, it is (LOL) but you know that it's waaay too easy to go unrealistic with these things! Throwing a number in this regard is always a fuzzy matter. I hope my Starcraft example gave you some perspective.

If you're planning on using this technique, there is a point when the player can move faster than the time it takes the game to load a new map. This would happen on slower computers, or if the size of each area wasn't set within reasonable parameters. Usually the faster the player, the bigger the areas have to be. It's fairly obvious that you shouldn't let the player enter an area that didn't have enough time to load!

However, I hope my exameple gave you some insight. Implementing a dynamic system like this, however simple it was for me to explain, is NOT easy! It's highly educational so if you're interested, be my guest ;) But as I said, your PC has more than enough resources for your game to work perfectly without this system.


Thanx for the forwarning!

I kinda guessed it wouldn't be a piece of cake but at least it'll put my degree knowledge of software engineering and my very "unpractised" maths skills to the test..

Thanx again everyone and if you have anymore tips and pointers for me then please don't hesitate to drop 'em down..

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement