Basic4GL
« Tile Map Tutorial »

Welcome Guest. Please Login or Register.
May 22, 2013, 5:12pm




Basic4GL :: BASIC4GL Boards :: BASIC4GL Help :: Tile Map Tutorial
Page 1 of 2 » Jump to page   Go    [Search This Thread] [Share Topic] [Print]
 AuthorTopic: Tile Map Tutorial (Read 5,653 times)
Linkage
Posts a bit
***
member is offline





Joined: Jan 2007
Posts: 147
 Tile Map Tutorial
« Thread Started on Mar 3, 2007, 11:57pm »

Here's a tutorial I've written for Tile Maps. I'm not sure if it's of much use to most of the people here, but it's aimed at the people who are new to sprites and stuff.

So, you know how to use sprites, and want to make your own 2D game. But most of the time, such a game will require a level to move around, and you’re not sure how to make it. You COULD make it one big sprite, or heaps of sprites put together, but that’d be annoying, and would probably slow the game down. So what’s a good way to make levels? Tile Maps.

Tile Maps are very similar to sprites, but are generally meant to be bigger and don’t require making a huge sprite. Instead, you take a picture that has multiple segments, referred to as tiles, and take each segment and place them where you want, kind of like a puzzle. This way, we can make a map using as little as 2 tiles.

So how do we make these Tile Maps? This tutorial will show you how, providing sample code and explanations of how it works to give you a good understanding of them. You don’t really need to know too much about Basic4GL to get through this tutorial, but an understanding of the main basic things such as loops, variables etc. Is required.

OK, so here we go. First, we need a picture to use as our tiles. For now, we’ll just use a very simple one, with only 2 tiles. Here it is:

[image]
(you’ll need to save this picture into whatever directory you’re running the finished program from, under the filename basictiles)

As you can see, it’s just divided into black and white sections. Seeing as the default background for Basic4GL programs is black, we’re going to use the white area to show where “something” is, and the black area for blank space.

Now, we’re going to write a section of code that we’ll use later on to tell Basic4GL how to distribute the tiles for the Tile Map. For this we use a data table:

Code:
TileData:
data 9,5
data 1,1,1,1,1,1,1,1,1
data 1,0,0,0,0,0,0,0,1
data 1,0,0,0,0,0,0,0,1
data 1,0,0,0,0,0,0,0,1
data 1,1,1,1,1,1,1,1,1

If you’ve never seen the data command before, it is basically used to tell Basic4GL that anything after it is going to be read into the program later and used accordingly.

Now, from looking at the data there, we can see the general shape of a room, visualising the 1s as white space and the 0s as black space. It is useful when using data tables for tile maps to keep all the numbers aligned, so it makes it easier to see in the numbers your map. However, when you start using pictures with an amount of tiles that goes into double digits, they may become unaligned and harder to visualise. It’s obviously not very good to restrict the variety of a tile map simply so that you can code it easier, so you’ll have to either put up with it or leave the first 10 spaces blank, so that all of the tiles will have double digits (and if you go into triple digits, well... that’s one big Tile Map!).

Also, you may be wondering why we have the 9 and the 5 up the top. We’re going to use that laster to help tell the program just how much data to read. When making your own tile maps, you'll have to make the first number equal to the amount of columns in your data, and the second equal to the amount of rows.

Now, we have to actually store that data into a variable so that we can use it. For that we have to dim a few variables and go through a certain subroutine:

Code:
dim &tiles ()(), mapx, mapy, i, x, y

LoadTiles:
read mapx, mapy
alloc tiles, mapx -1, mapy - 1
for y = 0 to mapy - 1
for x = 0 to mapx - 1
read i
tiles (x)(y) = i
next
next
return


You’re probably a bit puzzled as to how this works, so I’ll explain it bit by bit.

First, we dim a pointer variable. So far, the best explanation of pointer variables that I have come across is from Davy:

Quote:
Basic4gl's memory is allocated on one big array. So, say you dim the variable "X", you are just expanding the size of that big array by one, then the label "X" is replaced with the index into the memory array (assuming "X" is the first variable, it would be 0 or something).

Pointers are able to store that index value, so they essentially "point" to a place in memory... But they aren't stuck there, they can be changed and point to various locations in memory.

