 Computer Science Canada Programming C, C++, Java, PHP, Ruby, Turing, VB   Username:   Password: Wiki Blog Search Turing Chat Room Members
[Tutorial] 2D Tile based games        Author Message
CodeMonkey2000 Posted: Wed Jun 13, 2007 4:13 pm   Post subject: [Tutorial] 2D Tile based games

2D Tile Based Games

Before going into the tutorial, you will need to be fairly experienced with arrays (2d, flexible etc), function and procedures.

How tile based games work

Basically you have a text map saved in grid format. E.g. like:
1 1 1 1 1 1 1
1 0 0 0 0 0 1
1 1 1 1 1 1 1

Imagine that the screen is broken into blocks, 7 across and 3 down. Now imagine that each number in the text map represents a 10x10 tile/block on the screen. 1 means red tiles and 0 means black tiles. The position of the numbers is important, as that is going to be where the tiles are drawn. The top row in the text grid represents the top row which will be drawn on our screen (in this case the entire top row will be red, since the entire top row is 1). In the text map if I asked you what is at grid (1,3 ) you would say 1. So a red tile needs to be draw at grid 1,3 on our runtime screen. In short, the text map above should translate on screen into: *removed*

Creating and drawing a map.

First off let’s assume that our map is going to be 15 by 15 tiles. So our text file will have 15 numbers going across and 15 numbers going down. Now, let’s assume that each tile takes up 10 by 10 pixels. The number 1 still represents red tiles and the number 0 still represents black tiles. Here is a text file I made, save it as map.txt on your desktop:

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 1 1 1 0 0 0 0 0 0 1
1 0 0 0 0 0 0 1 0 0 0 0 0 0 1
1 0 0 0 0 0 0 1 1 1 1 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Now we need a 2d array which will store the numbers from the text file. The array size should be as follows: 0..14, 0..14. You will see why I started the array at 0 rather than 1 when we draw the map. We want the way we call our array to be the same as how we call a coordinate in the text grid (for collision purposes). Array (0,0) will store the number at the bottom left corner, array (0,1) will store the number right above it, array(1,1) will store the number which is to the right of the previous number, array (14,14) is the top right tile (which will be a red tile)…etc. So if I look at array (10,1) I am looking at a black tile. Now we need a way of storing the number from our text file into our array. Well, first we will need to open the text file. The way we get the information is simple: for every y and for every x in the array get the number. Drawing the map will have a similar for structure; for every y and for every x in the array, if the number is 1 draw a red box at x*10,y*10 (since each tile is 10 by 10 as stated above) or else draw a black box x*10,y*10 (We started the array at 0 because 1*10 is 10, so the whole map would be off 10 pixels). Here is some code which will draw our map (save this to where you save the text file above):
 Turing: View.Set ("graphics:150;150") var tiles : array 0 .. 14, 0 .. 14 of int var FileName : string := "map.txt" var FileNo : int open : FileNo, FileName, get for y : 0 .. 14 % for every y     for x : 0 .. 14 %for every x         get : FileNo, tiles (x, y) %get the tile type at (x,y)     end for end for close (FileNo) for x : 0 .. 14     for y : 0 .. 14         if tiles (x, y) = 1 then             Draw.FillBox (x * 10, y * 10, x * 10 + 10, y * 10 + 10, red) % the +10 is there because each tile is 10 by 10         else             Draw.FillBox (x * 10, y * 10, x * 10 + 10, y * 10 + 10, black)         end if         locate (5, 1)         put x, ' ', y .. % the current tile we are drawing         delay (150)         %that just shows you what's going on if you still aren't sure     end for end for

If you are observant you will notice that the displayed map is upside down. Why? Well when turing reads from a file, it starts at the top line and goes to the bottom. When we read our file we assume that the first line is the bottom and goes up. We should be starting our y at the top and work our way down. So we should be doing this:
 Turing: View.Set ("graphics:150;150") var tiles : array 0 .. 14, 0 .. 14 of int var FileName : string := "map.txt" var FileNo : int open : FileNo, FileName, get for decreasing y : 14 .. 0 % we start off from the top and go to the bottom     for x : 0 .. 14 %for every x         get : FileNo, tiles (x, y) %get the tile type at (x,y)     end for end for close (FileNo) for x : 0 .. 14     for y : 0 .. 14         if tiles (x, y) = 1 then             Draw.FillBox (x * 10, y * 10, x * 10 + 10, y * 10 + 10, red) % the +10 is there because each tile is 10 by 10         else             Draw.FillBox (x * 10, y * 10, x * 10 + 10, y * 10 + 10, black)         end if         locate (5, 1)         put x, ' ', y .. % the current tile we are drawing         delay (150)         %that just shows you what's going on if you still aren't sure     end for end for

