local StiWrapper = Object:extend() local STI = require "birb.modules.world.maps.tiled.libs.sti" function StiWrapper:new(owner, mapfile, x, y, canLoadPlayer) self.sti = STI(mapfile) self.owner = owner self.x = x or 0 self.y = y or 0 self.canLoadPlayer = (canLoadPlayer ~= false) self.objectlayer = 0 self.isLoaded = false end function StiWrapper:getRect() local w, h = self:getDimensions() return self.x, self.y, w, h end function StiWrapper:getDimensions() return self.sti.width * self.sti.tilewidth, self.sti.height * self.sti.tileheight end -- UPDATE FUNCTION -- Update or modify the map function StiWrapper:resize(w, h) self.sti:resize(w, h) end function StiWrapper:update(dt) self:lazyLoad() self.sti:update(dt) end -- OBJECT FUNCTIONS -- Handle objets function StiWrapper:lazyLoad() if (not self.isLoaded) then self:loadObjects() self.isLoaded = true end end function StiWrapper:loadObjects() self:loadCollisions() self:loadPlayers() self:loadActors() self.objectlayer = self:getObjectLayer() end function StiWrapper:loadCollisions() for _, objectlayer in pairs(self.sti.layers) do if self.owner:isCollisionIndexed(objectlayer.name) then local debugstring = "loading " .. #objectlayer.objects .. " objects in " .. objectlayer.name .. " collision layer" core.debug:print("map/sti", debugstring) for _, object in pairs(objectlayer.objects) do self.owner:newCollision(objectlayer, object, self.x, self.y) end self.sti:removeLayer(objectlayer.name) end end end function StiWrapper:loadActors() for k, objectlayer in pairs(self.sti.layers) do if self.owner:isActorIndexed(objectlayer.name) then local debugstring = "loading " .. #objectlayer.objects .. " objects in " .. objectlayer.name .. " actor layer" core.debug:print("map/sti", debugstring) for k, object in pairs(objectlayer.objects) do if (object.properties.batchActor) then self.owner:batchActor(objectlayer, object, self.x, self.y) else self.owner:newActor(objectlayer, object, self.x, self.y) end end self.sti:removeLayer(objectlayer.name) end end end function StiWrapper:loadPlayers() for k, objectlayer in pairs(self.sti.layers) do if (objectlayer.name == "player") then if (self.canLoadPlayer) then local debugstring = "loading at most " .. #objectlayer.objects .. " actors in " .. objectlayer.name .. " actor layer" core.debug:print("map/sti", debugstring) local i = 1 for k, object in pairs(objectlayer.objects) do self.owner:newPlayer(object, i, self.x, self.y) i = i + 1 end end self.sti:removeLayer(objectlayer.name) end end end function StiWrapper:getObjectLayer() local objectlayer = 0 for i, layer in ipairs(self.sti.layers) do if (layer.name == "objects") then objectlayer = i end self.nbrLayer = i end return objectlayer end -- TILE FUNCTIONS -- Handle tiles function StiWrapper:haveTileTypeInRect(x, y, w, h, type) local x1, y1, x2, y2 = self:getTileRectangle(x, y, x + w, y + h) local isSolid = false for i = x1, x2, 1 do for j = y1, y2, 1 do if (self:getTileTypeAtCoord(i, j) == type) then isSolid = true end end end return isSolid end function StiWrapper:getTileRectangle(x, y, x2, y2) local xx, yy = self:convertPixelToTile(x, y) local xx2, yy2 = self:convertPixelToTile(x2, y2) return xx, yy, xx2, yy2 end function StiWrapper:getTileTypeAtPoint(x, y) local xx, yy = self:convertPixelToTile(x, y) return self:getTileTypeAtCoord(xx, yy) end function StiWrapper:haveUpperLayerAtCoord(x, y) local xx, yy = self:convertPixelToTile(x, y) local haveLayer = false if (self.objectlayer > 0) then for i = self.objectlayer, self.nbrLayer, 1 do local layer = self.sti.layers[i] if layer.visible and layer.opacity > 0 and (layer.type == "tilelayer") then local _, tileid = self:getTileId(layer.name, xx, yy) if (tileid > 0) then haveLayer = true end end end end return haveLayer end function StiWrapper:getTileTypeAtCoord(x, y) local canSearch = true local currentType = nil for _, layer in ipairs(self.sti.layers) do if (canSearch) then if (layer.type == "tilelayer") then local tileset, tileid = self:getTileId(layer.name, x, y) local type = self:getTileType(tileset, tileid) if (type ~= nil) then currentType = type end else if (layer.name == "objects") then canSearch = false end end end end return currentType end function StiWrapper:convertPixelToTile(x, y) local xx, yy = self.sti:convertPixelToTile(x - self.x, y - self.y) return math.ceil(xx), math.ceil(yy) end function StiWrapper:getTileType(tileset, id) local tilesetData = self.sti.tilesets[tileset] if ((tileset == -1) or (id == -1)) then return nil end if (tilesetData ~= nil) then for i, tile in ipairs(tilesetData.tiles) do if (tile.id == id) and (tile.type ~= nil) then return tile.type end end end return "non-solid" end function StiWrapper:getTileId(layer, x, y) local line = self.sti.layers[layer].data[y] if (line ~= nil) then local tile = line[x] if not tile then return -1, -1 end return tile.tileset, tile.id end return -1, -1 end -- DRAW FUNCTIONS -- Draw the map function StiWrapper:drawUpperLayers() self:lazyLoad() if (self.objectlayer > 0) then for i = self.objectlayer, self.nbrLayer, 1 do self:drawLayer(i) end end end function StiWrapper:drawLowerLayers() self:lazyLoad() if (self.objectlayer > 0) then for i = 1, self.objectlayer, 1 do self:drawLayer(i) end else for i = 1, self.nbrLayer, 1 do self:drawLayer(i) end end end function StiWrapper:drawLayer(id) local layer = self.sti.layers[id] if (layer ~= nil) then if layer.visible and layer.opacity > 0 and (layer.type == "tilelayer") then self.sti:drawLayer(layer, self.x, self.y) end end end return StiWrapper