Pointer variables must be dimmed with a & at the start, and the type we are dimming, which is going to have a 2D array of numbers, must have a ()() at the end. The other variables we are dimming are all integer variables.

OK, now to the more confusing bits. First, we use read. Read does more or less what it says- it reads data, starting from the top, and assigns the values it reads to the variables told. So in this case, it first reads the data 9, and assigns it to mapx, and then the 5, and assigns it to mapy. So now mapx = 9 and mapy = 5.

Then, we use alloc. We use this to allocate the values of mapx – 1 and mapy – 1 to the array dimensions of &tiles. So now, &tiles has the dimensions of (8) and (4). This means that it is divided up into 9 sections, each with 9 values (remember, in arrays 0 is included as a usable section).

Now we use two for loops to read the rest of the data. Because when we go through the first loop the first time, it executes all of the second for loop, in which it reads the next piece of data into i, and ends up doing that instruction the amount of times equal to 9 times 5, which equals 45. So that way, we get it to read all of the data we put in. Also in the second for loop is an instruction to make tiles (x)(y) equal the current value of i. So we end up storing all of our data values into tiles, which we will now use to make the actual map appear. So after that code we place this:

Code:
MakeMap:
tilemap = LoadImageStrip("basictiles.gif", 32)
gosub LoadTiles
map = NewTileMap(tilemap)
SprSetYRepeat(false)
SprSetXRepeat(false)
SprSetTiles(tiles)


And we add some more variables to our dim statement:

Code:
dim &tiles ()(), mapx, mapy, i, x, y, tilemap(1), map


And one line of code after that dim statement:

Code:
goto MakeMap


To end up with a working program, which is this:

Code:
TileData:
data 9,5
data 1,1,1,1,1,1,1,1,1
data 1,0,0,0,0,0,0,0,1
data 1,0,0,0,0,0,0,0,1
data 1,0,0,0,0,0,0,0,1
data 1,1,1,1,1,1,1,1,1

dim &tiles ()(), mapx, mapy, i, x, y, tilemap(1), map

goto MakeMap

LoadTiles:
read mapx, mapy
alloc tiles, mapx -1, mapy - 1
for y = 0 to mapy - 1
for x = 0 to mapx - 1
read i
tiles (x)(y) = i
next
next
return

MakeMap:
tilemap = LoadImageStrip("basictiles.gif", 32)
gosub LoadTiles
map = NewTileMap(tilemap)
SprSetYRepeat(false)
SprSetXRepeat(false)
SprSetTiles(tiles)


So, if you run that, you can see the results, but first let me explain how the code we added works:

Code:
MakeMap:
tilemap = LoadImageStrip("basictiles.gif", 32)
gosub LoadTiles
map = NewTileMap(tilemap)
SprSetYRepeat(false)
SprSetXRepeat(false)
SprSetTiles(tiles)


This area first assigns the variable tilemap the Image Strip of our tile picture, using LoadImageStrip. This loads our image as a texture with tilemap as its handle. Then, we use gosub, which tells the program to skip to another labelled area of the program and run the code from there until it hits a return command, at which point it goes back to where it was. In this case, it sends it to the LoadTiles subroutine, where all the values of &tiles are set. Then, we use NewTileMap to make map a Tile Map, with the tiles in tilemap. SprSetXRepeat and SprSetYRepeat stop the map from being continuously displayed in both X and Y directions. Then we use SprSetTiles to set the map’s tiles to those indicated in &tiles, at which point it displays it.

The goto command we added before just makes the program skip straight to the MakeMap section, so it doesn't try to tun the LoadTiles section first.

So, hopefully this tutorial has given you a good understanding of how to make Tile Maps. If not, let me know and I’ll either try and address your questions personally or edit the tutorial to fit your needs. The most common thing I could think of is that maybe my explanations in some parts were a bit vague/confusing.

I’m also planning on making another one or two tutorials to do with Tile maps, such as collision detection with them.

EDIT: Almost forgot, I need to extend this slightly to explain how to load multiple maps. Not sure when I'll get around to it.
« Last Edit: Mar 10, 2007, 9:40pm by Linkage »Link to Post - Back to Top  IP: Logged
matthew
Global Moderator
*****
member is offline

[avatar]

[icq] [yim] [msn] [aim]
[homepage]