Collision detection.
Finally we are into collision! First off, let’s make a moveable piece (which will be our player) and make a redraw procedure:
 Turing: View.Set ("graphics:150;150,offscreenonly") var tiles : array 0 .. 14, 0 .. 14 of int var FileName : string := "map.txt" var FileNo : int open : FileNo, FileName, get for decreasing y : 14 .. 0 % for every y     for x : 0 .. 14 %for every x         get : FileNo, tiles (x, y) %get the tile type at (x,y)     end for end for close (FileNo) procedure reDraw     for x : 0 .. 14         for y : 0 .. 14             if tiles (x, y) = 1 then                 Draw.FillBox (x * 10, y * 10, x * 10 + 10, y * 10 + 10, red) % the +10 is there because each tile is 10 by 10             else                 Draw.FillBox (x * 10, y * 10, x * 10 + 10, y * 10 + 10, black)             end if         end for     end for end reDraw var key : array char of boolean var px, py : int := 1 % we start off at grid 1,1. %Note we don't begin at 2,2 because we set the first grid %to 0,0 so everything is off by 1 loop     reDraw     Input.KeyDown (key)     if key ('a') then         px -= 1     end if     if key ('d') then         px += 1     end if     if key ('s') then         py -= 1     end if     if key ('w') then         py += 1     end if     Draw.FillBox (px * 10, py * 10, px * 10 + 10, py * 10 + 10, yellow)     View.Update     delay (50) end loop

Collision is very easy. All we need to do is check weather or not the tile in front of us is open or not. Let all the black tiles be walk able, and red tiles are walls. So if the tile in front of the player is 1 (a red tile) we shouldn’t be able to move there. How are we going to do that? Well if ‘w’ is pressed check the tile above the player. If Array(px,py+1) = 0 then we can move. Now just do it for all keys. We get the code:
 Turing: View.Set ("graphics:150;150,offscreenonly") var tiles : array 0 .. 14, 0 .. 14 of int var FileName : string := "map.txt" var FileNo : int open : FileNo, FileName, get for decreasing y : 14 .. 0 % for every y     for x : 0 .. 14 %for every x         get : FileNo, tiles (x, y) %get the tile type at (x,y)     end for end for close (FileNo) procedure reDraw     for x : 0 .. 14         for y : 0 .. 14             if tiles (x, y) = 1 then                 Draw.FillBox (x * 10, y * 10, x * 10 + 10, y * 10 + 10, red) % the +10 is there because each tile is 10 by 10             else                 Draw.FillBox (x * 10, y * 10, x * 10 + 10, y * 10 + 10, black)             end if         end for     end for end reDraw var key : array char of boolean var px, py : int := 1 % we start off at grid 1,1 loop     reDraw     Input.KeyDown (key)     if key ('a') and tiles (px - 1, py) = 0 then         px -= 1     end if     if key ('d') and tiles (px + 1, py) = 0 then         px += 1     end if     if key ('s') and tiles (px, py - 1) = 0 then         py -= 1     end if     if key ('w') and tiles (px, py + 1) = 0 then         py += 1     end if     Draw.FillBox (px * 10, py * 10, px * 10 + 10, py * 10 + 10, yellow)     View.Update     delay (50) end loop

Whoa that was easy!!! And the beauty is that we can make the map larger, and all we need to change in the main program is the size of the array, and how many x’s and y’s there are (i.e. in the for loops in which we read the text file and in the for loops in which we re draw the map). But we have one small problem, this method assumes we go 10 pixels each step (ie. 1 tile a step). What if I want to go less pixels each steps so I get a smoother game play? Well I’ll cover that in the lesson after the next Next: Making a map editor and introducing a new method of detecting which tile you are in.    LaZ3R Posted: Wed Jun 13, 2007 4:53 pm   Post subject: Re: [Tutorial] 2D Tile based games

