views:

628

answers:

12

I've no games programming knowledge and have oft wondered how the levels in 2D games such as Mario and Sonic (etc) are stored.

'Stored' as in how is the data (ground, platforms, buttons, lifts, etc) stored.

I.e. obviously a level in mario is NOT some kind of very wide image which is moved from left to right.

A: 

This is too broad.

Game level storage varies WIDELY based on the engine.

MiffTheFox
+1, can really vary from 1 game to another.CAn be a Object collection, a big array for games like tetris, etc etc etc.
Clement Herreman
+1  A: 

As stored data structures.

Ask too broad a question, get too broad an answer. :)

chaos
Ah! Thanks for the clarification ;).
Dynite
A: 

Usually in some sort of custom file format that the game parses.

XML is a possibility as is plain text files. However, try opening up a level file from one of your games and you'll most likely see garbled text. You need to find documentation about the special file formats that the game uses.

Look at modding sites for your game and you will find more.

samoz
+5  A: 

Not really relevant but did you know the clouds in Mario are the same sprite as the bushes, just with the colour palette shifted? Memory really was expensive back then!

It's not really possible to know how they are stored but probably with an objects-on-a-grid approach with a few memory saving tricks here + there. Implementation is bound to vary massively from game to game and is pretty much entirely down to the developer - there isn't really any standard approach.


Update: I'd imagine representing the whole level as a (very wide) grid would be the best approach. In each grid box you'd place a sprite with properties (spawn, ground, wall, chest, baddie, spikes etc). The engine would then draw the sprite in the correct location, but also have the properties associated to it. If you put 10 floor pieces in a row you'd have to code the engine to recognise the join, and where to put the correct end piece etc. Obviously anything not a grid would be sky!

How you encode this information is pretty much up to you, and since memory isn't a huge deal anymore efficiency doesn't matter as much. Just a list of objectcode,x,y would probably do it.

Meep3D
Nice one about mario :-)
David Archer
It's a fun fact, and it's amazing how you can have played that game for literally hundreds of hours and not notice 'till someone points it out :)
Meep3D
@David I'll let you in on another secret: Mario and Luigi also use the same sprites, just palette-shifted.
Christoffer
hahahahahaha :-D
David Archer
Very Interesting :)
Dynite
A: 

In the case of the (presumably old and 2D) Mario and Sonic games you mention, probably some arcane compressed and optimized format to get around the storage and processing limitations of the consoles they were made for.

frou
+13  A: 
Martin Harris
This is the same principle as how images that are color palette based are stored, correct?
Rob
Pretty much, and the compression can be done in a very similar way to those images too. A very basic approach is just start grouping runs of numbers. That way the first line of my example format can become 8 200 and take up considerably less space.
Martin Harris
The Mario games are not as you describe, at all.
Kawa
+2  A: 

For most 2D games, I imagine the level is stored like a bitmap of tiles.

It works like this:

  • First, you have whole lot of tiles of a fixed say, let's say 16x16 pixels. These tiles are like the pieces of a jigsaw puzzle. You can fit them together in all sorts of ways to form a level. For example, here is a tileset, although this looks to be for some kind of top-down game the principles are the same: http://silveiraneto.net/wp-content/uploads/2009/04/free_tileset_version_9.png

  • Once your set of tiles is known, you give every tile a number. You can store this number in a byte if you have less than 256 tiles, or in a word or dword if you have more. It's also useful at this point to add some semantics to these numbers. Let's say for example that tiles 1-100 represent the "obstacles", which you cannot walk through. This will come in handy later.

  • Now it's time to define the map. We can simply do that by putting the jigsaw pieces on a large grid! We define a maximum size for the map. For a sidescroller, let's say the map is 1000 tiles wide and 50 tiles high. You can choose whatever you want. You can now represent the map in memory (and on disk) as a bix matrix of width * height numbers. Every "cell" in the grid contains a number that represents the tile that should be drawn at that location.

Drawing the map is easy now:

for (y = 0; y < height; y++) {
   for (x = 0; x < width; x++) {
      draw_tile(x * 16, y * 16, map[y][x]);
   }
}

As is other stuff. Remember that we defined the tiles 1-100 to be obstacles? We can use the map to detect whether it's possible for the player to move to a certain position:

bool moveable(int x, int y) {
   return map[y / 16][x / 16] > 100;
}

This is the most basic explanation of a tiled map. There are loads more fancy things you can do by extending this simple concept. Here are some ideas:

  • multiple layers, to represent objects on top of the background
  • parallax scrolling for cool background effects

I'm fairly sure that most 2D games use some variant of the tiled game map technique.

rix0rrr
+1  A: 

I have used Lua scripts to create the levels for Physle games. They are not as fast to load as a binary format but it makes it much easier to debug and integrate with other tools. Loading levels is also generally not where speed really pays off any way.

Nick
A: 

I don't know how something like Mario would store its levels and I've never done it myself, but this is how I would approach.

I'd create a simple file format that could be XML based. In that I would probably have the the playing area size defined and other meta data like name and time limit. Then I'd have a list of objects that would appear in the playing area with their x/y coordinates and the type of the object, e.g. player start position, level exit, etc....) I might even have a section that stores times for when events happen in the game.

Then the game engine would have to interpret the file and render the appropriate items on the screen when they come into view. I'd imagine storing the data is the easy bit, its what you do with it that'll be tricky.

Hope that helps.

Jon Mitchell
I would that think that XML would be too slow.
Dynite
If I was going to store it as XML I would probably serialize the 'level object' and then deserialize it from disk when I needed it. I wouldn't keep it in an XML Document and then XPath my way around it, that would be slow.
Jon Mitchell
A: 

A somewhat-related blog post from one of our esteemed leaders is Why are the Microsoft Office file formats so complicated? (And some workarounds)

AakashM
A: 

I've very often seen arrays used, with the values keyed to terrain/fill types. Here's a -great- tutorial from Tony Pa on flash tile-based game creation:

Game Map storage

Then the level creator scans through and creates the file. Look on Kongregate for games that allow user-level creation; they store a whole level that's submitted as POST variables when you link to the game. It's a transparent process that is not often encoded, so it's easy to learn from (and there are many game types that do this)

Alex Mcp
+1  A: 

All those who claim Mario games store their levels in a 2D array structure of some kind are way off: aside from the first two GB Mario games (and possible the third), the Super Mario games are object based.

Each level is split up into several screens, with the total size for each level being the same. Each screen contains a variable length list of objects, each with a type, position, and (depending on type) other properties. At the start of a level, the first screen or two is interpreted and converted to a regular 2D array structure that's used to draw the screen and do interactions. As the level scrolls past, this map is rebuilt on the fly, throwing away the parts that go out of range.

This is why enemies can respawn if you backtrack, most notably in one of the forest levels in SMW where you can use the cape to jump back and forth three screens wide from one caterpillar to another. Which incidentally, because you never touch the floor, gives a lot of lives.

The specifics of this system differ between games ofcourse.

Other than that, Martin Harris is completely right.

Kawa
On another note, the original Sonic trilogy did use a 2D array. The tiles were relatively big so a large level wouldn't take that much space. And for a game where you can move several screens far in scant seconds, large levels are a must.The subtiles, however... woah boy.
Kawa