Joined: Apr 2006
Gender: Male
Posts: 2,199
Location: England
 Re: Tile Map Tutorial
« Reply #1 on Mar 4, 2007, 3:41am »

I'm sure that a lot of people will find it useful. :)
Link to Post - Back to Top  IP: Logged

Linkage
Posts a bit
***
member is offline





Joined: Jan 2007
Posts: 147
 Re: Tile Map Tutorial
« Reply #2 on Mar 6, 2007, 12:41am »

OK, here's the section on multiple Tile Maps, and I've also edited some sections of the previous section to make a few things clearer.

EXTENSION: Loading Multiple Tile Maps

Loading multiple Tile Maps is not much different from loading a single tile map. For our example, we are simply going to add a second data table and make some changes to the section of code that makes the maps. Here’s the second data table:

Code:
TileData2:
data 7, 4
data 1,1,1,1,1,1,1
data 1,0,1,0,1,0,1
data 1,0,1,0,1,0,1
data 1,1,1,1,1,1,1


You should place that under the previous data table.

And here’s the changes we need to make to the part that makes the maps:

Code:
MakeMap:
tilemap = LoadImageStrip("basictiles.png", 32)
reset TileData
gosub LoadTiles
map(0) = NewTileMap(tilemap)
SprSetYRepeat(false)
SprSetXRepeat(false)
SprSetTiles(tiles)
reset TileData2
gosub LoadTiles
map(1) = NewTileMap(tilemap)
SprSetXRepeat(false)
SprSetYRepeat(false)
SprSetTiles(tiles)
SprSetPos(300,100)


We also need to slightly change part of our dim statement, too, so that map looks like map(1).

So, what difference has our changes made? If you’ve run that, you’ll see that it displays two Tile Maps in different sections of the screen. We do this by, apart from adding a second section to make a map, by adding in the reset function. The reset function resets the spot from which the program will read data to the label you tell it to. This is useful when you need the program to read sections of data from different places in the program. In this particular program, it’s not actually necessary, but in proper 2D games it’s important to have it before every time you run the LoadTile routine, as you will probably end up having to read certain sections of data multiple times. So by placing these commands in front of every time you run the LoadTiles routine, we make sure that the data we want to be read is read.

There is also one more function at the end of the program: SprSetPos. This just moves our second tile map to the designated position on screen, so we can see both at the same time.

Some changes that could be made to this program is to, while having multiple tile maps, to only display one at a time. Apart from a small section to decide which one to display, it’s also good to add in some more pointer variables, so that rather than having multiple map-making sections, we only add an if statement to the section that sets its tiles. For this we’d have to add a line to, with the new pointer variables, set the pointer variable you want to mirror the current &tiles after each LoadTiles routine. But, I’ll let you give that a try for yourself.
Link to Post - Back to Top  IP: Logged
Centanoul
Posts a lot
****
member is offline

[avatar]

I do be Cent the Coding Monkey

[msn]

Joined: Jan 2005
Gender: Male
Posts: 269
Location: NC, USA
 Re: Tile Map Tutorial
« Reply #3 on Mar 8, 2007, 3:25pm »

This.Post = This.Post + "Sticky"
Error: Not Moderator

Seriously though, someone should sticky this on the bat.
Link to Post - Back to Top  IP: Logged

"How do I print 'Hello World'?" ~Cent
davy
Global Moderator
*****
member is online
member is offline

[avatar]

[msn] [aim]
[homepage]

Joined: May 2006
Gender: Male
Posts: 1,049
Location: USA
 Re: Tile Map Tutorial
« Reply #4 on Mar 8, 2007, 7:04pm »


Quote:

First, we dim a pointer variable. I don’t know much about pointer variables, so I can’t go into a proper explanation of them (although anyone who can and is willing to contribute one to this tutorial... please go ahead)


OK... Pointers aren't really as complex as people generally think they are. They do what they say they do and "point" to a location in memory (generally where another variable is being stored)

In this case you're using them with dynamically allocated memory.

I do have to point out for anyone afraid of pointers that there is another way of doing this...

Code:
dim mapx, mapy, i, x, y

LoadTiles:
read mapx, mapy
dim tiles (mapx-1)(mapy-1)
for y = 0 to mapy - 1
for x = 0 to mapx - 1
read i
tiles (x)(y) = i
next
next
return