Excellent Tutorial. Simple to understand (If you understand arrays already that is ).

I haven't bothered trying to make a 2D Tile based game but I guess that's one of the small amount of games I can still try to make. I'm working on a slime soccer game in turing (Circular hit detection is what I'm into now ).

Good job on this turotial.  SNIPERDUDE  Posted: Thu Jun 14, 2007 9:11 am   Post subject: Re: [Tutorial] 2D Tile based games

Yes, it was a great tutorial - simple and easy to understand. I have done 2D mapping games before (although with more advanced collision detection), but now I am into 2D isometric mapping. I have most of it working, I just want to remove some of the lag and fix some other problems (knowing which tile the mouse is on and placing objects accordingly). I hope to get enough of it working soon so I can post some of it . DifinityRJ  Posted: Thu Jun 14, 2007 9:41 am   Post subject: Re: [Tutorial] 2D Tile based games

Awesome Tutorial, thanks codemonkey!  CodeMonkey2000 Posted: Thu Jun 14, 2007 7:37 pm   Post subject: RE:[Tutorial] 2D Tile based games

Thanks for the comments. I'm glad everyone found it easy to understand. I hope I didn't sound too redundant though... Anyway I plan to add more after exams. Dan  Posted: Thu Jun 14, 2007 7:58 pm   Post subject: RE:[Tutorial] 2D Tile based games

Not a bad tutorial at all. This is a simple version of how alot of old 2d rpgs where made.

There is alot that could be added on to this idea like how to add more propterys to a title, and making it so the world (titles move) rather then the char, so you get scorling type effect and do not have to reload the map so much. You could also add more info on how to load the titles from a image rather then just boxs.

Overall tho it is a very good intro to the tile system, and is alot clearer then the current posts we have on it.

+ 100 bits
Computer Science Canada Help with programming in C, C++, Java, PHP, Ruby, Turing, VB and more! CodeMonkey2000 Posted: Mon Jul 02, 2007 2:54 pm   Post subject: Re: [Tutorial] 2D Tile based games

Changing the map size without hassle.

The current way of drawing our map isn’t flexible. We can’t make the map bigger or smaller without changing the code. One possible solution to this is to use a 2 dimensional flexible array. The problem is that turing doesn’t support 2d flexible arrays. Now what? Well we could store all the information from a 2d array into a single dimensional flexible array, after all a 2d array is just another way of organizing information. (Note that the size of the array must be totalX’s times totallY’s. So if our grid was 15 by 15, our array should have 225 elements. We also we need to know the totalX’s and totallY’s beforehand). For simplicities sake, the way we will read our text file exactly how we did before, only instead of doing
 code: get : FileNo, tiles(x,y)
we will do
 code: get : FileNo, tiles( Array(x,y) )
. Where array is a function that takes in x and y (which would normally be used in a 2d array) and converts it into the single dimensional equivalent. How do we do that? There are two formulas we can use. They are: TotalX *currentY+currentX or TotalY *currentX+currentY. Both are practically identical.

In our text file we need to include the totalX’s and totalY’s, so it should be:
15
15
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 1 1 1 0 0 0 0 0 0 1
1 0 0 0 0 0 0 1 0 0 0 0 0 0 1
1 0 0 0 0 0 0 1 1 1 1 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Next we need to enclose the subscripts for the 2d array with Array(), and change the values in our for loop structure. Here’s what our new code looks like:
 Turing: View.Set ("graphics:150;150,offscreenonly") var tiles : flexible array 0 .. 0 of int var FileName : string := "map.txt" var FileNo : int var totalX, totalY : int := 0 fcn Array (x, y : int) : int     result totalX * y + x     %totalY * x + y also works end Array %open the file open : FileNo, FileName, get get : FileNo, totalX %how many X's get : FileNo, totalY %how many Y's new tiles, totalX * totalY - 1 %total number of elements %the -1 is there because we started the aray at 0 for decreasing y : totalY - 1 .. 0 % for every y remember we started the array at 0!     for x : 0 .. totalX - 1 %for every x         get : FileNo, tiles (Array (x, y)) %get the tile type at (x,y) and store it in it's 1d counter-part     end for end for close (FileNo) procedure reDraw     for x : 0 .. totalX - 1         for y : 0 .. totalY - 1             %array is a function and px-1,py are the parameters             if tiles (Array (x, y)) = 1 then                 Draw.FillBox (x * 10, y * 10, x * 10 + 10, y * 10 + 10, red) % the +10 is there because each tile is 10 by 10             else                 Draw.FillBox (x * 10, y * 10, x * 10 + 10, y * 10 + 10, black)             end if         end for     end for end reDraw var key : array char of boolean var px, py : int := 1 % we start off at grid 1,1 loop     reDraw     Input.KeyDown (key)     %array is a function and px-1,py are the parameters     if key ('a') and tiles (Array (px - 1, py)) = 0 then         px -= 1     end if     if key ('d') and tiles (Array (px + 1, py)) = 0 then         px += 1     end if     if key ('s') and tiles (Array (px, py - 1)) = 0 then         py -= 1     end if     if key ('w') and tiles (Array (px, py + 1)) = 0 then         py += 1     end if     Draw.FillBox (px * 10, py * 10, px * 10 + 10, py * 10 + 10, yellow)     View.Update     delay (50) end loop

