247 lines
6.8 KiB
Lua
247 lines
6.8 KiB
Lua
|
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
|