REM *********************************************** REM Title: Tilemap tutorial REM Author: Phaelax REM Downloaded from: http://dbcc.zimnox.com/ REM *********************************************** SetErrorMode(2) SetWindowTitle( "tut_tilemap" ) SetWindowSize(640,480, 0 ) SetVirtualResolution( 640,480) SetSyncRate(60, 0 ) UseNewDefaultFonts( 1 ) Global yellow = 0 : yellow = makeColor(255,255,0) Type UDT_Tile id as integer EndType Type UDT_Map width as integer height as integer tileSize as integer view as integer[0,0] data as UDT_Tile[0,0] coll as integer[0] x as float y as float maxX as integer maxY as integer viewWidth as integer viewHeight as integer EndType Type UDT_Guy x as float y as float spr as integer speed as float EndType map as UDT_Map guy as UDT_Guy // Open file for reading f = openToRead("map3.txt") // Read first line r$ = readLine(f) map.width = val(getStringToken2(r$, ",", 1)) map.height = val(getStringToken2(r$, ",", 2)) map.tileSize = val(getStringToken2(r$, ",", 3)) imgFilename$ = getStringToken2(r$, ",", 4) // Get number of tiles total = countStringTokens2(r$, ",") - 4 map.coll.length = total // Because the animation frames start at 1 and not 0, // in this case we'll also start the array at 1. It's // only used as a lookup for collision this'll keep simple. for i = 1 to map.coll.length map.coll[i] = val(getStringToken2(r$, ",", i+4)) next i // Redfine the size of the 2D array map.data.length = map.width for x = 0 to map.width-1 map.data[x].length = map.height next x // Load map data for y = 0 to map.height-1 r$ = readLine(f) for x = 0 to map.width-1 map.data[x, y].id = val(getStringToken2(r$, ",", x+1)) next next y // Don't forget to close the file closeFile(f) // Calculate number of tiles that can be shown on screen map.viewWidth = ceil((getVirtualWidth()+0.0) / map.tileSize) + 1 map.viewHeight = ceil((getVirtualheight()+0.0) / map.tileSize) + 1 map.view.length = map.viewWidth for x = 0 to map.viewWidth-1 map.view[x].length = map.viewHeight next x // Calculate the max boundaries for map scrolling map.maxX = (map.width * map.tileSize) - getVirtualWidth() map.maxY = (map.height * map.tileSize) - getVirtualheight() // The base of all tile sprites used in this map spr_base = createSprite(loadImage(imgFilename$)) // Number of tiles in this tileset tileCount = (getSpriteWidth(spr_base) / map.tileSize) * (getSpriteHeight(spr_base) / map.tileSize) setSpriteAnimation(spr_base, map.tileSize, map.tileSize, tileCount) // Position the map tiles for y = 0 to map.viewHeight-1 for x = 0 to map.viewWidth-1 map.view[x, y] = cloneSprite(spr_base) setSpriteFrame(map.view[x, y], map.data[x, y].id) setSpritePosition(map.view[x, y], x*map.tileSize, y*map.tileSize) next next y setSpriteVisible(spr_base, 0) // don't need to see this // Create a periwinkle-colored 32x32 sprite guy.spr = createSprite(0) setSpriteSize(guy.spr, 32, 32) setSpriteColor(guy.spr, 128,128, 255, 255) // How fast the character can move guy.speed = 5 // Starting position, center of screen guy.x = getVirtualWidth() / 2 guy.y = getVirtualHeight() / 2 // How close the player can be to the edge of the screen // before it starts scrolling the map. edgeBuffer = 48 do // Use arrow keys to scroll the map if getRawKeyState(37) // left moveGuy(guy, -guy.speed, 0, map) endif if getRawKeyState(39) // right moveGuy(guy, guy.speed, 0, map) endif if getRawKeyState(38) // up moveGuy(guy, 0, -guy.speed, map) endif if getRawKeyState(40) // down moveGuy(guy, 0, guy.speed, map) endif // Boundaries to keep guy on the screen. if guy.x < 0 then guy.x = 0 if guy.x > getVirtualWidth()-getSpriteWidth(guy.spr) then guy.x = getVirtualWidth()-getSpriteWidth(guy.spr) if guy.y < 0 then guy.y = 0 if guy.y > getVirtualHeight()-getSpriteHeight(guy.spr) then guy.y = getVirtualHeight()-getSpriteHeight(guy.spr) if guy.x < edgeBuffer setMapPosition(map.x-guy.speed, map.y, map) if map.x > 0 then guy.x = edgeBuffer endif if guy.x > getVirtualWidth()-getSpriteWidth(guy.spr)-edgeBuffer setMapPosition(map.x+guy.speed, map.y, map) if map.x < map.maxX then guy.x = getVirtualWidth()-getSpriteWidth(guy.spr)-edgeBuffer endif if guy.y < edgeBuffer setMapPosition(map.x, map.y-guy.speed, map) if map.y > 0 then guy.y = edgeBuffer endif if guy.y > getVirtualHeight()-getSpriteHeight(guy.spr)-edgeBuffer setMapPosition(map.x, map.y+guy.speed, map) if map.y < map.maxY then guy.y = getVirtualHeight()-getSpriteHeight(guy.spr)-edgeBuffer endif setSpritePosition(guy.spr, guy.x, guy.y) // Displays the world tile coordinates under the mouse mx = floor((getRawMouseX() + map.x) / map.tileSize) my = floor((getRawMouseY() + map.y) / map.tileSize) print(str(mx)+":"+str(my)) Sync() loop function getWorldX(x, m ref as UDT_Map) tx = floor((x + m.x) / m.tileSize) endfunction tx function getWorldY(y, m ref as UDT_Map) ty = floor((y + m.y) / m.tileSize) endfunction ty function moveGuy(g ref as UDT_Guy, vx, vy, m ref as UDT_Map) w = getSpriteWidth(g.spr) h = getSpriteHeight(g.spr) a = checkPoint(g.x+vx, g.y+vy, m) // top left b = checkPoint(g.x+vx+w, g.y+vy, m) // top right c = checkPoint(g.x+vx, g.y+vy+h, m) // bottom left d = checkPoint(g.x+vx+w, g.y+vy+h, m) // bottom right if a+b+c+d = 0 g.x = g.x + vx g.y = g.y + vy endif endfunction function checkPoint(cx, cy, m ref as UDT_Map) // Get this point in world coordinates tx = getWorldX(cx, m) ty = getWorldY(cy, m) if tx < 0 or ty < 0 or tx > m.width-1 or ty > m.height-1 then exitfunction 0 // Determine the tile in which this point lies frame = m.data[tx,ty].id // Return 0 or 1, if the tile is passable or not. r = m.coll[frame] // Strictly for showing the collision with tiles if r = 1 bx = (tx*m.tileSize) - m.x by = (ty*m.tileSize) - m.y drawBox(bx, by, bx+m.tileSize, by+m.tileSize, yellow, yellow, yellow, yellow, 0) endif endfunction r function setMapPosition(mx, my, m ref as UDT_Map) m.x = mx m.y = my // Boundary checks to avoid scrolling beyond the map if m.x < 0 then m.x = 0 if m.y < 0 then m.y = 0 if m.x > m.maxX then m.x = m.maxX if m.y > m.maxY then m.y = m.maxY for y = 0 to m.viewHeight-1 for x = 0 to m.viewWidth-1 // Local offsets for viewport tiles ox = x*m.tileSize - mod(m.x, m.tileSize) oy = y*m.tileSize - mod(m.y, m.tileSize) // World offsets for map data tiles wx = floor(m.x / m.tileSize) wy = floor(m.y / m.tileSize) // Boundary check for edge cases if x+wx < m.data.length and y+wy < m.data[x+wx].length // Update viewport tiles with correct tile information setSpriteFrame(m.view[x,y], m.data[x+wx, y+wy].id) endif // Position viewport tiles setSpritePosition(m.view[x, y], ox, oy) next next y endfunction