Scrolling.

Yeah we are in to scrolling! There are many methods of doing this, but the one I’m going to look at is the simplest one. Save this map as map.txt:
30
30
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1
1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1
1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1
1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1
1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Let’s set the boundaries of where we should scroll. If the player’s x is more than (or less than) maxx div 2 move the map left/right depending on the direction. Similarly if the player’s y is more than (or less than) maxy div 2 move the map up/down depending on the direction the player is moving. Let’s make 2 counters that keep track of how much the map has moved (x and y displacements). This number will increase/decrease (depending on the direction that the has player moved in) and will be added to the x and y’s of both the player and tiles when we draw them. Code:

 Turing: View.Set ("graphics:150;150,offscreenonly") var tiles : flexible array 0 .. 0 of int var FileName : string := "map.txt" var FileNo : int var displacementX, displacementY : int := 0 var totalX, totalY : int := 0 fcn Array (x, y : int) : int     result totalX * y + x     %totalY * x + y also works end Array %open the file open : FileNo, FileName, get get : FileNo, totalX %how many X's get : FileNo, totalY %how many Y's new tiles, totalX * totalY - 1 %total number of elements %the -1 is there because we started the aray at 0 for decreasing y : totalY - 1 .. 0 % for every y remember we started the array at 0!     for x : 0 .. totalX - 1 %for every x         get : FileNo, tiles (Array (x, y)) %get the tile type at (x,y) and store it in it's 1d counter-part     end for end for close (FileNo) procedure reDraw     for x : 0 .. totalX - 1         for y : 0 .. totalY - 1             %array is a function and px-1,py are the parameters             if tiles (Array (x, y)) = 1 then                 Draw.FillBox (x * 10 + displacementX, y * 10 + displacementY,                     x * 10 + 10 + displacementX, y * 10 + 10 + displacementY, red)                 % the +10 is there because each tile is 10 by 10             else                 Draw.FillBox (x * 10 + displacementX, y * 10 + displacementY, x * 10 + 10 + displacementX, y * 10 + 10 + displacementY, black)             end if         end for     end for end reDraw var key : array char of boolean var px, py : int := 1 % we start off at grid 1,1 loop     reDraw     Input.KeyDown (key)     %array is a function and px-1,py are the parameters     if key ('a') and tiles (Array (px - 1, py)) = 0 then         px -= 1         %notice how this if is within the if that checks weather or not the player has collided?         %this is convenient since the map should move only if the player moved.         if px * 10 + displacementX <= maxx div 2 then             displacementX += 10         end if     end if     if key ('d') and tiles (Array (px + 1, py)) = 0 then         px += 1         if px * 10 + displacementX >= maxx div 2 then             displacementX -= 10         end if     end if     if key ('s') and tiles (Array (px, py - 1)) = 0 then         py -= 1         if py * 10 + displacementY <= maxy div 2 then             displacementY += 10         end if     end if     if key ('w') and tiles (Array (px, py + 1)) = 0 then         py += 1         if py * 10 + displacementY >= maxy div 2 then             displacementY -= 10         end if     end if     Draw.FillBox (px * 10 + displacementX, py * 10 + displacementY, px * 10 + 10 + displacementX, py * 10 + 10 + displacementY, yellow)     View.Update     delay (50) end loop

This works great, but the map should snap back to the screen when it goes off screen. What we want to happen is:

