2D Overhead scrolling maze
BlitzMax Forums/BlitzMax Beginners Area/2D Overhead scrolling maze
| ||
I'm sure that someone has done this before, nevertheless: I am looking for a sample of a 2D overhead scroller, with a map that includes "walls" for collisions. The controls don't matter, I intend to use a car sort of control scheme. I'm thinking something similar to the old 2D GTA games (GTA1 and GTA2). Has anyone done/seen anything like that? |
| ||
this may be a bit more complicated than you wanted but: map editor http://www.scottshaver2000.com/forum/viewtopic.php?t=140 tilemap module http://www.scottshaver2000.com/forum/viewtopic.php?t=135 there are some samples in the mapeditor zip file that cover what you want |
| ||
There's always my example that can be found on the Code section of my Blitz site (link in my sig). Not quite as complicated as the one above, but the walls are generated randomly in my example. The map is simply stored in an array, as it pretty much would be any tilemap, so can be populated by any means - DefData, load from file, etc. |
| ||
I'm sure someone attempted to do a GTA clone in Blitz Basic, but I am not sure what ever happened to it. |
| ||
Jazzie, I looked at your site, I couldn't find the program to which you were referring. Mind telling me which title, or providing a link? |
| ||
Scott Shaver, Loved what you are doing but unfortunately I was unable to compile and run any of your examples... I extracted each example into it's own directory, are they dependent upon files in other directories? Should I just unzip everything into one directory? |
| ||
I'm still taking responses to this question... This should be a sticky thing, like scrolling 101... I doubt anyone buying BlitzMax DOESN'T want scrolling and collisions. |
| ||
That's great Zamfir. I look forward to reading it when you've finished. What have you got so far? |
| ||
You need to make sure you have my tilemap module to compile the examples |
| ||
Ah! |
| ||
On your forum, you have this: "The tilemaps module had to be updated due to a change in BlitzMax handling of bigendian machines." ... I'm not seeing the tilemap module. |
| ||
the second link in my first post |
| ||
Scott, fter doing the MinGW thing and rebuilding all modules, your stuff worked like a charm. Great stuff, and I'll probably use it. Another question though... If anyone's seen on here the demo where it takes a very large PNG or some other bitmap and breaks it up into smaller pieces so any video card can handle it... Would it be possible to make a map using one large image for the obstacles and transparent alpha for the background and test collisions against that? That might be a way to break out of the grid format... Just a thought. Thanks! |
| ||
the system works by having all of the tiles in a single image, you could modify the code but it would be a pain. |
| ||
note to tohers, if there is a reference to igl.mod in the demos remove it. |
| ||
Scott, is your collision all rectangular? Also, what about rotating the background around the player? |
| ||
There is no rotation, the tilemap module was intended for platformer type games. As for the collision stuff that's really up to you, there isn't any built in collision handling as you can see in the examples, I implmented the wall collisions in the easiest manner possible, full tile collision. If you use some non-rectangular tiles (via transparency) you could implement the collisions in your own way. |
| ||
Jazzie, I looked at your site, I couldn't find the program to which you were referring. Mind telling me which title, or providing a link? You may have clicked on the wrong link in my sig, as there are two sites there. My SOS Software site where all my games are, and the Blitz site, which is my programming site (code examples, current projects, etc). The page with all my code examples is here: http://www.blitz.sos-software.co.uk/code.htm And the download for the tilemap example is here: http://www.blitz.sos-software.co.uk/downloads/TileDemoMax.zip My example also demonstrates keeping the player central on-screen whenever possible. If the player is near the edge of the level then it's the player that moves and not the level. |
| ||
@JazzieB, very nice tile map demo. |
| ||
Jazzie, I concur, very well done! |
| ||
Jazzie, I like your engine, I've tried using fredborg's viewport rotation function (found here: http://www.blitzbasic.com/Community/posts.php?topic=42799#478997 but it only works for a second when "A" is pressed. The code is below, I'm not sure how to put it in a code window yet: Framework brl.glmax2d Import brl.random Import brl.pngloader SetGraphicsDriver GLMax2DDriver() ' ----- CONSTANTS ----- Const scrWidth=640,scrHeight=480 ' screen resolution Const scrDepth=32 ' bitdept, *** change as required *** Const scrHertz=75 ' refresh rate (this is nice and smooth, but change if required). Const tileWidth=32,tileHeight=32 ' dimension of tiles Const tileMain=1,tileBack=2,tilePlayer=3 ' frame numbers for tiles Const playerSpeed=4 ' pixels for player to move each update Const mapWidth=64,mapHeight=64 ' size of map Const marginX=(scrWidth-tileWidth)/2 ' margin between edge of screen and centre (horizontal) Const marginY=(scrHeight-tileHeight)/2 ' margin between edge of screen and centre (vertical) ' ----- GLOBALS ----- SeedRnd MilliSecs() Global ms#,fps#,msTot#,msCnt#,msAvg# ' ----- TYPE / METHOD DECLARATIONS ----- Type player Field mapX,mapY ' map block co-ordinates (top left if more than one square occupied) Field x,y ' pixel co-ordinates Function Create:player() ' create a player with the starting x and y map co-ordinates Local sx,sy p:player=New player ' create player Repeat sx=Rand(1,mapWidth-1) ' choose random x position sy=Rand(1,mapHeight-1) ' choose random y position Until lev.Read(sx,sy)=0 p.mapX=sx ' set starting x (map co-ordinate) p.mapY=sy ' set starting y (map co-ordinate) p.x=sx*tileWidth ' set x position (pixels) p.y=sy*tileHeight ' set y position (pixels) Return p End Function Method Update() Local dx=(KeyDown(key_right)-KeyDown(key_left))*playerSpeed ' get player input for the x direction Local dy=(KeyDown(key_down)-KeyDown(key_up))*playerSpeed ' get player input for the y direction If dy Then ' check vertical movement If MapCollision(x+dx,y+dy) Then ' check if we can move If dx Then ' can't move, but might be trying to move diagonally If MapCollision(x,y+dy) Then ' can we move straight up or down? dy=0 ' still can't move, so don't allow EndIf Else dy=0 ' not trying to move at angle, so don't allow EndIf EndIf EndIf If dx Then ' do the same for horizontal If MapCollision(x+dx,y+dy) Then If dy Then If MapCollision(x+dx,y) Then dx=0 EndIf Else dx=0 EndIf EndIf EndIf x:+dx ' update co-ordinates y:+dy mapX=Floor(x/tileWidth) ' update map position mapY=Floor(y/tileHeight) End Method Method Draw(sx,sy) DrawImage imgTiles,sx,sy,tilePlayer ' draw plater with supplied screen co-ordinates DrawText "World position: "+x+","+y,0,0 DrawText "Map position: "+mapX+","+mapY,0,16 End Method End Type Type level Field map[mapWidth,mapHeight] ' define our map array Method Read(x,y) ' method to read tile at map position Return map[x,y] End Method Method Write(x,y,z) ' method to write to a map position map[x,y]=z End Method Method Draw(ox,oy) ' draw map at specified offset (calculated in RenderGame) SetBlend solidblend ' set blending to solid to erase screen TileImage imgTiles,ox/2,oy/2,tileBack ' draw our parallax background image SetBlend alphablend ' set blending to alpha (not needed, as our tiles are square) ' now go through map and display each tile, but ignore any blank tiles for additional speed For Local y=0 Until mapHeight For Local x=0 Until mapWidth If Read(x,y) Then DrawImage imgTiles,x*tileWidth+ox,y*tileHeight+oy,Read(x,y) Next Next End Method End Type Rem NOTE: The Draw() method above could be optimised further to only loop through those tiles that appear on-screen, but is not really needed at the moment as only those images that appear on-screen will be rendered anyway. Larger and more complicated ganes may benefit if every bit of available processing power is needed. The rendering process of this demo runs at under 1ms on a P4 2.4GHZ with Radeon 9800 Pro. EndRem ' ----- SET UP GRAPHICS ----- Graphics scrWidth,scrHeight,scrDepth,scrHertz ' change graphics mode HideMouse ' hide the mouse pointer Global imgTiles=LoadAnimImage("tiles.png",tileWidth,tileHeight,0,4) ' load the tiles ' ----- INITIALISE MAP ----- Global lev:level=New level ' create a level For Local x=0 Until mapWidth ' draw the top and bottom borders lev.Write(x,0,tileMain) lev.Write(x,mapHeight-1,tileMain) Next For Local y=0 Until mapHeight ' draw the left and right borders lev.Write(0,y,tileMain) lev.Write(mapWidth-1,y,tileMain) Next For Local i=1 To 50 ' draws50 random lines of the wall tile dir=Rand(0,1) x=Rand(1,mapWidth-2) y=Rand(1,mapHeight-2) l=Rand(2,30) For Local j=0 Until l If dir Then lev.Write(x,y,tileMain) x:+1 If x=mapWidth Then Exit Else lev.Write(x,y,tileMain) y:+1 If y=mapHeight Then Exit EndIf Next Next ' ----- INITIALISE PLAYER ----- Global face:player=player.Create() ' create a player ' ----- MAIN LOOP ----- While Not KeyHit(key_escape) face.Update ' get player input and update position RenderGame ' render the screen Wend ' ----- RENDER FUNCTION ----- Function RenderGame() If KeyHit(KEY_A) Sangle:+1 EndIf Local time=MilliSecs() ' used to time how long this takes (before flipping, which waits for vsync) Local t$ ' used to format render time Local lx,ly,px,py ' level offsets and players on-screen position ' check horizontal placement If face.x>=marginX And face.x<=((mapWidth-1)*tileWidth-marginX) Then ' if player within central area px=marginX ' player stays in centre lx=px-face.x ' level offset is player's x minus the margin between the screen edge and player ElseIf face.x<marginX ' check if player near left edge px=face.x ' yes, so on-screen position is same as x lx=0 ' and level offset is it's left edge Else ' otherwise player is near right edge of level px=marginX+marginX-((mapWidth-1)*tileWidth-face.x) ' calculate player's position based on level width lx=-mapWidth*tileWidth+scrWidth ' adjust level's position so that right edge is same as screen edge EndIf ' check for vertical placement - same as above, but on the y axis If face.y>=marginY And face.y<=((mapHeight-1)*tileHeight-marginY) Then py=marginY ly=py-face.y ElseIf face.y<marginY py=face.y ly=0 Else py=marginY+marginY-((mapHeight-1)*tileHeight-face.y) ly=-mapHeight*tileHeight+scrHeight EndIf lev.Draw(lx,ly) ' draw the level at the calculated offset face.Draw(px,py) ' draw the player at the calculated on-screen position ms=MilliSecs()-time ' work out how long it took to draw msTot:+ms ' add to total render time for previous frames msCnt:+1 ' increase count (for average) msAvg=msTot/msCnt ' calculate average render time If msAvg Then fps=1000/msAvg ' make sure we won't get a /0 error and calculate *estimated* FPS t=msAvg ' convert to string for displaying on screen DrawText "Avg render time: "+t[..5]+"ms ("+Int(fps)+" FPS)",0,32 ' write to screen SetViewRotation (Sangle) Flip ' flip the buffers so we can see everything and clear any rubbish from memory. End Function ' ----- CHECKS IF ANY SQUARES AT PIXEL CO-ORDINATES ARE OCCUPIED ----- Function MapCollision(x,y) Local mx,my mx=Floor(x/tileWidth) ' get map position my=Floor(y/tileHeight) If lev.Read(mx,my) Then Return True ' check top left If (x Mod tileWidth) Then If lev.Read(mx+1,my) Then Return True ' check top right If (y Mod tileHeight) Then If lev.Read(mx,my+1) Then ' check bottom left Return True ElseIf (x Mod tileWidth) Then If lev.Read(mx+1,my+1) Then Return True ' check bottom right# EndIf EndIf Return False End Function Rem bbdoc: Set the rotation of the viewport about: SetViewRotation allows you to rotate the entire viewport, so that all drawing is rotated according to the @angle parameter. endrem Function SetViewRotation(angle:Float) Global o_angle:Float glMatrixMode GL_PROJECTION glRotatef angle-o_angle,0,0,1 o_angle=angle glMatrixMode GL_MODELVIEW glLoadIdentity End Function Rem bbdoc: Set the offset of the viewport about: SetViewOffset allows you to offset the entire viewport, so that all drawing is offset according to the @offsetx and @offsety parameters. endrem Function SetViewOffset(offsetx:Float,offsety:Float) Global o_offsetx:Float Global o_offsety:Float glMatrixMode GL_PROJECTION glTranslatef offsetx-o_offsetx,offsety-o_offsety,0 o_offsetx = offsetx o_offsety = offsety glMatrixMode GL_MODELVIEW glLoadIdentity End Function Rem bbdoc: Set the zoom factor of the viewport about: SetViewZoom allows you to zoom all drawn elements at once, instead of scaling each individual element. Use the @zoom parameter to define the level of zoom, a value of 0 is the default zoom, >0 zooms in, <0 zooms out. endrem Function SetViewZoom(zoom:Float) Global o_zoom:Float glMatrixMode GL_PROJECTION glScalef 1.0+(zoom-o_zoom),1.0+(zoom-o_zoom),1.0+(zoom-o_zoom) o_zoom = zoom glMatrixMode GL_MODELVIEW glLoadIdentity End Function |
| ||
but it only works for a second when "A" is pressed. The code is below, I'm not sure how to put it in a code window yet: it's because your "sangle" variable is not defined as global. and allways you call rendergame the sangle variable is set to zero. put sangle as global before main loop ' ----- MAIN LOOP ----- Global Sangle:Float code box: [ codebox] [ /codebox] (whitout spaces) and... you don't need projection matrix. you need to work with Angle, Distance, COS and SIN, is easy. Try to make your own engine. |
| ||
thank you, that worked. |
| ||
maybe you can find a better way to do it. it's only an example. use up,down,left,right to move. 'A' and 'S' to rotate |
| ||
Right on, that's cool. If I can get that to work with a tile map I'm golden! |
| ||
Did you see this function? This is exactly what I need it to do, just not sure where or how to implement it properly: Rem bbdoc: Set the rotation of the viewport about: SetViewRotation allows you to rotate the entire viewport, so that all drawing is rotated according to the @angle parameter. endrem Function SetViewRotation(angle:Float) Global o_angle:Float glMatrixMode GL_PROJECTION glRotatef angle-o_angle,0,0,1 o_angle=angle glMatrixMode GL_MODELVIEW glLoadIdentity End Function |
| ||
Very helpful. Thanks guys. |