Friday, October 8, 2010

Tiled .tmx loader for Love Engine (Lua)

After several hours of work, my .tmx loader for my game is working! This will speed things up considerably!

I'm posting the source in case anyone wants it, but be warned that it makes some assumptions:

  • that tilewidth and tileheight are the same across the map, and all the tilesheets
  • that we've saved file under the csv method
  • this snippet only loads the variables from the file, and doesn't do anything with them - loading the info into tiles is another several hundred lines of code I'm not including here

Here it is: it's ugly, but its working.

function getTileArg(stringVal, argVal)
 --gets argument value from the string in the form argument="value"
 mySearchBegin, mySearchEnd = string.find(stringVal, ' ' .. argVal .. '="')
 if mySearchBegin then
    --find closing quote (")
    openQuote = mySearchEnd
    closeQuote, closeQuoteEnd = string.find(stringVal, '"', openQuote + 1)
    return string.sub(stringVal, openQuote + 1, closeQuote - 1)
 else
  return -1
 end
end

function explodeNumeric(div,str)
  if (div=='') then return false end
  local pos,arr = 0,{}
  -- for each divider found
  for st,sp in function() return string.find(str,div,pos,true) end do
    table.insert(arr,tonumber(string.sub(str,pos,st-1))) -- Attach chars left of current divider
    pos = sp + 1 -- Jump past current divider
  end
  table.insert(arr,string.sub(str,pos)) -- Attach chars right of last divider
  return arr
end

function setupLevel(levelfile)

 lines = {}
 for line in love.filesystem.lines(levelfile .. ".tmx") do
  table.insert(lines, line)
 end

  --find <map> line, get arguments
  mapWidth = -1
  mapHeight = -1
  tileSize = -1
  collideMapFirstLine = -1
  collideMapWidth = -1
  collideMapHeight = -1
  spritesMapFirstLine = -1
  spritesMapWidth = -1
  spritesMapHeight = -1
  collideFirstTile = -1
  collideFile = -1
  spritesFirstTile = -1 
  spriteFile = -1
  for i,v in ipairs(lines) do
    --main map line
   if string.find(v, "<map ") then
    --get mapWidth, mapHeight, tileSize
  mapWidth = tonumber(getTileArg(v, "width"))
  mapHeight = tonumber(getTileArg(v, "height"))
  tileWidth = tonumber(getTileArg(v, "tilewidth"))
  tileHeight = tonumber(getTileArg(v, "tileheight"))
  if tileWidth == tileHeight then tileSize = tileWidth end
   end
   
   --tilesets
   if string.find(v, "<tileset ") then
    --get which map this is
    whichMap = getTileArg(v, "name")
    if whichMap == "collide" then
     collideFirstTile = tonumber(getTileArg(v, "firstgid"))
     collideTileWidth = tonumber(getTileArg(v, "tilewidth"))
     collideTileHeight = tonumber(getTileArg(v, "tileheight"))
     collideFile = getTileArg(lines[i + 1], "source")
    elseif whichMap == "sprites" then
     spritesFirstTile = tonumber(getTileArg(v, "firstgid"))
     spritesTileWidth = tonumber(getTileArg(v, "tilewidth"))
     spritesTileHeight = tonumber(getTileArg(v, "tileheight"))
     spriteFile = getTileArg(lines[i + 1], "source")
    end
   end
   
   --layers
   if string.find(v, "<layer ") then
    --get which layer this is
    whichLayer = getTileArg(v, "name")
    if whichLayer == "Collision" then
     collideMapWidth = tonumber(getTileArg(v, "width"))
     collideMapHeight = tonumber(getTileArg(v, "height"))
     collideMapFirstLine = i + 2
    elseif whichLayer == "Sprites" then
     spritesMapWidth = tonumber(getTileArg(v, "width"))
     spritesMapHeight = tonumber(getTileArg(v, "height"))
     spritesMapFirstLine = i + 2
    end
   end
   
  end
  
  if mapWidth == -1 or mapHeight == -1 or tileSize == -1 then
   error("Error Loading .tmx File (1)")
  end
  
  if collideFirstTile == -1 or collideFile == -1 or collideTileHeight ~= collideTileWidth or collideTileHeight ~= tileSize then
   error("Error Loading .tmx File (1)")
  end  

  if spritesFirstTile == -1 or spriteFile == -1 or spritesTileHeight ~= spritesTileWidth or spritesTileHeight ~= tileSize then
   error("Error Loading .tmx File (1)")
  end  
  
  if collideMapWidth == -1 or spritesMapWidth == -1 or collideMapWidth ~= spritesMapWidth or collideMapHeight == -1 or spritesMapHeight == -1 or collideMapHeight ~= spritesMapHeight or collideMapFirstLine == -1 or spritesMapFirstLine == -1 or collideMapWidth ~= mapWidth or collideMapHeight ~= mapHeight
   then
   error("Error Loading .tmx File (1)")
  end 
end

Next up is some glitch fixes - my character won't jump while running downhill - I need to tweak the touchingGround check somehow. Yay for bug fixes!

Thanks to the tilemap loader, I can now create nice looking levels
... er... nicer looking levels than before, at any rate.

No comments:

Post a Comment