If the displacementX plus the location (relative to our screen) of the very last X tile is less than maxx then the displacementX should equal maxx - totalX * 10.
Or else if the displacementX plus the location (relative to our screen) of the very first X tile is more than 0 then the displacementX should equal 0 - 0 *10.

And we repeat the same thing for displacementY. Code:
 Turing: View.Set ("graphics:150;150,offscreenonly") var tiles : flexible array 0 .. 0 of int var FileName : string := "map.txt" var FileNo : int var displacementX, displacementY : int := 0 var totalX, totalY : int := 0 fcn Array (x, y : int) : int     %make sure that going offscreen won't crash the game     if x >= 0 and x < totalX and y >= 0 and y < totalY then         result totalX * y + x %totalY * x + y also works     else         for k : 0 .. upper (tiles)             if tiles (k) = 1 then                 result k             end if         end for     end if end Array %open the file open : FileNo, FileName, get get : FileNo, totalX %how many X's get : FileNo, totalY %how many Y's new tiles, totalX * totalY - 1 %total number of elements %the -1 is there because we started the aray at 0 for decreasing y : totalY - 1 .. 0 % for every y remember we started the array at 0!     for x : 0 .. totalX - 1 %for every x         get : FileNo, tiles (Array (x, y)) %get the tile type at (x,y) and store it in it's 1d counter-part     end for end for close (FileNo) procedure reDraw     for x : 0 .. totalX - 1         for y : 0 .. totalY - 1             %array is a function and px-1,py are the parameters             if tiles (Array (x, y)) = 1 then                 Draw.FillBox (x * 10 + displacementX, y * 10 + displacementY,                     x * 10 + 10 + displacementX, y * 10 + 10 + displacementY, red)                 % the +10 is there because each tile is 10 by 10             else                 Draw.FillBox (x * 10 + displacementX, y * 10 + displacementY, x * 10 + 10 + displacementX, y * 10 + 10 + displacementY, black)             end if         end for     end for end reDraw var key : array char of boolean var px, py : int := 1 % we start off at grid 1,1 proc snapGrid     %if the grid is too far left     if (displacementX + totalX * 10) < maxx then         displacementX := maxx - totalX * 10 %we use 10 because that is the size of each tile         %if the grid is too far right     elsif (displacementX + 0 * 10) > 0 then         displacementX := 0 - 0 * 10 %or just zero     end if     %if the map is too far down, move it up     if (displacementY + totalY * 10) < maxy then         displacementY := maxy - totalY * 10         % if the map is too far up move it down     elsif (displacementY + 0 * 10) > 0 then         displacementY := 0 - 0 * 10 %or just zero     end if end snapGrid loop     reDraw     Input.KeyDown (key)     %array is a function and px-1,py are the parameters     if key ('a') and tiles (Array (px - 1, py)) = 0 then         px -= 1         %notice how this if is within the if that checks weather or not the player has collided?         %this is convenient since the map should move only if the player moved.         if px * 10 + displacementX <= maxx div 2 then             displacementX += 10         end if     end if     if key ('d') and tiles (Array (px + 1, py)) = 0 then         px += 1         if px * 10 + displacementX >= maxx div 2 then             displacementX -= 10         end if     end if     if key ('s') and tiles (Array (px, py - 1)) = 0 then         py -= 1         if py * 10 + displacementY <= maxy div 2 then             displacementY += 10         end if     end if     if key ('w') and tiles (Array (px, py + 1)) = 0 then         py += 1         if py * 10 + displacementY >= maxy div 2 then             displacementY -= 10         end if     end if     snapGrid     Draw.FillBox (px * 10 + displacementX, py * 10 + displacementY, px * 10 + 10 + displacementX, py * 10 + 10 + displacementY, yellow)     View.Update     delay (50) end loop

