Making a map for a 2D game.

Started by
11 comments, last by farmdve 10 years, 7 months ago

So I decided to once again dabble in game development and again do 2D for experience. Last time I used SDL 1.2 and sprites(BlitSurface), this time I will use SDL 2.0,Chipmunk-Physics and again some 2D sprites.

Before I used a tile-based map, however truth be told I only copied the code from an SDL example rather than try to understand, this time I want to try.

At first I wanted to do the same type of map again, where you can walk up,down,left and right, but maybe I should do one like Super Mario Bros from 84 for the SNES where you can only jump and go left OR right.

Here's how it looked/s

Super-Mario-Bros.jpg

You can see that the character is walking on stone BUT above him there are objects he can interact with(in this game's case, usually smashing those bricks or bumping the question marks if he hits them from below, or walk on those objects) and there are objects behind the character such as bushes or trees and even clouds above which do not collide with the character.

But what kind of map is that, and how can I replicate the results(I do not want to make a clone, just something that utilizes this concept). Because I have no idea how one would describe that map. Funny, the game was made in 1984, and nearly 30 years later I still have no idea how it's done.

And while I have not forgotten, on a tile-based map how can one place objects on the tiles themselves? For my old game test(which was just random junk) I read the map from a file being just numbers that represented a different sprite but one couldn't describe an object on those tiles.

And perhaps last, but probably not least. Using OpenGL or the Graphics API in SDL 2.0 for the sprites/drawing? Because I feel like I am not yet ready for GL.

Any help would be appreciated.

Advertisement

I read the map from a file being just numbers that represented a different sprite but one couldn't describe an object on those tiles.

One way to do this: instead of using the numbers to refer to images, use it to refer to an object description. Don't think of tiles as something that is not an object. Just think of tiles as objects whose positions are snapped to a grid. That means the ground brick is an object, the question brick is an object, and so on.

For example, I can have a map description file like this (ini-like format):


[level 1]
tiles =
A
A
A  B
AAAA
 
A = "brick"
B = "player"

In this example, the value of "tiles" describes the placement of objects in the map. The symbols 'A' and 'B' are tiles, and they point to an object description, not an image file. When loading the map, just read in the symbols of "tiles" and see what object each of those symbols refer to, and use the refered object description to load in the object, and set the object's position according to some loop state variables you keep.

If you want to know how NES games work... they have background sprites for some things and "normal" sprites for the rest. Every frame, for every pixel the background color is computed first and then all the sprites are checked to see if anything is over the background at that one pixel. If there's a non-transparent pixel of a sprite over the background, the sprite pixel is drawn in that place.

For collision detection, there's also a mechanism that's commonly used called "sprite zero hit": http://wiki.nesdev.com/w/index.php/PPU_OAM

Based on the first paragraph, maybe you should use 2 tile maps, one for the background and one for the objects that will interact between them.

OK, so there are like 5 connected but separate parts to this:

1. A logical data structure to hold / represent such a map in the computer.

2. A file format or other structure to save these maps to and load them from.

3. The code that does the saving and loading.

4. The code that interacts with the loaded map object(s) to make the display happen.

5. The code that interacts with the loaded map object(s) to make the "game" logic happen.

Most of the time when people are asking "how do I make a map" they primarily mean #1, which is what we focus on when deciding on a design. 2 and 3 are just natural consequences of #1, so nothing special there. And 4 and 5 depend completely on whatever game engine or environment you want to use.

So the data structure - there are hundreds of ways to store these things, and no right way. Usually in the OLD days, people stored them in the SMALLEST way possible that had only the ability to support EXACTLY what was needed. So for instance an SMB screen is about 14 blocks high, and 16 blocks wide, and most maps are purely horizontal ... so they probably stored the map as a 2D array of integers - where each integer represented what was "in" the block. something like:

#define BLOCK_HEIGHT 32
#define BLOCK_WIDTH 32
#define MAX_VERTICAL_BLOCKS 16
#define MAX_HORIZONTAL_BLOCKS 256
int blockArray[MAX_HORIZONTAL_BLOCKS][MAX_VERTICAL_BLOCKS];
int currentScreenPosition = 0; // defined what "pixel" on the map is the leftmost pixel displayed on the screen
 
//and then some big switch statement probably controlled the "rendering"

Now, with modern C++ / OO techniques we would probably make a couple of classes to do this (minimum). Here's quick and dirty pseudo-code rough draft:

enum BlockType
{
  Empty = 0,
  SolidBlock = 1,
  BreakableBlock = 2,
  QuestionBlock = 3,
  EmptyQuestionBlock = 4
  // these are not NEARLY enough, I'm just trying to show the general idea
  // most likely the "int" for the enum values would be a bit pattern where certain bits would control "is empty", "is solid", "is interactive", etc that affect the physics / game logic, while others would control the visual variations that only affect the screen (Note that the background images (clouds / grass, etc) are stored in a SEPARATE overlap layer, from the primary "map" elements.
};
 
typedef std::vector<BlockType> BlockList;
typedef std::vector<BlockList> BlockMatrix;
 
class Map
{
  BlockMatrix blocks;
 
  // add helpful functions as needed, such as:
  BlockMatrix GetScreen(int xBlockCoord, int numBlocks);
  BlockList GetSlice(int xBlockCoord);
 
  // or connect the map to something like a "SpriteManager" and give it functions to:
  Sprite GetBlockSprite(int xCoord, int yCoord);
  void DrawScreen(Display display, int leftmostPixel); // note you'd want to divide pixel by BlockWidth to find out what block it is in
};

Sorry I'm out of time today, so I can't really show you the whole picture, but I hope this gives you a little bit of a start.

Check out Tiled if you haven't already. It's a great tiled map editor.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

So I decided to once again dabble in game development and again do 2D for experience. Last time I used SDL 1.2 and sprites(BlitSurface), this time I will use SDL 2.0,Chipmunk-Physics and again some 2D sprites.

First off I'd like to question your use of a physics library in a platformer. I think there's a bit of a misconception from people about needing to use a physics library in a game with motion.

Thing is a physics library is often designed for things like rigid body physics, complex interactions and movements that often are a lot harder to process than simple movements. A good candidate for when you might use a library like that is if you want actual physics objects, like being able to run into a box and it tumble. You would not use it for something like mario, the code will if anything be much slower and needlessly complex, especially when you're doing things like impulses for movement instead of just adjusting velocity.

You can see that the character is walking on stone BUT above him there are objects he can interact with(in this game's case, usually smashing those bricks or bumping the question marks if he hits them from below, or walk on those objects) and there are objects behind the character such as bushes or trees and even clouds above which do not collide with the character.

But what kind of map is that, and how can I replicate the results(I do not want to make a clone, just something that utilizes this concept). Because I have no idea how one would describe that map. Funny, the game was made in 1984, and nearly 30 years later I still have no idea how it's done.


I'll go into a little lesson just to illustrate the process of thinking over just taking a ready made solution.

The easiest way to think about how to deal with stuff like this is to seperate it mentally into two seperate "planes of existance" in memory, and on disc. In memory you may have something like a grid where "tiles" are placed, objects like boxes and things in a mario game may count as a special tile or perhaps a seperate entity, things like enemies would of course be seperate from a tile.

Now that you have that in your head, think about the information you need to save from that. Well you certainly don't need to save the enemies with the tiles, if you needed to save them at all you could save their positions as seperate information, what you end up with is the fact that you need to save the positions of each tile and then simply place that back into memory when loading the level.

So how could you do that? Well the easiest way would be to split the map into a grid and simply save -every- tile, but thats a little wasteful, especially on a game like mario where most of the "blocks" will be sky and the rest will be sparsely placed areas above the ground. So maybe you could do something like only save each block that isn't just air and its position, that would probably at least half the information needed to actually have the level ready in memory.

So of course now you have your data, you can save it and load it. One thing a game may choose to do is since we have that information as just a bunch of bytes now, you could theoretically use some kind of algorithm to compress the data together(merging sets of numbers into a single number then reverting it to normal form when you load the level.) A bit of an advanced topic but it of course gives an insight into how you might -approach- things like this.

And while I have not forgotten, on a tile-based map how can one place objects on the tiles themselves? For my old game test(which was just random junk) I read the map from a file being just numbers that represented a different sprite but one couldn't describe an object on those tiles.

As I pointed out that usually depends on your game and how you seperate objects and enemies. In a 3d game for example the terrain is often saved and treated in a vastly different way from a moving object like an enemy or physics object, it's often saved seperately so that a map file might contain just the static geometry of the level and all the entity data, trigger data, map flags and such all squashed together into a compressed file.

For instance in a mario game how would you treat the moving platforms that follow rails like in super mario world? Logically you probably would save them as entities instead of a map tile or something because they have complex motion behavior. But on the other hand if you have something that animates but may be treated in code as a tile you may just save it as one. It's all about the game and your perspective.

And perhaps last, but probably not least. Using OpenGL or the Graphics API in SDL 2.0 for the sprites/drawing? Because I feel like I am not yet ready for GL.

If you aren't ready for straight opengl, don't use it. Quite frankly the only time I would suggest venturing into opengl is either when you become curious about it or you really hit a point in developing a game where you -need- that extra performance. Don't learn things just to learn things, if they're important you'll learn about them when the time comes and get -way- more out of them!

Also yes, tiled is a good suggestion for a tool, you can adapt it to save data in a way you need it to, and set your game up to load it.


First off I'd like to question your use of a physics library in a platformer. I think there's a bit of a misconception from people about needing to use a physics library in a game with motion.

Thing is a physics library is often designed for things like rigid body physics, complex interactions and movements that often are a lot harder to process than simple movements. A good candidate for when you might use a library like that is if you want actual physics objects, like being able to run into a box and it tumble. You would not use it for something like mario, the code will if anything be much slower and needlessly complex, especially when you're doing things like impulses for movement instead of just adjusting velocity.

I totally disagree. Have you used a 2d physics library? If you have, you;d realize how much simpler it makes everything related to movement and collision. Sure, it can also do some rgeat things with axis, ropes, springs, lines, etc. But, when it comes to movement an collision, IMO, physics library is a easy solution, and the developer no longer needs to worry about collision handling (detection and response) nor movement, outside of providing a force or velocity.

I whole believe using a physics library is a GOOD thing for a platformer; it will decrease development time hugely, and you can do some really fun things with it too with little effort.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

I totally disagree. Have you used a 2d physics library?

Yes. Honestly that's turning into a pet peeve of mine that the first thing people do is question if I've used something or if I'm just stupid, it's like every OS fanboy out there. "Have you even used it?" might as well be going "Do you even lift bro?"

Yes I've used a physics library, I'm not trying to be cute.

If you have, you;d realize how much simpler it makes everything related to movement and collision.

I would not call having to set up the basic physics system from the library, attach rigid bodies to objects and then set everything up so it behaves the way you want to be as "simple" as you put it. Using something like box2d in a mario game is almost a joke to the point where you're getting ridiculous physics collision and physical forces for behavior that doesn't require even a fraction of that complexity. You end up having to lock the physics objects to stay vertical and basically act like dumb boxes anyway, so in reality you're more or less using the physics to overcomplicate a simple task for no real gain.

Sure, it can also do some rgeat things with axis, ropes, springs, lines, etc. But, when it comes to movement an collision, IMO, physics library is a easy solution, and the developer no longer needs to worry about collision handling (detection and response) nor movement, outside of providing a force or velocity.

I definitely would not call it easier, I could set up simple collision in a few moments whereas setting up a library takes quite a bit more time to make the game react the way you wish it to. On top of that in a game like a platformer you have to deal with things like handling terrain collision and other fun things. Is it more accurate? Well yes, it tends to be because it is a full on physics library and has a lot of fancy internal code and math to deal with time of impact and response.

I whole believe using a physics library is a GOOD thing for a platformer; it will decrease development time hugely, and you can do some really fun things with it too with little effort.

I think it depends on the situation, it is a waste of time to do something excessive just for the fact of having it there. If you -need- complex physics in your game, sure, go for it.


I definitely would not call it easier, I could set up simple collision in a few moments whereas setting up a library takes quite a bit more time to make the game react the way you wish it to.

In the time you could set up a "simple" collision system (don't forget handling movement as well), I will have set up one that handles ALL cases, and I'd be able to point out all the limitations you have in your collision system.

We will agree to disagree then. I will continue to tout the use of 2d physics libraries, even for simple platformers. I didn't find them at all complex in setting them up.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

In the time you could set up a "simple" collision system (don't forget handling movement as well), I will have set up one that handles ALL cases, and I'd be able to point out all the limitations you have in your collision system.

It boggles my mind that you make it sound like in five minutes you can throw together some code and bam, you have monkeys swinging from rope vines and rolling down hills, when in reality we all know that isn't true.

You still have to set up movement, you still have to map input to impulses or changes in velocity, thats really not any different from rolling your own simple physics, you also will not get intended behavior by just throwing objects into the game, thats precisely -why- the physics bodies have so many features and setting and you can lock their rotations and other details. Oh.. and you have to do that for -every- object, just like with a simple physics system.

I really don't see how it is any different, but hey whatever.

This topic is closed to new replies.

Advertisement