RPG Map

From GDWiki

Jump to: navigation, search

Contents

[edit] Want to make a world for your 2D RPG? Keep reading...

Prerequisites:

  1. Knowledge of a language
  2. Ability to draw images with your language/API
  3. Desire to make an RPG
  4. Pulse

[edit] Introduction

This tutorial is intended for beginners. However you do need to be familiar with your preferred language and also must know already how to draw images, like bitmaps. Not everything is spelled out in this tutorial, such as where to place the code. This is because it's totally up to you. All you need to know is the concept. Lets begin.

[edit] The Map

If you don't know already, a map is the game world and the game world is the map. The map makes up the place your character runs around in. In this tutorial we're going to make a generic map system. You'll see that a map is nothing more than a grid, or 2D array, of tiles which will be represented like this illustration:

Image:Tiles.png


So now you understand that a tile, or square, is the building block of a map. Now we need to represent this stuff with code, starting with the building block:

TILE structure
	u : integer
	v : integer
	blocked : boolean

This User Defined Type (UDT) holds all the properties we need for each tile. However u and v do NOT represent the tile's position! It's very important to understand this; u and v represent which part of our tiles bitmap is going to be drawn for this tile. Blocked is the property of the tile that tells us whether the characters can walk over that tile or not. We've represented the tile, now lets represent the map grid with a two-dimensional array:

MapWidth = 80
MapHeight = 80
 
Map[MapWidth,MapHeight] : TILE // Declare this globally

This is our map. Each tile's X and Y position on the map corresponds to where the tile is located at inside the array Map[X,Y].

You need to know some more information before we continue. Each tile we're using in this example is 32 x 32 pixels. The resolution we're running at is 640 x 480 pixels. Again, for the sake of demonstration, we're going to use constants because it's easier to read and understand than using magic numbers.

TileWidth = 32
TileHeight = 32
 
ResolutionWidth = 640
ResolutionHeight = 480
 
x : integer
y : integer
r : RECT // Defines the area of the bitmap being drawn
 
For x = 0 to ResolutionWidth / TileWidth
	For y = 0 to ResolutionHeight / TileHeight
		r.Left = Map[x,y].u
		r.Top = Map[x,y].v
		r.Right = r.Left + TileWidth
		r.Bottom = r.Top + TileHeight
		
		Draw(x * TileWidth, y * TileHeight, r)
		//...^ X position & ^ Y position where the portion of the bitmap (r) is drawn
	Next y
Next x

Cool, isn't it? But wait a minute. We're only seeing a small region of our map, whats up with that? We'll have to 'scroll' the map (move it around) in order to explore it. We do this by using a camera or also called a point of view.

[edit] Scrolling the map

The camera system is nothing more than a point from which we begin to draw our map. It may be difficult to visualize at first, so I painted a pretty picture to show you:

Image:Camera.png


To represent the camera we use exactly what it is, a point (though technically it's a rectangle, all we need is the top left corner; a single point):

POINT structure
	x : integer
	y : integer
 
Camera : POINT

We only draw the tiles that are within the camera's view (the rectangle). Now we can draw our map based on where our camera is at. An important thing to remember is that when you draw your tiles in your game while using the camera, you must always subtract the camera's x and y values from the x and y values of the object. The reason for this is that we want to always start at (0,0), the top left of our screen. Otherwise our tiles would be drawn with an offset equal to the camera's x and y values instead of from the origin. The map should move, not the screen. Let's do it:

TileWidth = 32
TileHeight = 32
 
ResolutionWidth = 640
ResolutionHeight = 480
 
x : integer
y : integer
r : RECT
 
For x = Camera.x / TileWidth to Camera.x / TileWidth + ResolutionWidth / TileWidth
	For y = Camera.y / TileHeight to Camera.y / TileHeight + ResolutionHeight / TileHeight
		r.Left = Map[x,y].u
		r.Top = Map[x,y].v
		r.Right = r.Left + TileWidth
		r.Bottom = r.Top + TileHeight
		
		Draw(x * TileWidth - Camera.x, y * TileHeight - Camera.y, r)
	Next y
Next x

Move your camera around in realtime. Nifty huh? But wait, you might have a problem: You've copied the code above letter for letter, with exception to naming of the variables and objects. Why aren't the tile's being drawn by the edges of the screen when I move the camera? That's because DirectDraw will only display blits that are totally onscreen. Yeah, that kinda sucks. But good news, we get around this by clipping the rectangle before using it to draw with. See clipping.

If that wasn't your problem, then perhaps this is: You're escaping the bounds of your map array. Easy fix. You have to add restrictions to where your camera is allowed to be (ie keep it from trying to leave our map). This means we can't attempt to blit tiles that don't exist e.g. when the camera position's values are negative or greater than the map's dimensions, it's going to try to draw tiles that our map array doesn't even have! We apply these restrictions with a few conditionals before drawing.

If Camera.x < 0 Then Camera.x = 0
If Camera.x + ResolutionWidth > MapWidth * TileWidth Then Camera.x = MapWidth * TileWidth - ResolutionWidth
If Camera.y < 0 Then Camera.y = 0
If Camera.y + ResolutionHeight > MapHeight * TileHeight Then Camera.y = MapHeight * TileHeight - ResolutionHeight
 
// Now drawing code...

Didn't have either of those two problems? Pat yourself on the back. Have a different problem you encountered? Sucks to be you, this tutorial is finished. See the forum.

Ready for the next level? Maybe you'd like to read about saving maps to files.

Personal tools