Editing a map.
To edit a map we could change the text in the text map. But that is too tedious. Why not make program that can enable us to edit the map with ease? First we should give the user choice to create a new map, or to load an old one. If the user chooses to start a new map we should ask for the dimensions of the map and then set all the tiles to 0 (so we don’t get any “variable has to value error”). If they choose to load, we should load the map how we normally do. We can copy and paste a bunch of things from the main game onto our map editor (eg. The redraw procedure).
Now if the user left clicks we should place a red tile in the tile the mouse is on (tiles in Array(mouseX, mouseY) now equals 1). If the user right clicks place a black tile in the tile the mouse is on on (tiles in Array(mouseX, mouseY) now equals 0). We can figure out what tile the mouse is on with the formula: mx div sizeOfTile (which is 10), my div sizeOfTile (which is 10). This method of detecting what tile we are on can be used for collision. It is very accurate but it can be slow. There is a trick to using it though. (Note: if we know what tile we are on, but want to find out its position on screen we do: x*10 and y*10). Moving along, if the user presses ‘q’ we should quit and save. The format to save is exactly the same as how we load, but we replace get with put. Code [Note: I added the ability to tell weather or not the mouse is within the grid. Don’t let it confuse you.]:

 Turing: var tiles : flexible array 0 .. 0 of int var answer : string var totalX, totalY : int var FileName : string := "map.txt" var FileNo : int fcn Array (x, y : int) : int     result totalX * y + x     %totalY * x + y also works end Array put "Would you like to load or create a new map? (load/new)" get answer if answer = "new" then     put "How many tiles across and down?"     get totalX, totalY     new tiles, totalX * totalY - 1 %total number of elements     for x : 0 .. totalX * totalY - 1         tiles (x) := 0     end for elsif answer = "load" then     %open the file     open : FileNo, FileName, get     get : FileNo, totalX %how many X's     get : FileNo, totalY %how many Y's     new tiles, totalX * totalY - 1 %total number of elements     %the -1 is there because we started the aray at 0     for decreasing y : totalY - 1 .. 0 % for every y remember we started the array at 0!         for x : 0 .. totalX - 1 %for every x             get : FileNo, tiles (Array (x, y)) %get the tile type at (x,y) and store it in it's 1d counter-part         end for     end for     close (FileNo) else     put "Invalid input, now crashing"     delay (1000)     quit end if procedure reDraw     for x : 0 .. totalX - 1         for y : 0 .. totalY - 1             %array is a function and px-1,py are the parameters             if tiles (Array (x, y)) = 1 then                 Draw.FillBox (x * 10, y * 10, x * 10 + 10, y * 10 + 10, red)                 % the +10 is there because each tile is 10 by 10             else                 Draw.FillBox (x * 10, y * 10, x * 10 + 10, y * 10 + 10, black)             end if         end for     end for end reDraw Mouse.ButtonChoose ("multibutton")%check the turing help section if you don't know what this does cls var mx, my, mb, left, middle, right : int var key : array char of boolean View.Set ("offscreenonly") loop     Mouse.Where (mx, my, mb)     %how this work can be found in the turing help section under 'Mouse.ButtonChoose'     left := mb mod 10     middle := (mb - left) mod 100     right := mb - middle - left     %move the map around     Input.KeyDown (key)     reDraw     %make sure that the mouse is within the grid     %remember mx div 10,my div 10 tells us what grid we are on     % the lower bound of the grid is 0 and the upper bound is totalX/Y     if mx div 10 >= 0 and mx div 10 < totalX and my div 10 >= 0 and my div 10 < totalY then         %places red tiles         if left = 1 then             tiles (Array (mx div 10, my div 10)) := 1         end if         %places black tiles         if right = 100 then             tiles (Array (mx div 10, my div 10)) := 0         end if         %just makes it clearer which tile you are on         Draw.Box (mx div 10 * 10, my div 10 * 10, mx div 10 * 10 + 10, my div 10 * 10 + 10, white)     end if     View.Update     exit when key ('q') end loop open : FileNo, FileName, put put : FileNo, totalX     %how many X's put : FileNo, totalY     %how many Y's %new tiles, totalX * totalY - 1     %total number of elements %the -1 is there because we started the aray at 0 for decreasing y : totalY - 1 .. 0     % for every y remember we started the array at 0!     for x : 0 .. totalX - 1     %for every x         put : FileNo, tiles (Array (x, y))     %get the tile type at (x,y) and store it in it's 1d counter-part     end for end for close (FileNo)

Now we can just start playing in the new map right away, and not worry about changing the main code.

If you open the text file you will see that you now have a number per line. We don’t need to worry about organizing the text file any more.

