-=======================================-
-=== VGASteve's Programming Articles ===-
-=======================================-
- By Steve Swan -
- (C) Copyright 2000 -
- All Rights Reserved -
-----------------------------------------
Todays's topic : 2-Dimensional Coordinates
Welcome to this issue of VGASteve's Programming... In this article
I will be explaining the three main 2-D coordinate systems involved
in a side scrolling game. First, what IS a side scrolling game? A
side scrolling game is a tile-based game where the player views the
world from a side, as the world scrolls in all directions. This
means that the player can only see a fixed amount of space in front
of him.
Examples of side scrolling games include Commander Keen, Jazz Jackrabbit,
and Super Mario Brothers.
The levels for these games are stored as a grid. Each grid square
represents a tile, or bitmap of fixed size. Common sizes for these
bitmaps include 16x16 pixels and 32x32 pixels. The artwork for a
level is split into bite-sized chunks this way. One tile could be a
piece of wall, while another tile is the right side of a ledge. One
tile could be a corner of a large window, while another could be a
chunk of wall with a torch mounted on it.
Anyway, this gives the level designers the flexibility to decide where
they want to put windows, torches, walls, stairways, etc. The grid
which holds the level can have basically any dimensions you want. Each
entry in the level grid is a number which references a tile, or bitmap,
stored in an array of bitmaps. Because there are generally fewer than
256 different tiles in a good sized level, we can safely allocate a
single byte (number range of 0-255) for each grid square.
Now that we've had the overview, let's jump right in... Here are the
three types of coordinate systems used in a side scroller engine:
- Grid Coordinates
- World Coordinates
- Screen Coordinates
Each coordinate measurement has an X axis and a Y axis. To clarify these,
consider the following diagram:
0,0
+------------------------------------------------------->
| Increasing X values
|
|
|
|
|
|
| Increasing Y values
|
|
|
\|/
The origin is at the upper-left hand corner, and the X and Y values
increase as they move out. This is the coordinate system used on
computer screens.
We've already seen a glimpse of the grid coordinates. These coordinates
identify a particular square on the grid. The square in the very upper
left hand corner of the level is square (0, 0). The first number in
parentheses is the X coordinate, and the second number is the Y coordinate.
If your level is 64 grid squares across and 128 grid squares down, we say
it's size is 64x128 grid squares. The upper left hand corner is (0, 0),
and the bottom right hand corner is (63, 127). Note that we measure from
0.
World coordinates are measured in pixels. They also have their origin
at the upper-left hand of the level grid, but they can be used to specify
an exact location on any tile. The dimensions of your level in world
coordinates are determined by the dimensions in tiles and the dimensions
of your tile artwork. If you have 32 by 32 pixel artwork, and your
level is 64x64 grid squares, the dimensions in world coordinates
are (32*64, 32*64), or (2048, 2048). This means that the lower right
hand edge of the level would be (2047, 2047).
Here's an illustration of grid coordinates vs. world coordinates:
--Tiles are 16x16 pixels--
First numbers listed are grid coordinates.
Second numbers are world coordinates.
+--------+--------+--------+--------+--------+--------+--------+--------
|(0,0) | | |(3,0) | | | |
|(0,0) | | |(48,0) | | | |
| | | | | | | |
| | | | | | | |
+--------+--------+--------+--------+--------+--------+--------+--------
| | |(2,1) | |(4,1) | | |
| | |(32,16) | |(64,16) | | |
| | | | | | | |
| | | | | | | |
+--------+--------+--------+--------+--------+--------+--------+--------
| |(1,3) | | | | | |
| |(16,32) | | | | | |
| | |
|
Note that we are only looking at upper-left corners of the tiles...
World coordinates let us address ANY pixel in the level grid. To look
in the MIDDLE of tile (1, 1), we would use (16+8, 16+8), or (24, 24).
The game engine I'm currently developing, SmoothBore(R), uses world
coordinates to keep track of where the enemies are because the enemies
need to move smoothly, instead of jerking from tile to tile.
Now to move on to the last coordinate system... Screen coordinates are
measured in pixels just like world coordinates are. The difference is
that they have their origin in the upper left hand corner of the SCREEN.
When you are playing a side scroller, you will notice that the screen
is constantly scrolling, and hence the origin of the screen is constantly
changing.
To keep track of where the upper-left hand corner of the screen is, you
use World coordinates. Hence, if your screen starts at (39, 47), and you
have a Screen coordinate point (5, 8), the same point in world coordinates
is (39 + 5, 47 + 8). This suggests the formula:
worldX = screenStartX + screenX;
worldY = screenStartY + screenY;
Also, to find the screen coordinate form of a given world coordinate:
screenX = worldX - screenStartX;
screenY = worldY - screenStartY;
You can gather from the above that it is VERY important to keep track
of the origin of the screen (screenStartX, screenStartY) in world
coordinates. This is, in fact, how scrolling is achieved; by moving
these variables.
How useful are screen coordinates??? VERY useful. You have to translate
enemy positions (in world coordinates) into screen coordinates in order
to know where to draw them on the screen, or, indeed, IF you should
bother drawing them at all... For instance, let's say you have an sprite
(another name for an enemy) who's position in world coordinates is
(50, 80), and your screen origin is at (256, 430).
+----------------------------------------------------------------------->
| (50, 80)
| ++ Sprite
| ++
|
|
|
|
|
| (256, 430)
| +---------------+
| | Screen |
| | |
| | |
| | |
| +---------------+
|
It's fairly obvious at a glance that the sprite shouldn't be drawn to the
screen. But how does your code know this??? Let's translate to screen
coordinates:
screenX = worldX - screenStartX;
screenY = worldY - screenStartY;
screenX = 50 - 256
screenY = 80 - 430
screenX = -206
screenY = -350
If your sprite is 32x32 pixels, then you wouldn't bother drawing him
unless the his screen coordinate position was greater than (-32, -32).
With a quick compare, the code above can rule him out of the picture...
In summary, here's a table with the three different coordinate types:
Coordinate: Unit: Origin:
--------------------------------------------------------------------
Grid Coordinates Grid Squares U.L. Corner of level
World Coordinates Pixels U.L. Corner of level
Screen Coordinates Pixels U.L. Corner of screen
--------------------------------------------------------------------
And here are some equations:
worldX = gridX * tileSizeX // Grid to World
worldY = gridY * tileSizeY
gridX = worldX / tileSizeX // World to Grid
gridY = worldY / tileSizeY
screenX = worldX - screenStartX // World to Screen
screenY = worldY - screenStartY
worldX = screenX + screenStartX // Screen to World
worldY = screenY + screenStartY
screenX = (gridX * tileSizeX) - screenStartX // Grid to Screen
screenY = (gridY * tileSizeY) - screenStartY
gridX = (screenX + screenStartX) / tileSizeX // Screen to Grid
gridY = (screenY + screenStartY) / tileSizeY
That's All!
Next Time : Hit Detection!
E-Mail : VGASteve@yahoo.com
|