ATTENTION READERS! Lucky's VB Gaming Site is no longer active. For updated game programming information and tutorials, please visit The Game Programming Wiki!
A brief description
of tile based algorithms - By Gary Beebe
This tutorial is here to help you make your own Tile Based game using
some simple Algorithms. This tutorial show you both aspects of making
an editor and where to display the tile. There are many styles of
games that could come from these algorithms such as side views and top
views. Some parts of this tutorial may be easier to understand.
I will do my best to give you the most flexible code so that you may change
it to suite your needs.
Basic declarations
These are some of the declarations that you may need to get started.
In some cases you may want to keep some of these declarations Private
instead of Public.
Public Const Xoff = 6
Public Const Yoff = 6
Public Const TileHeight = 16
Public Const TileWidth = 16
The picture above shows you why you may need the Xoff
and Yoff variables. You may have a space
between where the top and left of the map start and the actual top and
left of the area that the map is in. The thick black line may be
the border of the maps container (ex: Picture1) and the cyan tiles
are your actual map. The width and height of your tiles are held
as TileWidth and TileHeight.
You may need to change these to equal the width and height of your tiles
in your set.
Understanding your tile sets
Tile set forms may be different from programmer to programmer.
They may also be different from each game made by the same programmer.
Most often, the tiles in a set will appear side by side and in multiple
rows separated only by one row or column of pixels.
The picture above shows what I mean. The tiles are arranged side
by side separated by a column of pixels and are in rows separated by a
row of pixels. Finding the exact Top and Left of a tile can be easy
if you know the X and Y (row, column) of that tile or, if need be, a single
number representing.
Single and X, Y number tile sets
Suppose, in our tile set, that the first tile is #1 and the second tile
is #2 that would make the tile under #1 (the black one) be #5 and the last
tile #16. These are called single number tile sets. Note:
This is based on a tile set that has 4 columns only. To be able to
use our single number tile set we must first convert it over to an X, Y
tile.
An X, Y tile set is one which gives you the number of the tile using
it's X and Y position. For example, the first tile in our tile set
is (1, 1), the second is (2, 1), the one under the first one (the black
one) is (1, 2) and the last one is (4, 4).
Using an X, Y tile set is easier to work with at design and run times.
Because your tile sets may change in size you would have to rewrite a part
of your code to compensate for a change in columns, using a single number
tile set. By using an X, Y tile set you may only have to let the
program know the maximum of rows and columns in the set.
Converting from single to X,
Y
Even though I don't approve of using single numbered tile sets, I will
show you how to work with them since I mentioned them above.
To convert from single to X, Y you first must have a constant holding
the number of columns that you have in your tile set. I recommend
using a constant because using an actual number every time you do this
may make it difficult to find and change if the time ever comes that you
have resized the set. A constant, on the other hand, can be easy
to locate and you'd only have to change it's value.
Again I am using a Public instead of Private
declaration. Also I am using the number 4. This is the same
number of columns that I have in the example above, you will need to change
this to the number of columns in your set. Also, for future purposes,
we will make a variable type called XYTile
containing the X
and Y value.
These should be put in a Module.
Public Const MaxCol = 4
Type XYTileA
X As Integer
Y As Integer
End Type
Public XYTile As XYTileA
To do this easily you may want to make a sub.
This will reduce the lines of code that you will have..
Public Function GetXandY (SingleNumber as Integer)
As XYTileA
Let GetXandY.X = SingleNumber Mod
MaxCol
Let GetXandY.Y = Fix(SingleNumber
/ MaxCol) + 1
End Function
This is very simple math once you think about
it. To get the Y
you divide the single tile number (SingleNumber)
by the maximum number of columns (MaxCol). We use Fix because we
don't want a remainder for the Y and we use + 1 because it considers the
first column to be 0 (zero). To get the X
just simply get the remainder of the same product. Using
Mod will give
us only the remainder and nothing else.
To use this code just follow the examples below:
Let XYTile = GetXandY (SingleNumber)
Given the single number of the tile XYTile.X
and XYTile.Y
will become the row and column location of the single number.
With that out of the way, let get down to business...
Finding the top left of a tile
in a set
Finding the top and left corner of a tile in a tile set is almost easier
than finding the X, Y of a single numbered tile. In fact, it's quite
similar, but very opposite :). Remember the TileWidth
and TileHeight declarations (in Basic declarations)?
This is one place they will come in use. Also, to do this, we may
need a another to work with. This should be put in a Module as well.
Note: I am recycling the XYTileA Type in the Converting
from single to X, Y section above.
Public CurrentTileInSet as XYTileA
I will stick with the tile set I have above in this code. They
are 16x16. We will also use a Function to save us some lines of code.
Public Function GetTopLeftOf (X As Integer, Y
As Integer) As XYTileA
Let GetTopLeftOf.Top = X * (TileWidth
+ 1) - TileWidth
Let GetTopLeftOf.Left = Y * (TileHeight
+ 1) - TileHeight
End Function
We add 1 to TileWidth and TileHeight
to compensate for the one pixel dividers. We then multiply X
or Y by TileWidth
or TileHeight. Because this will be
(1, 1) too many, we subtract TileWidth and
TileHeight from the answers. So, once
you have the row and column (X and Y)
of the tile, pass it to the function and it will return the Top
and Left corner of the tile. Here is
an example of how to use it.
Let CurrentTileInSet = GetTopLeftOf(X, Y)
This will let CurrentTileInSet.Top and CurrentTileInSet.Left
equal the right pixel of the Top, Left corner of the X,
Y tile.
And for you single number set users who are following closely along...
Let CurrentTileInSet = GetTopLeftOf(XYTile.X,
XYTile.Y)
You clicked where?
Suppose, in your editor, you have all of your tile set displayed.
It may be a challenge to find out which tile you or the user wants to draw
on the screen, if you are new to programming. Anyone good at math
should be able to figure it out. But if you lacking in programming
experience or math skills it could take a while. It may seem quite
obvious once you figure it out and you may decide to kick yourself in the
butt for not doing so sooner. To save you some time and pain, I will
write the code for you.
Supposing that your tile set is contained in a Picture box, you can
easily get the X and Y
coordinates where the user clicked. Note: Don't forget to change
the ScaleMode to 3 - Pixels. For our
example we will name our Picture box TileSetBox1
and in order to get the X and Y
of where the user clicked we will use the MouseUp
event. The code is as follows:
Private Sub TileSetBox1_MouseUp(Button As Integer,
Shift As Integer, X As Single, Y As Single)
Let XYTile.X = Fix(X / (TileWidth
+ 1)) + 1
Let XYTIle.Y = Fix(Y / (Tile.Height
+ 1)) + 1
End Sub
Again, we are using Fix to ensure that we don't have a remainder, we
are adding 1 to TileWidth and TileHeight to compensate for the 1 pixel
dividers in our set and, we are adding because Fix usually considers 0
to be the first number.
Note: The declaration for XYTile
appears in the Converting single to X,
Y section of this tutorial.
Single number tile set users
need to work backwards
If you are using a single number tile set then you need to work backwards
to be able to record the data correctly. What I mean by this is that
the section above gives you the information in X and Y format. You,
on the other hand, may be using single numbered tiles. In this case,
just use the following code:
Let SingleNumber = (XYTile.Y -1) * MaxCol + XYTile.X
What this does is figures out the last tile in the row above XYTile.Y
by subtracting 1 and multiplying by MaxCol.
Then we move on ahead by adding XYTile.X to
get the correct Tile.
Ok, now what?
Now that you have the Top Left corner of the tile, in the set, and all
data needed for recording purposes, we can move on and plot our tile.
Remember Xoff and Yoff
(in Basic declarations)? This is where they will come into place.
This can be an easy step, if you know Top and Left corner is of the tile
on your map. But suppose you don't. This is almost like finding
the Top and Left corner of your tile set, except you don't have to compensate
for the single pixel dividing the tiles because there aren't any on the
map. We do, however, have to compensate for Xoff
and Yoff.
Again in our code we need to have another variable to work with.
This should be put in a Module as well.
Public TileInMap as XYTileA
And our Function should look like this:
Public Function GetTopLeftOfTile (XofTile As Integer,
YofTile As Integer) As XYTileA
Let GetTopLeftOfTile.X = (XofTile
* TileWidth) - TileWidth + Xoff
Let GetTopLeftOfTile.Y = (YofTile
* TileHeight) - TileHeight + Yoff
End Function
Note: In the section below (But, what if I don't know that either?)
there is the declaration for XofTile and YofTile
This just simply multiplies the Row (XofTile)
by the width of the tiles (TileWidth).
We have to subtract TileWidth also because
1 * 2 = 2. Also Xoff because the far
left of the Map (Where the tiles start may not be at point 0 (zero).
We do this for the column (YofTile) as well.
But, what if I don't know that
either?
It's ok, you're in good hands. So, you need
what tile, on the map, you or the user clicked on. No problem.
This is much like finding out what tile in the tile set was selected, but
we don't have to compensate for the one pixel devoured and we have to compensate
for the Xoff and Yoff.
First we need our variables. You should
know where to put it by now (in the Module).
Public XofTile as Integer
Public YofTile as Integer
For this example we will be using a picture box
named TiledMap1. Remember to set the ScaleMode to 3-Pixel.
Private Sub TiledMap1_MouseUp(Button As Integer,
Shift As Integer, X As Single, Y As Single)
Let XofTile = Fix(X / TileWidth)
+ 1
Let YofTile = Fix(Y / TileHeight)
+ 1
End Sub
We figure out what tile the user clicked on by
dividing the mouse position (either X
or Y)
by the size of the tile (either TileWidth
or TileHeight).
We then add 1 because Fix starts at 0 (zero).
Well, that's it. You soon should be on your
way to creating a tile set, working on your editor, or plotting the tiles
on your map.
|