Code archives/Graphics/2D Tile map engine
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
I starte a tile map game a while ago but never finished but the engine works to my satisfaction. I decided to post it for anybody to use. it is only two dimensional one layer. it works with any valid graphics mode it can be minimu 10 X 10 tiles to any size limitd by hardware. I really like for this to be open source so if anyone wants to make changes or inprovements to it, I would appreciate if any changes are posted here for everyone to use and take advantage of. I will be modifying it as I find changes usefll. I really want to add layers to it but I will add them slowly over time as I don't really have to much time to work on it. to change tile size for the whole game all you need to do is to change TILEWIDTH and TILEHEIGHT to whatever tile size is to be used. to use just one standard tile for the wall tile 0(zero)just comment out "CompileMaze(map.maze)" in the create function. link to a mac executable included source: http://www.mediafire.com/?krc1igh4v1xabai [/update] name "maze.bmx" | |||||
' map constants Const MINTILESA :Int = 10 Const MINTILESD :Int = 10 Const TILEWIDTH :Float = 32.0 Const TILEHEIGHT :Float = 32.0 Const MIDTILEWIDTH :Float = TILEWIDTH/2 Const MIDTILEHEIGHT :Float = TILEHEIGHT/2 'type of tiles Const WALKABLE :Int = 0 Const UNWALKABLE :Int = 1 ' type of grass Const GRASSTYPE :Int = 0 ' type of wall Const WALLTYPE :Int = 1 ' map controls Const MAP_LEFT :Int = KEY_LEFT Const MAP_RIGHT :Int = KEY_RIGHT Const MAP_UP :Int = KEY_UP Const MAP_DOWN :Int = KEY_DOWN Const SPEED_X :Float = 6.0 Const SPEED_Y :Float = 6.0 'Type of tiles Type set Field a:Int 'Walkable unwalkable Field b:Int 'Type of tile (ex: wall,grass) Field c:Int 'type of graphic tile to display (ea: if wall which wall) End Type Type TMap Field x :Float,.. y :Float Field speedx :Float,.. speedy :Float Field maxx :Float,.. maxy :Float Field bitx :Float,.. bity :Float Field tilesAcross :Float,.. tilesDown :Float Field width :Float,.. height :Float Field viewwidth :Float,.. ViewHeight :Float Field Midviewwidth :Float,.. Midviewheight :Float Field Offsetx :Float,.. Offsety :Float Field windowwidth :Float,.. windowheight :Float Field tilewidth :Float,.. tileheight :Float Field maze :set[][] Field tilesinviewacross :Float,.. tilesinviewdown :Float Field screen_width :Float,.. screen_height :Float Field wall :TImage Field tile :TImage[8] Field windowshiftx :Float Field windowshifty :Float Field Offbitx :Float,.. Offbity :Float Field clearscreen :Int 'sets up the maze including tiles and format '************************************************************************************ ' * ' creates a map any size * ' * ' mw = mapwidth in tiles * ' mh = mapheight in tiles * ' * ' MINTILESA = controlls the minimum number of tiles across * ' MINTILESD = controlls the minimum number of tiles down * ' * '************************************************************************************ Function Create:TMap(mw:Float=MINTILESA,mh:Float=MINTILESD) 'mapwidth,mapheight,tilewidth,tileheight If mw< MINTILESA Then mw=MINTILESA If mh< MINTILESD Then mh=MINTILESD Local map:Tmap = New TMap map.screen_width = GraphicsWidth() map.screen_height = GraphicsHeight() map.wall=LoadAnimImage("walltiles.png",TILEWIDTH,TILEHEIGHT,0,16,FILTEREDIMAGE|DYNAMICIMAGE) map.tile[0] =LoadImage("grass.png", FILTEREDIMAGE|DYNAMICIMAGE) map.tilesAcross = mw map.tilesdown = mh map.windowwidth=GraphicsWidth() map.windowheight=GraphicsHeight() map.tilewidth = TILEWIDTH map.tileheight = TILEHEIGHT map.width = mw * TILEWIDTH 'multiply map width by bitmap width for map width in pixels map.height= mh * TILEHEIGHT 'multiply map height by bitmap height for map height in pixels centermap(map) map.maxx = map.width-map.windowwidth map.maxy = map.height-map.windowheight map.midviewwidth = (map.Tilesinviewacross / 2)*TILEWIDTH map.midviewheight = (map.Tilesinviewdown/ 2)*TILEHEIGHT If map.maxx<0 map.maxx = 0 If map.maxy<0 map.maxy = 0 map.speedx = SPEED_X map.speedy = SPEED_Y 'create map array map.maze = map.maze[..mw] For Local h:Int = 0 To mw-1 map.maze[h]=map.maze[h][..mh] Next For Local down:Int = 0 To mh-1 For Local across:Int = 0 To mw-1 'places a wall edge around maze map.maze[across][down]= New set If across = 0 Or across = (mw-1) Or down=0 Or down = (mh-1) map.maze[across][down].a=UNWAlKABLE map.maze[across][down].b=WALLTYPE Else map.maze[across][down].a=WALKABLE map.maze[across][down].b=GRASSTYPE EndIf Next Next 'places wall tiles randomly on the maze excluding maze edges Local rx:Int Local ry:Int For Local n:Int = 1 To mw*mh Step 5 ' step determine s more or less the density rx = Rnd(1,mw-2) ry = Rnd(1,mh-2) map.maze[rx][ry].a = UNWALKABLE map.maze[rx][ry].b = WALLTYPE Next CompileMaze(map.maze) Return map End Function '************************************************************************************ ' * ' moves Map Window using the mouse when the mouse is less then * ' five pixels from edges of screen * ' * '************************************************************************************ 'moves the maze when mouse is at edges of screen Method MouseMapControl(controlled:Int=False) If Not controlled Then If width > Windowwidth Then If MouseX() >(screen_width -5) MoveMapX(speedx) ElseIf MouseX() < 5 MoveMapX(-speedx) EndIf EndIf If height > windowheight Then If MouseY() > (screen_height - 5) MoveMapY(speedy) ElseIf MouseY() < 5 MoveMapY(-speedy) EndIf EndIf EndIf bitx = x Mod tilewidth ' division remainder determins the number of pixels bity = y Mod tileheight ' to move per tile before moving to the next tile. offbitx = offsetx-bitx offbity = offsety-bity EndMethod '************************************************************************************ ' * ' use keyboard to move window in preset steps * ' * '************************************************************************************ Method KeyControl(controlled:Int=False) If Not controlled Then If width > Windowwidth Then If KeyDown(MAP_RIGHT) MoveMapX(speedx) ElseIf KeyDown(MAP_LEFT) MoveMapX(-speedx) EndIf EndIf If height > windowheight Then If KeyDown(MAP_DOWN) MoveMapY(speedy) ElseIf KeyDown(MAP_UP) MoveMapY(-speedy) EndIf EndIf EndIf bitx = x Mod tilewidth ' division remainder determins the number of pixels bity = y Mod tileheight ' to move per tile before moving to the next tile. offbitx = offsetx-bitx offbity = offsety-bity EndMethod '************************************************************************************ ' * ' returns a valid random walkable x,y position * ' * '************************************************************************************ Method Random(rx:Float Var,ry:Float Var) Local x:Int Local y:Int Repeat x:Int = Rand(1,TilesAcross-1) y:Int = Rand(1,TilesDown-1 ) Until maze[x][y].a = WALKABLE rx = x*TILEWIDTH + MIDTILEWIDTH ry = y*TILEHEIGHT + MIDTILEHEIGHT End Method '************************************************************************************ ' * ' moves map window to a valid x,y positon * ' * '************************************************************************************ Method XYControl(x:Float Var,y:Float Var) If y > Maxy Then Self.y = maxy ElseIf y < 0 Then Self.y = 0 Else Self.y = y EndIf If x > maxx Then Self.x = maxx ElseIf x < 0 Then Self.x = 0 Else Self.x = x EndIf x = Self.x y = Self.y bitx = Self.x Mod tilewidth ' division remainder determins the number of pixels bity = Self.y Mod tileheight ' to move per tile before moving to the next tile. offbitx = offsetx-bitx offbity = offsety-bity End Method '************************************************************************************ ' * ' moves map position x,y to center of screen if possible * ' * '************************************************************************************ Method Centerto(x:Float,y:Float,dx:Float,dy:Float,speed:Float) Local sx:Float,.. 'viewwidth center relative to map. sy:Float Local fx:Float,.. fy:Float If Not speed If dx = 0 Then dx = SPEED_X If dy = 0 Then dy = SPEED_Y EndIf dx = Abs(dx) dy = Abs(dy) fy:Float = y+dy sx:Float = Self.x+midviewwidth If x < sx Then Self.x :- dx sx :- dx If x > sx Then Self.x = x-midviewwidth ElseIf x > sx Then Self.x :+ dx sx :+ dx If x < sx Then Self.x = x-midviewwidth EndIf If Self.x > maxx Then Self.x = Maxx If Self.x < 0 Then Self.x = 0 bitx = Self.x Mod tilewidth offbitx = offsetx-bitx sy:Float = offsety+Self.y+midviewheight If y < sy Then Self.y:-dy sy:-dy If y > sy Then Self.y = y-midviewheight ElseIf y > sy Then Self.y :+ dy sy:+dy If y < sy Then Self.y = y-midviewheight EndIf If Self.y > maxy Then Self.y = Maxy If Self.y < 0 Then Self.y = 0 bity = Self.y Mod tileheight offbity = offsety-bity End Method '************************************************************************************ ' * ' returns x,y position relative to window and screen position * ' * '************************************************************************************ Method GetXY(x:Float Var,y:Float Var) x = offsetx-Self.x y = offsety-Self.y End Method '************************************************************************************ ' * ' sets map moving speed * ' * '************************************************************************************ Method setspeed(sx:Float=SPEED_X,sy:Float=SPEED_Y) speedx = sx speedy = sy End Method '************************************************************************************ ' * ' move map X direction a specified amount + or - * ' * '************************************************************************************ Method MoveMapX(x:Float = SPEED_X) Self.x :+x If Self.x < 0 Self.x = 0 ElseIf Self.x > maxx Self.x = maxx EndIf End Method '************************************************************************************ ' * ' clears screen only when map either is smaller then screen size * ' * '************************************************************************************ Method windowclear() If clearscreen Then Cls() End Method '************************************************************************************ ' * ' moves map Y direction a specified amount + or - * ' * '************************************************************************************ Method MoveMapY(y:Float = SPEED_Y) Self.y :+ y If Self.y < 0 Self.y = 0 ElseIf Self.y > maxy Self.y = maxy EndIf End Method '************************************************************************************ ' * ' This Function checks for collition of objects with map tiles. * ' * ' x,y is the position to check collition from * ' * ' sw1,sh1 --> is x,y of point 1 from the center of the object * ' sw2,sh2 --> is x,y of point 2 from the center of the object * ' * ' as in a car collition with an object, if the car is traveling in the * ' forward direction, the car front or two front points are the first * ' two points affected by the collition. * ' * ' * '************************************************************************************ Method RectCollided:Int(x:Float,y:Float,sw1:Float,sh1:Float,sw2:Float,sh2:Float) Local collided:Int = True If maze[(x+sw1)/TILEWIDTH][(y+sh1)/TILEHEIGHT].b=0 And .. maze[(x+sw2)/TILEWIDTH][(y+sh2)/TILEHEIGHT].b=0 Then 'moving along the x axis If x < (width-HALFBITMAPWIDTH) And x > 0 Then collided = False 'move along the y axis If y < (height-HALFBITMAPHEIGHT) And y > 0 Then collided = False EndIf Return collided End Method '************************************************************************************ ' * ' moves the display window left, right, up or down * ' usefull for when window(or map) is smaller then display are * ' * '************************************************************************************ Method SetMapOffset(x:Float,y:Float) If width < screen_width If x > viewwidth offsetx = viewwidth ElseIf x <-viewwidth offsetx = -viewwidth Else offsetx = x EndIf EndIf If height < screen_height If y > viewheight offsety = viewheight ElseIf y < -viewheight offsety = -viewheight Else offsety = y EndIf EndIf End Method '************************************************************************************ ' * ' Displays a rotated image to its corresponding map position * ' * '************************************************************************************ Method DrawImageToMap(image:timage,x:Float,y:Float,angle:Float,index:Int = 0) Local thisx:Float, thisY:Float Local posx:Float, posy:Float GetXY(thisx,thisy) thisx:+x thisy:+y posx= thisx+image.width posy= thisy+image.height SetRotation angle If (posx >= 0) If (thisx < SCREEN_WIDTH) If (posy >= 0) If (thisy < SCREEN_HEIGHT) DrawImage image,thisx,thisy,index EndIf EndIf EndIf EndIf End Method '************************************************************************************ ' * ' Displays visible map area * ' * '************************************************************************************ Method display() Local nx :Int,.. ny :Int Local tilex :Float,.. tiley :Float Local tx :Int = x/TileWidth,.. ty :Int = y/TileHeight Local tpx :Float,.. tpy :Float SetColor 255,255,255 SetRotation(0) For ny = 0 To tilesinviewdown tiley = ny+ty tpy = offbity+ny*TileHeight For nx = 0 To tilesinviewacross tilex = nx+tx If tilex < tilesacross And tiley < tilesdown Local shape:Int = maze[tilex][tiley].b Select shape Case WALLTYPE DrawImage(wall,offbitx+nx*TileWidth,tpy,maze[tilex][tiley].c) Case GRASSTYPE DrawImage(tile[maze[tilex][tiley].c],offbitx+nx*TileWidth,tpy) End Select EndIf Next Next End Method End Type '************************************************************************************* ' * ' Compiles tiles adjacent To each other To uniform patterns * ' for use with "mazetiles.png" * ' may be used with different tile set but must fallow pattern: * ' codes generated is binary * ' (+) -> connects To (*) tile * ' (*) -> represents the actual tile * ' * ' tile 0: #0000 * tile 1: #0001 + * ' * * ' * ' tile 2: #0010 *+ tile 3: #0011 + * ' *+ * ' * ' tile 4: #0100 * tile 5: #0101 + * ' + * * ' * ' tile 6: #0110 *+ tile 7: #0111 + * ' + *+ * ' * ' tile 8: #1000 +* tile 9: #1001 + * ' +* * ' * ' tile 10: #1010 +*+ tile 11: #1011 + * ' +*+ * ' * ' tile 12: #1100 +* tile 13: #1101 + * ' + +* * ' + * ' * ' tile 14: #1110 +*+ tile 15: #1111 + * ' +*+ * ' + * ' * '************************************************************************************* Function CompileMaze(maze:set[][] Var) Local a:Int,c:Int For a:Int = 0 To maze.length-1 'tiles across Local d:Int For d:Int = 0 To maze[a].length-1 'tiles down If maze[a][d].a = WALLTYPE If a >0 'tile away from left edge If a < maze.length-1 ' tile away from right edge If d >0 'away from top edge If d< maze[a].length-1 ' tile out of range of right edge 'tile is away from bottom edge maze[a][d].c = (maze[a-1][d].a Shl 3).. ' * |(maze[a][d+1].a Shl 2).. '*+* |(maze[a+1][d].a Shl 1).. ' * | maze[a][d-1].a Else 'tile on bottom edge(not corner) maze[a][d].c = (maze[a-1][d].a Shl 3).. ' * |(maze[a+1][d].a Shl 1).. '*+* |maze[a][d-1].a ' EndIf Else ' is on top edge(not corner) maze[a][d].c = (maze[a-1][d].a Shl 3).. ' |(maze[a][d+1].a Shl 2).. '*+* |(maze[a+1][d].a Shl 1) ' * EndIf Else If d > 0 'tile is on right edge If d< maze[a].length-1 'tile is on right edge(not corner) maze[a][d].c = (maze[a-1][d].a Shl 3).. ' * |(maze[a][d+1].a Shl 2).. '*+ |maze[a][d-1].a ' * Else 'tile is on top left corner maze[a][d].c = (maze[a-1][d].a Shl 3).. '+* |maze[a][d-1].a '* EndIf Else 'tile is on bottom left corner maze[a][d].c = (maze[a-1][d].a Shl 3).. '* |(maze[a][d+1].a Shl 2).. '+* EndIf EndIf Else If d>0 'tile not on top left cornertile If d< maze[a].length-1 'tile on edge(not corner) maze[a][d].c = (maze[a][d+1].a Shl 2).. ' * |(maze[a+1][d].a Shl 1).. ' +* |maze[a][d-1].a ' * Else 'tile on bottom corner maze[a][d].c = (maze[a+1][d].a Shl 1).. ' * |maze[a][d-1].a ' +* EndIf Else 'tile on top corner maze[a][d].c = (maze[a][d+1].a Shl 2).. ' +* |(maze[a+1][d].a Shl 1) ' * EndIf EndIf EndIf If maze[a][d].c = 0 c=(c+1) Mod 7 If c maze[a][d].b= 0 maze[a][d].a= 0 EndIf EndIf Next Next For a:Int = 0 To maze.length-1 For Local d:Int = 0 To maze[a].length-1 'If maze[a][d].a = 0 maze[a][d].c = 0 Next Next End Function '************************************************************************************ ' * ' centers window to center of map if map is bigger than window * ' centers map to center of screen if map with and/or height is * ' smaller than screen * ' * '************************************************************************************ Function Centermap(map:tmap) map.clearscreen = False 'centers maze to screen horizontally if smalller than screen width If map.width < map.windowwidth Then map.viewwidth = map.width map.offsetx = (map.windowwidth-map.width) / 2 map.clearscreen = True Else ' center map horizontally to view area (absolute) map.viewwidth = map.windowwidth map.offsetx = 0 map.x = (map.width - map.windowwidth)/2 EndIf 'centers maze to screen vertically if smaller than screen height If map.height < map.windowheight Then map.ViewHeight = map.height map.Offsety = (map.windowheight-map.height) / 2 map.clearscreen = True Else 'center map vertically to view area (absolute) map.ViewHeight = map.windowheight map.Offsety = 0 map.y = (map.height - map.windowheight)/2 EndIf map.tilesinviewacross = Ceil(Float(map.viewwidth)/map.tilewidth) map.tilesinviewdown = Ceil(Float(map.viewheight) /map.tileheight) End Function |
Comments
| ||
test with this: and this: "tank.bmx" use this images: "grass.png" "walltiles.png" "tankimg.png |
Code Archives Forum