Both ways will work. Since the width/height are already known by the programmer, you can do without having to dynamically allocate the space.
Link to Post - Back to Top  IP: Logged

Linkage
Posts a bit
***
member is offline





Joined: Jan 2007
Posts: 147
 Re: Tile Map Tutorial
« Reply #5 on Mar 9, 2007, 7:32am »

The thing with that is that I'm pretty sure that when having multiple data sections to be read, an error would occur when it came to re-dimming the tiles pointer. So while it would for single tile maps, having more than one to load would be troublesome, and in most games I'd expect to have many more than one Tile Map.

Also, I can think of at least three more tutorials on Tile Maps that I could end up writing: Collision Detection (not too hard), Animation (not too hard either), and switching between Tile Maps, like going from one room into another (a bit more lengthy than the others, but still not too hard).

Don't hold your breath for them though. I really don't know when I'll find the time to do them.
Link to Post - Back to Top  IP: Logged
davy
Global Moderator
*****
member is online
member is offline

[avatar]

[msn] [aim]
[homepage]

Joined: May 2006
Gender: Male
Posts: 1,049
Location: USA
 Re: Tile Map Tutorial
« Reply #6 on Mar 9, 2007, 7:58am »

I'm aware that dynamic memory is a blessing, I'm just explaining that it's not the only way in case someone gets frightened by the use of alloc.

This would work for multiple maps (you have to add the map count to the data):


dim map_count, mapx, mapy, i, x, y, n

read map_count
read mapx, mapy
dim tiles (map_count)(mapx-1)(mapy-1)
for n = 0 to map_count
for y = 0 to mapy - 1
for x = 0 to mapx - 1
read i
tiles (n)(x)(y) = i
next
next
next
« Last Edit: Mar 9, 2007, 9:53am by davy »Link to Post - Back to Top  IP: Logged

Linkage
Posts a bit
***
member is offline





Joined: Jan 2007
Posts: 147
 Re: Tile Map Tutorial
« Reply #7 on Mar 9, 2007, 8:27pm »

Hm, I never thought of that. Oh well.

Oh, and do you mind if I stick that tidbit of info on pointers into the main tutorial?

Thanks for the sticky as well.
Link to Post - Back to Top  IP: Logged
davy
Global Moderator
*****
member is online
member is offline

[avatar]

[msn] [aim]
[homepage]

Joined: May 2006
Gender: Male
Posts: 1,049
Location: USA
 Re: Tile Map Tutorial
« Reply #8 on Mar 9, 2007, 10:36pm »


Quote:
Hm, I never thought of that. Oh well.

Oh, and do you mind if I stick that tidbit of info on pointers into the main tutorial?

Thanks for the sticky as well.


Well, either way works. It just depends whether or not they are comfortable with dynamically allocated memory (I didn't get into that until I started getting into C)

You can certainly add that to the main tutorial, but I bet you can find a more thorough explanation somewhere on these boards. That was kind-of a half-smurfed way of explaining it.

Basic4gl's memory is allocated on one big array. So, say you dim the variable "X", you are just expanding the size of that big array by one, then the label "X" is replaced with the index into the memory array (assuming "X" is the first variable, it would be 0 or something).

Pointers are able to store that index value, so they essentially "point" to a place in memory... But they aren't stuck there, they can be changed and point to various locations in memory.

This is basically how pointers work in C and C++ too, but instead of storing the index of the memory array, they point to the actual physical memory location the data is being stored.

C also has a command similar to "alloc" but it's called "malloc"
C++ has "new"

However, since C and C++ allocate their memory in the physical address, the memory must be freed or it can cause a memory leak...

Basic4GL uses a safer alternative to memory allocation so those issues don't exist.
Link to Post - Back to Top  IP: Logged

Linkage
Posts a bit
***
member is offline





Joined: Jan 2007
Posts: 147
 Re: Tile Map Tutorial
« Reply #9 on Mar 10, 2007, 9:41pm »

OK, updated first post with your explanation from the post above stuck in.
Link to Post - Back to Top  IP: Logged
timid
Posts
**
member is offline





Joined: Nov 2007
Gender: Male
Posts: 52
 Re: Tile Map Tutorial
« Reply #10 on Dec 7, 2007, 1:23pm »

nice tut, although......im bit slow on this....can you explain how does the program determine what part of the image is 1 and 0 ? how about showing a tut with a Tilemap 3x3 tiles ?
Link to Post - Back to Top  IP: Logged
Linkage
Posts a bit
***
member is offline





Joined: Jan 2007
Posts: 147
 Re: Tile Map Tutorial
« Reply #11 on Dec 7, 2007, 6:37pm »

I'm not sure I completely understand your question, but I'll try and give it an answer anyway.

So, I guess I may not have made it clear how the tilemap knows what tiles to put where. Basically, how that's done is in in this line:

Code:
SprSetTiles(tiles)


This tells the tilemap to use the array we declared earlier, tiles, as its reference for what tiles go where. Now, if you remember back to where we gave tiles its values:

Code:
LoadTiles:
read mapx, mapy
alloc tiles, mapx -1, mapy - 1
for y = 0 to mapy - 1
for x = 0 to mapx - 1
read i
tiles (x)(y) = i
next
next
return


Remember how this code loaded our Tile Data into the tiles array? So, after that, the tiles variable looks more or less the same as the Tile Data:

Code:
data 1,1,1,1,1,1,1,1,1
data 1,0,0,0,0,0,0,0,1
data 1,0,0,0,0,0,0,0,1
data 1,0,0,0,0,0,0,0,1
data 1,1,1,1,1,1,1,1,1


So, when we tell our tilemap to use tiles as its reference for what tiles go where, it looks in that array and, where it sees a 1, places a white square there and then continues on to look at the other variables, placing white squares for 1 and then black for 0.

I hope that answers your question. If you're still having trouble, go ahead and ask more.
Link to Post - Back to Top  IP: Logged
El_Dorado
Posts
**
member is offline

[avatar]

Your Time Has Come

[yim] [aim]
[homepage]

Joined: Jan 2008
Gender: Male
Posts: 65
Location: Hades
 Re: Tile Map Tutorial
« Reply #12 on Jan 18, 2008, 1:25pm »

Hmm. Good tutorial. I stopped fumbling with DATA a while back and just started using variables X and Y in tiles(x)(y)=variable to change tilemaps up or create tilebases.

It's easier for me, but DATA is just confusing in general. Tutorial helps a lot for those who don't know what they're doing, though I didn't learn much from it. I'm assuming it's because I've studied some B4GL examples and I've learned all of this by doing such...

In fact, that's how I learned to use 3D in my programs. I studied the walkaround demos and the NeHe stuff, and it helps a lot. I think the most effective effort was putting the tutorial/demonstration programs into Basic4GL.

Ah, I'm babbling again...
Link to Post - Back to Top  IP: Logged

The Bucket Fan Club founding member.
Linkage
Posts a bit
***
member is offline





Joined: Jan 2007
Posts: 147
 Re: Tile Map Tutorial
« Reply #13 on Jan 25, 2008, 9:43pm »

Yeah, for some people studying demo code can be the best way to learn something. I actually learnt how to use tilemaps from the Documentation + the CavernDemo, but I wanted to write a tutorial on it because I think people new to programming would prefer tutorials where everything is explained so they can then understand it. I also am the kind of person who likes everything to be explained in full.

I also saw that tutorial-wise, Basic4GL has a bit of a learning gap in terms of the lead up to making 2D games. Tom's ASCII tutorials are great for beginners (it's where I started), but I thought the areas of actual 2D graphics were left out in the cold a bit, so I hoped that by making this I could help out in that.
Link to Post - Back to Top  IP: Logged
Darkjester
Posts a lot
****
member is offline

[avatar]



Joined: Jun 2009
Gender: Male
Posts: 425
 Re: Tile Map Tutorial
« Reply #14 on Apr 11, 2008, 3:43pm »

What is a common format for a tilemap or is there?
Link to Post - Back to Top  IP: Logged

Page 1 of 2 » Jump to page   Go    [Search This Thread] [Share Topic] [Print]

Click Here To Make This Board Ad-Free


This Board Hosted For FREE By ProBoards
Get Your Own Free Message Boards & Free Forums!
Terms of Service | Privacy Policy | Notice | FTC Disclosure | Report Abuse | Mobile