Changing map

closed account (GbX36Up4)
Right now I'm making a 2D engine in Allegro, and it's going well so far. The only problem is I'm trying to find a good way to go from one map to another. Basically I have a map class and a tile class. The tile class holds the properties for each tile (is it a door, what does it look like, can we go through it, where is it located, etc.) while the map class tells us where the text files for the current map are. My problem is that I'm not sure how I can tell if the map has changed. Sure, I could just have an ass load of if statements or a big switch, but I want something that wont take up a whole bunch of code. Any Ideas?
No code in the game should care about which map you're in. The map and tile classes should be generic enough to handle any and all map data you want.

Transitioning from one map to another should be a simple process:

1) reposition the player
2) load the new map (replacing the old map)
3) redraw the screen.


As for figuring out when to transition maps, there are a number of ways to do this. The two common approaches are:

1) when the user steps outside of the map boundaries. For this case, each Map should have properties specifying adjoining maps on each boundary.

2) When the user steps on a specific "teleportation" tile (like stepping onto a doorway or staircase tile). For this case the Tile (or the Tileset) should have properties specifying the area the player is going to teleport to.


EDIT:

I just reread something that is questionable...

The tile class holds the properties for each tile (is it a door, what does it look like, can we go through it, where is it located, etc.)


A tile should not care about where it's loaded.

In a tile based 2D engine... the layout is usually pretty simple. The example below is set up for a top-down style retro-RPG (NES/SNES era Final Fantasy, Dragon Warrior, etc), but the concept is more or less the same for platformers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Tile
{
  bool canWalk;  // true is player can walk here, false if they can't (if it's a wall)
  bool doesTeleport;  // is this a teleportation tile?
  TeleportInfoStruct teleportInfo;  // where to teleport to
  GraphicInfo graphics;  // info on how to actually draw the tile
};

class Tileset
{
  Tile tiles[0x100];  // a clump of a bunch of tiles for this tileset
};

class Map
{
  Tileset tileset;  // the tileset this map uses
  SomeKindOf2DArray<Tile*> map;  // the actual map
};


The map file in this case would be little more than info to indicate which tileset to use, and a big array of integral values to represent the tile. When you load the map, you will take those values and use them to index the tileset array... giving you a big array of tiles.
Last edited on
closed account (GbX36Up4)
Thanks for the help. The location thing was before I read your code in another post:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
struct TileProperties
{
    bool bWall;  // true if the tile is a solid wall
    int  nGfxX;  // X coord of the graphic
    int  nGfxY;   // Y coord of the graphic
};

TileProperties myTileset[2] = {
  { true,  0, 0 },  // tile 0 = solid wall; graphics at 0,0
  { false, 32, 0 } // tile 1 = open space, graphics at 32,0
};

const int MAP_WD = 5;  // 5x5 map for simplicity
const int MAP_HT = 5;

int map[MAP_WD * MAP_HT] = {
  1,1,1,1,1,
  1,1,0,0,1,
  1,0,0,0,1,
  1,0,1,0,1,
  1,1,1,1,1
};


//================================
//  now if you want to get the properties of a tile at a specific coords:

const TileProperties& GetTile(int x, int y)
{
    return myTileset[ map[ (y*MAP_HT) + x ] ];
}

// now you can do things like:
if( GetTile(player.x, player.y).bWall )
{
  // disallow the player to move here
}

//================================
// as for drawing, it's the same idea:
int y, x;
for(y = 0; y < MAP_HT; ++y)
{
    for(x = 0; x < MAP_WD; ++x)
    {
        const TileProperties& t = GetTile(x,y);
        DrawImage( /* draw 32x32 pixels from whatever tileset image you have.  Use t.nGfxX
                 and t.nGfxY as the source coords for the image */ );
    }
}


Edit:
With your two suggestions for changing the map, I would have to use if statements, unless I'm not seeing something?
1
2
3
4
if(this_map && this_direction)
{
         newmap = thismap;
}

and then do that for all possible combinations. I'm not too good with all the "re-usability" stuff.

EditEdit: I'm retarded. Disregard the above part.
Last edited on
1
2
3
4
if(this_map && this_direction)
{
         newmap = thismap;
}


I don't think I understand what you're illustrating here.

But it's very simple. Just do something like this:

Approach 1: Going outside map boundaries

1
2
3
4
5
6
7
8
9
10
// after the player moves
if( player.x < map.left_side )
{
  LoadNewMap( map.left_neighbor );
}
else if( player.x > map.right_side )
{
  LoadNewMap( map.right_neighbor );
}
// do same for north/south 


Approach 2: Stepping on a "teleport" tile

1
2
3
4
5
6
7
// after the player moves
Tile t = map.GetTile( player.x, player.y );

if( t.IsThisATeleportTile() )
{
  LoadNewMap( t.teleport_info );
}
closed account (GbX36Up4)
Holy turd. Thanks a ton. I'm new to classes and all so thinking of ways to do all of this is hard.
Topic archived. No new replies allowed.