Next: I will show you how to add property to tiles, how to only draw the tiles that are on screen, change tiles during game play, how to use pictures rather than the Draw.Box procedure, and finally add enemies. I will probably use pacman as an example as it’s the simplest to understand. skaarj Posted: Sun Jul 08, 2007 10:00 am   Post subject: Re: [Tutorial] 2D Tile based games

Hi,

I'm writing a RPG game (C++/OpenGL/OpenAL) and this map editor would be very useful, can i find binary for this tutorial? somewhere.    CodeMonkey2000 Posted: Sun Jul 08, 2007 10:36 am   Post subject: RE:[Tutorial] 2D Tile based games

You can't find binaries for turing. If you understand the logic you probably could program your own map editor.

Oh and how experienced are you with openGL? If you are new, then SDL is probably a better alternative. It's simple (hence the name Simple Direct-Media Layer). I found openGl to be very confusing and frustrating. skaarj Posted: Sun Jul 08, 2007 11:19 am   Post subject: Re: [Tutorial] 2D Tile based games

Im not new in OpenGL, just look at this:

http://img412.imageshack.us/my.php?image=screenav2.png

I'll try to write map editor. Sandwich Posted: Mon Jun 16, 2008 9:30 pm   Post subject: Re: [Tutorial] 2D Tile based games

Thank you very much for this tutorial. Aziz  Posted: Tue Jun 17, 2008 7:43 am   Post subject: RE:[Tutorial] 2D Tile based games

CodeMonkey, I suggest you pic a better image host next time. I didn't know that map would translate into jailbait. CodeMonkey2000 Posted: Tue Jun 17, 2008 11:02 pm   Post subject: RE:[Tutorial] 2D Tile based games

Wow I just noticed that.  Posted: Fri Jan 06, 2012 3:52 pm   Post subject: Re: [Tutorial] 2D Tile based games

it doesnt seem to be working for me, it highlights "get" and says "invalid integer input"... whats wrong?

 Turing: var rural, town : array 0 .. 39, 0 .. 29 of int var rfile, tfile, mfile : int var rname, tname, mname : string rname := "rural.txt" tname := "town.txt" mname := "map.txt" open : rfile, rname, get for decreasing y : 29 - 1 .. 0     for x : 0 .. 39 - 1         get : rfile, rural (x, y)     end for end for close (rfile) mirhagk Posted: Fri Jan 06, 2012 3:56 pm   Post subject: RE:[Tutorial] 2D Tile based games

whatever it's getting isn't a integer (or possibly it's too large) it means your file is formatted incorrectly. Display posts from previous: All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First         Page 1 of 2  [ 21 Posts ]
Goto page 1, 2  Next
 Jump to:  Select a forum  CompSci.ca ------------ - Network News - General Discussion     General Forums   -----------------   - Hello World   - Featured Poll   - Contests     Contest Forums   -----------------   - DWITE   - [FP] Contest 2006/2008   - [FP] 2005/2006 Archive   - [FP] 2004/2005 Archive   - Off Topic     Lounges   ---------   - User Lounge   - VIP Lounge     Programming -------------- - General Programming     General Programming Forums   --------------------------------   - Functional Programming   - Logical Programming   - C     C   --   - C Help   - C Tutorials   - C Submissions   - C++     C++   ----   - C++ Help   - C++ Tutorials   - C++ Submissions   - Java     Java   -----   - Java Help   - Java Tutorials   - Java Submissions   - Ruby     Ruby   -----   - Ruby Help   - Ruby Tutorials   - Ruby Submissions   - Turing     Turing   --------   - Turing Help   - Turing Tutorials   - Turing Submissions   - PHP     PHP   ----   - PHP Help   - PHP Tutorials   - PHP Submissions   - Python     Python   --------   - Python Help   - Python Tutorials   - Python Submissions   - Visual Basic and Other Basics     VB   ---   - Visual Basic Help   - Visual Basic Tutorials   - Visual Basic Submissions     Education ----------- - Student Life   Graphics and Design ----------------------- - Web Design     Web Design Forums   ---------------------   - (X)HTML Help   - (X)HTML Tutorials   - Flash MX Help   - Flash MX Tutorials   - Graphics     Graphics Forums   ------------------   - Photoshop Tutorials   - The Showroom   - 2D Graphics   - 3D Graphics     Teams ------ - dTeam Public

 Style: Appalachia blueSilver eMJay subAppalachia subBlue subCanvas subEmjay subGrey subSilver subVereor Search: