### Author Topic: [Tutorial] Tilemaps in Axe Basic  (Read 30880 times)

0 Members and 1 Guest are viewing this topic.

#### SirCmpwn

• Guest
##### [Tutorial] Tilemaps in Axe Basic
« on: April 07, 2010, 11:26:39 am »
Hey, I wanted to do something special for my 400th post, so I wrote a quick tutorial.

Tilemaps are a very important part of many, many games.  For more information on what a tilemap is and how it relates to games, see this: http://en.wikipedia.org/wiki/Tile_engine  So, let's jump right in:

Getting started: The Data
The tilemap data actually defines which tiles go where.  Now, in Axe, we use the [] tokens to store hex data.  If you are not clear on what hex is, go here: http://vlaurie.com/computers2/Articles/hexed.htm.  A hex pair consists of two digits.  Now, we want to compress our map data, and using a special routine from BuilderBoy, we can cut our map data in half.  We have to limit ourselves to 16 tiles per map, but I'll address how to get around that later.  Anyways, here is an example map, 4x4 for the purposes of the demonstration:
Code: [Select]
[1111->GDB1
[1001
[1001
[1111
Let's explain this.  How can we store 4 tiles to two bytes?  Well, we use each digit to store a tile.  We will talk about how to get each digit alone later.  Let me explain, however, why I put "->GDB1" at the top as opposed to the bottom, like you would do for a sprite.  GDB1 is just a pointer.  You see, Axe is going to add this data to the bottom of the program output.  It also will set GDB1 to point at the very first one.  However, if we were to re-arrange the code like so:
Code: (Axe Basic) [Select]
[1111
[1001
[1001
[1111->GDB1
Then we would have GDB1 point to the 7th byte after the start of the map data.  This would be bad because it would make the first row all "1" tiles, and the rest of the rows the random gibberish sitting in the memory after the last row.  Not good.  So, we put "->GDB1" on the first line.  Also, for the sake of demonstration, please have your sprites in Pic1.

Drawing the Tile Map
Having the data is nice and all, but at some point you want to show it off.  So, we have a simple method to draw it.  The following method uses a 14x9 tile map with 7x7 tiles (hmm, isn't that what Half-Life 2: OC uses? ).  However, it should be easily customizable to fit with your needs.
Code: (Axe Basic) [Select]
ClrDraw
For(I,0,7  // Start at zero, and go until your tile map width diveded by two (because we store two tiles for every one byte)
For(J,0,8  // The Y axis has one byte to each tile, so you can just use the height minus one here.
{J*9+I+GDB1->A  // J*9 gets us the row offset (see below) and we just add the X value.
A^16->B // Get the second digit of the hex into B
A/16->A // And the first digit into A
If A
Pt-On(I*14,J*7,Pic1+A-8  // I*14 because of the two tiles to a byte, J*7 because of 7 pixel tiles
End
If B
Pt-On(I*14+7,J*7,Pic1+B-8
End
End
End
Spoiler For Cool Optimization:
If you have more sprites than just what is needed for the tilemap, you can optimize away the "-8" subtraction in the Pt-On lines.  You also need to have Pic1 point to the sprite before the first tile map sprite in the data.
A^16?!? A/16?!?  How is that supposed to get each digit?!?  Honestly, I don't know.  Ask BuilderBoy.  It vaugely makes sense in my mind, but I haven't put a lot of brainpower towards it.  Anyway, this routine will draw your tilemap on-screen, without updating the screen.  It's your job to call DispGraph eventually, but you can still draw a character or something without having to worry about flicker.
Now, this line: "{J*9+I+GDB1->A" is weird.  Let me explain.  If you have a tilemap that looks like this:
11111111111111
10000000000001
10000000000001
10000000000001
10000000000001
10000000000001
10000000000001
10000000000001
11111111111111
It doesn't get stored in memory looking nice and layed out for you.  It gets stored like this:
111111111111111000000000000110000000000001100000000000011000000000000110000000000001100000000000011000000000000111111111111111
So, what we can do to find the correct tile is this.  We start with the row.  We know each row is 7 bytes wide (2 tiles to a byte, remember?), so we can multipy J by seven.  So if we have J=2, then we get J=14.  That gives us an offset of 14 bytes.  So, we have eliminated tiles and we have a current estimate of which byte we are going to draw: (X for an eliminated tile)
XXXXXXXXXXXX
XXXXXXXXXXXX
10000000000001
10000000000001
10000000000001
10000000000001
10000000000001
10000000000001
11111111111111
Now, we just add the I value to get the current X offset, getting us the actual byte we need (I=3):
XXXXXXXXXXXX
XXXXXXXXXXXX
XXXXX00000001
10000000000001
10000000000001
10000000000001
10000000000001
10000000000001
11111111111111
Ta-da!  We have the correct byte. Now we can use voodoo magic to extract each individual digit from the byte, and draw it on-screen.

Getting a Tile
Hooray!  You drew a tilemap!  Congradulations!  Now, if you want to use something better than Pxl-Test to check collisions with it, you need to be able to get the value of a single tile.  I won't bother explaining this routine in detail, but just know I spent a half hour on it so you don't have to:
Code: (Axe Basic) [Select]
Lbl GT  ; X position in S, Y position in T.  Returns tile
S/7->S  // Swap 7 for the size of your tiles
T/7*7->T  // Yes, I know it is /7*7.  Leave it that way.  Unless you don't have 7x7 tiles, in which case you should change the values accordingly
If S^2
{(S/2)+T+GDB1}^16
Return
End
{(S/2)+T+GDB1}/16
Return

More Than 16 Tiles
You may get to here and realize that, using this method, you can only have up to 16 tiles, one for each digit 0-F.  This is true.  However, you can have different tiles for different maps.  What?  You can only have 16 tiles per map, but you can have 16 unique tiles per map.  So, you can have different "themes" for each map.  It's easy.  Here is a revised draw method:
Code: (Axe Basic) [Select]
ClrDraw
For(I,0,7  // Start at zero, and go until your tile map width diveded by two (because we store two tiles for every one byte)
For(J,0,8  // The Y axis has one byte to each tile, so you can just use the height here.
{J*9+I+GDB1->A  // J*9 gets us the row offset (see below) and we just add the X value.
A^16->B // Get the second digit of the hex into B
A/16->A // And the first digit into A
If A
Pt-On(I*14,J*7,O*8+Pic1+A-8  // I*14 because of the two tiles to a byte, J*7 because of 7 pixel tiles.  O is the offset
End
If B
Pt-On(I*14+7,J*7,O*8+Pic1+B-8
End
End
End

You'll notice we added "O*8+" to the Pt-On lines.  This will make it so that you can specify O as an offset sprite.  So, if you wanted an entirely new set of tiles, you can specify O as 16, which would point to the sprites after the first set.  If you wanted to add one new sprite and lose the first old sprite, you could specify 1.  If you want the original sprites, specify O=0.

If you have any questions, feel free to post them, and I will do my best to answer.

Also, 400th post!
« Last Edit: April 07, 2010, 10:58:15 pm by SirCmpwn »

#### Eeems

• Mr. Dictator
• LV13 Extreme Addict (Next: 9001)
• Posts: 6234
• Rating: +318/-36
• little oof
##### Re: Tutorial: Tilemaps in Axe Basic
« Reply #1 on: April 07, 2010, 11:33:19 am »
sweet! this could come in handy for my mario game....if you want I can style this with my tutorial style I had in my tutorial.
/e

#### SirCmpwn

• Guest
##### Re: Tutorial: Tilemaps in Axe Basic
« Reply #2 on: April 07, 2010, 11:34:26 am »
Can you email me your idea for the format before you do?

#### Eeems

• Mr. Dictator
• LV13 Extreme Addict (Next: 9001)
• Posts: 6234
• Rating: +318/-36
• little oof
##### Re: Tutorial: Tilemaps in Axe Basic
« Reply #3 on: April 07, 2010, 11:39:31 am »
I could just PM you actually, you can edit it for yourself and then I'll actually apply the post so it will work.
/e

#### SirCmpwn

• Guest
##### Re: Tutorial: Tilemaps in Axe Basic
« Reply #4 on: April 07, 2010, 11:39:55 am »

#### Eeems

• Mr. Dictator
• LV13 Extreme Addict (Next: 9001)
• Posts: 6234
• Rating: +318/-36
• little oof
##### Re: Tutorial: Tilemaps in Axe Basic
« Reply #5 on: April 07, 2010, 11:44:59 am »
done, also, I'll have to apply it later today, class ended
/e

#### DJ Omnimaga

• Former TI programmer
• CoT Emeritus
• LV15 Omnimagician (Next: --)
• Posts: 55893
• Rating: +3152/-232
• CodeWalrus founder & retired Omnimaga founder
##### Re: Tutorial: Tilemaps in Axe Basic
« Reply #6 on: April 07, 2010, 12:29:53 pm »
Thanks a lot, I think I am getting the grasp of tilemapping in Axe, but I haven't messed around with them as much yet. Hopefully this should be very useful if I get problems or missed something.

Nice tutorial

#### SirCmpwn

• Guest
##### Re: [Tutorial] Tilemaps in Axe Basic
« Reply #7 on: April 07, 2010, 12:33:39 pm »
Thanks.  I have been thinking about releasing this one for a while, it was just finally prompted by my lack of respect on this forum.  It's down to 1 :O, I want to restore some of my credibility.

#### DJ Omnimaga

• Former TI programmer
• CoT Emeritus
• LV15 Omnimagician (Next: --)
• Posts: 55893
• Rating: +3152/-232
• CodeWalrus founder & retired Omnimaga founder
##### Re: [Tutorial] Tilemaps in Axe Basic
« Reply #8 on: April 07, 2010, 12:36:26 pm »
mhmm strange it has been a while since I actually saw it drop a lot :O. It was at 9 then dropped to 0 a few weeks ago, though, but since then I think it remained kinda stable

projects updates/tutorials/helping can help increase it, though (unless activity is ridiculously high, like last night around 11PM-1AM of my time)

#### SirCmpwn

• Guest
##### Re: [Tutorial] Tilemaps in Axe Basic
« Reply #9 on: April 07, 2010, 01:08:11 pm »
Yeah, I just need less complex projects to get more frequent updates
HL2: OC, LinTIx, and Mosaic are my major projects, and they are all pretty hefty.

#### meishe91

• Super Ninja
• LV11 Super Veteran (Next: 3000)
• Posts: 2946
• Rating: +115/-11
##### Re: [Tutorial] Tilemaps in Axe Basic
« Reply #10 on: April 07, 2010, 05:22:47 pm »
Nice tutorial. I'm not sure if I followed it all but that's just from lack of Axe knowledge.

(By the way, as a tip for the future. BBCode doesn't work inside the [code ][/code ] command (I just noticed the [b ][/b] to try to bold and thought I'd let ya know for the future.).)
« Last Edit: April 07, 2010, 05:24:39 pm by meishe91 »
Spoiler For Spoiler:

For the 51st time, that is not my card! (Magic Joke)

#### DJ Omnimaga

• Former TI programmer
• CoT Emeritus
• LV15 Omnimagician (Next: --)
• Posts: 55893
• Rating: +3152/-232
• CodeWalrus founder & retired Omnimaga founder
##### Re: [Tutorial] Tilemaps in Axe Basic
« Reply #11 on: April 07, 2010, 05:35:43 pm »
What I do if I need bbcode is

Code: [Select]
[quote][font=monospace]text
goes
here[/font][/quote]

Then check the "Don't use smileys" box.

#### meishe91

• Super Ninja
• LV11 Super Veteran (Next: 3000)
• Posts: 2946
• Rating: +115/-11
##### Re: [Tutorial] Tilemaps in Axe Basic
« Reply #12 on: April 07, 2010, 06:03:29 pm »
@DJ What do you mean exactly? What you said just isn't making sense to me is all, sorry.
« Last Edit: April 07, 2010, 06:03:44 pm by meishe91 »
Spoiler For Spoiler:

For the 51st time, that is not my card! (Magic Joke)

#### DJ Omnimaga

• Former TI programmer
• CoT Emeritus
• LV15 Omnimagician (Next: --)
• Posts: 55893
• Rating: +3152/-232
• CodeWalrus founder & retired Omnimaga founder
##### Re: [Tutorial] Tilemaps in Axe Basic
« Reply #13 on: April 07, 2010, 06:42:48 pm »
Could someone else explain for me? I don't really have the patience to explain stuff like this this evening when I alerady done enough effort to do so. No offense intended.

#### meishe91

• Super Ninja
• LV11 Super Veteran (Next: 3000)
• Posts: 2946
• Rating: +115/-11
##### Re: [Tutorial] Tilemaps in Axe Basic
« Reply #14 on: April 07, 2010, 07:03:21 pm »
Oh, sorry, DJ. I wasn't trying to be rude or anything. When I read what you said it just wasn't making sense in my head for some reason (probably my lack of sleep). I think I get it now though. Did you mean that instead of using "code" to have a box around it you use "quote" when you still need BBCode inside (since BBCode doesn't work in "code")? Sorry again, wasn't trying to aggravate you or anything like that.
Spoiler For Spoiler:

For the 51st time, that is not my card! (Magic Joke)