sonic-radiance/sonic-radiance.love/birb/modules/world/maps/tiled/stiwrapper.lua
2021-05-05 08:30:32 +02:00

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