From b691d96c99b04e7f8cee8fe61b6ae914c3af515f Mon Sep 17 00:00:00 2001 From: Kazhnuz Date: Tue, 23 Mar 2021 13:32:48 +0100 Subject: [PATCH] improvement: refactor the map system --- .../core/modules/world/maps/init.lua | 2 +- .../core/modules/world/maps/sti.lua | 271 ------------------ .../core/modules/world/maps/tiled/init.lua | 61 ++++ .../maps/{ => tiled}/libs/sti/graphics.lua | 0 .../world/maps/{ => tiled}/libs/sti/init.lua | 5 +- .../{ => tiled}/libs/sti/plugins/box2d.lua | 0 .../{ => tiled}/libs/sti/plugins/bump.lua | 0 .../world/maps/{ => tiled}/libs/sti/utils.lua | 0 .../core/modules/world/maps/tiled/mixins.lua | 81 ++++++ .../modules/world/maps/tiled/stiwrapper.lua | 204 +++++++++++++ .../core/modules/world/world2D.lua | 1 - .../scenes/overworld/screens/parent.lua | 2 +- 12 files changed, 352 insertions(+), 275 deletions(-) delete mode 100644 sonic-radiance.love/core/modules/world/maps/sti.lua create mode 100644 sonic-radiance.love/core/modules/world/maps/tiled/init.lua rename sonic-radiance.love/core/modules/world/maps/{ => tiled}/libs/sti/graphics.lua (100%) rename sonic-radiance.love/core/modules/world/maps/{ => tiled}/libs/sti/init.lua (99%) rename sonic-radiance.love/core/modules/world/maps/{ => tiled}/libs/sti/plugins/box2d.lua (100%) rename sonic-radiance.love/core/modules/world/maps/{ => tiled}/libs/sti/plugins/bump.lua (100%) rename sonic-radiance.love/core/modules/world/maps/{ => tiled}/libs/sti/utils.lua (100%) create mode 100644 sonic-radiance.love/core/modules/world/maps/tiled/mixins.lua create mode 100644 sonic-radiance.love/core/modules/world/maps/tiled/stiwrapper.lua diff --git a/sonic-radiance.love/core/modules/world/maps/init.lua b/sonic-radiance.love/core/modules/world/maps/init.lua index 369bd99..12153c4 100644 --- a/sonic-radiance.love/core/modules/world/maps/init.lua +++ b/sonic-radiance.love/core/modules/world/maps/init.lua @@ -1,7 +1,7 @@ local cwd = (...):gsub('%.init$', '') .. "." local mapObjects = {} -mapObjects.Sti = require(cwd .. "sti") +mapObjects.Sti = require(cwd .. "tiled") mapObjects.Base = require(cwd .. "parent") return mapObjects diff --git a/sonic-radiance.love/core/modules/world/maps/sti.lua b/sonic-radiance.love/core/modules/world/maps/sti.lua deleted file mode 100644 index 26b57b0..0000000 --- a/sonic-radiance.love/core/modules/world/maps/sti.lua +++ /dev/null @@ -1,271 +0,0 @@ -local cwd = (...):gsub('%.sti$', '') .. "." - -local Parent = require(cwd .. "parent") -local STI = require(cwd .. "libs.sti") - -local StiMap = Parent:extend() - -function StiMap:new(world, mapfile) - self.sti = STI(mapfile) - StiMap.super.new(self, world) - self:setBackgroundColorFromTable(self.sti.backgroundcolor) - self.mapname = self:getMapName(mapfile) - - self.objectlayer = 0 -end - -function StiMap:loadObjects() - self:loadCollisions() - self:loadPlayers() - self:loadActors() - self.objectlayer = self:getObjectLayer() -end - -function StiMap: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 - -function StiMap:getMapName(mapfile) - local filepath = utils.string.split(mapfile, "/") - local filenameMap = utils.string.split(filepath[#filepath], ".") - return filepath[#filepath - 1] .. "." .. filenameMap[1] -end - -function StiMap:getDimensions() - return self.sti.width * self.sti.tilewidth, - self.sti.height * self.sti.tileheight -end - --- UPDATE FUNCTION --- Update or modify the map - -function StiMap:resize(w, h) - self.sti:resize(w, h) -end - -function StiMap:update(dt) - self.sti:update(dt) -end - --- LOADING FUNCTION --- Load actors directly into the world - -function StiMap:loadCollisions() - for k, objectlayer in pairs(self.sti.layers) do - if self.world:isCollisionIndexed(objectlayer.name) then - local debugstring = "loading " .. #objectlayer.objects .. " objects in " .. objectlayer.name .. " collision layer" - core.debug:print("map/sti", debugstring) - for k, object in pairs(objectlayer.objects) do - self:newCollision(objectlayer, object) - end - self.sti:removeLayer(objectlayer.name) - end - end -end - -function StiMap:loadActors() - for k, objectlayer in pairs(self.sti.layers) do - if self.world: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:batchActor(objectlayer, object) - else - self:newActor(objectlayer, object) - end - end - self.sti:removeLayer(objectlayer.name) - end - end -end - -function StiMap:loadPlayers() - for k, objectlayer in pairs(self.sti.layers) do - if (objectlayer.name == "player") 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:newPlayer(object, i) - i = i + 1 - end - self.sti:removeLayer(objectlayer.name) - end - end -end - -function StiMap:batchActor(objectlayer, object) - local name = objectlayer.name - local gwidth = object.properties.gwidth or self.sti.tilewidth - local gheight = object.properties.gheight or self.sti.tileheight - local x = object.x - local y = object.y - local z = object.properties.z or 0 - local w = object.width - local h = object.height - - local cellHor = math.ceil(w / gwidth) - local cellVert = math.ceil(h / gheight) - - for i=1, cellHor do - for j=1, cellVert do - self.world:newActor(name, x + (i-1)*gwidth, y + (j-1)*gheight, z, object.properties) - end - end -end - -function StiMap:newActor(objectlayer, object) - local z = object.properties.z or 0 - local adaptPosition = object.properties.adaptPosition or false - - local y = object.y - if (adaptPosition) then - y = y + z - end - - self.world:newActor(objectlayer.name, object.x, y, z, object.properties, self.mapname) -end - -function StiMap:newCollision(objectlayer, object) - local z = object.properties.z or 0 - local d = object.properties.d or 16 - local fromTop = object.properties.fromTop or false - - local y = object.y - if (fromTop) then - local poschange = z .. ";" .. y .. " => " .. z-d .. ";" .. y+z - core.debug:print("map/sti", "create from top, set z and y: " .. poschange) - y = y + z - z = z - d - end - - self.world:newCollision(objectlayer.name, object.x, y, z, object.width, object.height, d) -end - -function StiMap: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 StiMap: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 StiMap:getTileTypeAtPoint(x, y) - local xx, yy = self:convertPixelToTile (x, y) - return self:getTileTypeAtCoord(xx, yy) -end - -function StiMap: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 StiMap:convertPixelToTile(x, y) - local xx, yy = self.sti:convertPixelToTile (x, y) - return math.ceil(xx), math.ceil(yy) -end - -function StiMap: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 StiMap: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 - -function StiMap:newPlayer(object, i) - local z = object.properties.z or 0 - local adaptPosition = object.properties.adaptPosition or false - - local y = object.y - if (adaptPosition) then - core.debug:print("map/sti", "adapting position, set y: " .. y .. " => ", y+z) - y = y + z - end - - self.world:addPlayer(object.x, y, z, i) -end - --- DRAW FUNCTIONS --- Draw the map - -function StiMap:drawUpperLayers() - if (self.objectlayer > 0) then - for i = self.objectlayer, self.nbrLayer, 1 do - self:drawLayer(i) - end - end -end - -function StiMap:drawLowerLayers() - for i = 1, self.objectlayer, 1 do - self:drawLayer(i) - end -end - -function StiMap:drawLayer(id) - local layer = self.sti.layers[id] - if (layer ~= nil) then - if layer.visible and layer.opacity > 0 and (layer.type == "tilelayer") then - print("upper " .. id) - self.sti:drawLayer(layer) - end - end -end - -return StiMap diff --git a/sonic-radiance.love/core/modules/world/maps/tiled/init.lua b/sonic-radiance.love/core/modules/world/maps/tiled/init.lua new file mode 100644 index 0000000..0cfa600 --- /dev/null +++ b/sonic-radiance.love/core/modules/world/maps/tiled/init.lua @@ -0,0 +1,61 @@ +local Parent = require "core.modules.world.maps.parent" +local TiledMap = Parent:extend() +local StiWrapper = require "core.modules.world.maps.tiled.stiwrapper" + +local TiledMixins = require "core.modules.world.maps.tiled.mixins" + +TiledMap:implement(TiledMixins) + +function TiledMap:new(world, mapfile) + self.wrapper = StiWrapper(self, mapfile, 0, 0) + TiledMap.super.new(self, world) + + self:setBackgroundColorFromTable(self.wrapper.sti.backgroundcolor) + self.mapname = self:getMapName(mapfile) +end + +function TiledMap:getMapName(mapfile) + local filepath = utils.string.split(mapfile, "/") + local filenameMap = utils.string.split(filepath[#filepath], ".") + return filepath[#filepath - 1] .. "." .. filenameMap[1] +end + +function TiledMap:getDimensions() + return self.wrapper:getDimensions() +end + +function TiledMap:loadObjects() + self.wrapper:loadObjects() +end + +-- TILE FUNCTIONS +-- Get tiles + +function TiledMap:haveTileTypeInRect(x, y, w, h, type) + return self.wrapper:haveTileTypeInRect(x, y, w, h, type) +end + +-- UPDATE FUNCTION +-- Update or modify the map + +function TiledMap:resize(w, h) + self.wrapper:resize(w, h) +end + +function TiledMap:update(dt) + self.wrapper:update(dt) +end + +-- DRAW FUNCTIONS +-- Handle drawing the wrapper + + +function TiledMap:drawUpperLayers() + self.wrapper:drawUpperLayers() +end + +function TiledMap:drawLowerLayers() + self.wrapper:drawLowerLayers() +end + +return TiledMap diff --git a/sonic-radiance.love/core/modules/world/maps/libs/sti/graphics.lua b/sonic-radiance.love/core/modules/world/maps/tiled/libs/sti/graphics.lua similarity index 100% rename from sonic-radiance.love/core/modules/world/maps/libs/sti/graphics.lua rename to sonic-radiance.love/core/modules/world/maps/tiled/libs/sti/graphics.lua diff --git a/sonic-radiance.love/core/modules/world/maps/libs/sti/init.lua b/sonic-radiance.love/core/modules/world/maps/tiled/libs/sti/init.lua similarity index 99% rename from sonic-radiance.love/core/modules/world/maps/libs/sti/init.lua rename to sonic-radiance.love/core/modules/world/maps/tiled/libs/sti/init.lua index de1bd16..a4e70de 100644 --- a/sonic-radiance.love/core/modules/world/maps/libs/sti/init.lua +++ b/sonic-radiance.love/core/modules/world/maps/tiled/libs/sti/init.lua @@ -745,10 +745,13 @@ end --- Draw an individual Layer -- @param layer The Layer to draw -function Map.drawLayer(_, layer) +function Map.drawLayer(_, layer, x, y) local r,g,b,a = lg.getColor() lg.setColor(r, g, b, a * layer.opacity) + print(x, y) + lg.translate(x, y) layer:draw() + lg.translate(-x, -y) lg.setColor(r,g,b,a) end diff --git a/sonic-radiance.love/core/modules/world/maps/libs/sti/plugins/box2d.lua b/sonic-radiance.love/core/modules/world/maps/tiled/libs/sti/plugins/box2d.lua similarity index 100% rename from sonic-radiance.love/core/modules/world/maps/libs/sti/plugins/box2d.lua rename to sonic-radiance.love/core/modules/world/maps/tiled/libs/sti/plugins/box2d.lua diff --git a/sonic-radiance.love/core/modules/world/maps/libs/sti/plugins/bump.lua b/sonic-radiance.love/core/modules/world/maps/tiled/libs/sti/plugins/bump.lua similarity index 100% rename from sonic-radiance.love/core/modules/world/maps/libs/sti/plugins/bump.lua rename to sonic-radiance.love/core/modules/world/maps/tiled/libs/sti/plugins/bump.lua diff --git a/sonic-radiance.love/core/modules/world/maps/libs/sti/utils.lua b/sonic-radiance.love/core/modules/world/maps/tiled/libs/sti/utils.lua similarity index 100% rename from sonic-radiance.love/core/modules/world/maps/libs/sti/utils.lua rename to sonic-radiance.love/core/modules/world/maps/tiled/libs/sti/utils.lua diff --git a/sonic-radiance.love/core/modules/world/maps/tiled/mixins.lua b/sonic-radiance.love/core/modules/world/maps/tiled/mixins.lua new file mode 100644 index 0000000..ad0162c --- /dev/null +++ b/sonic-radiance.love/core/modules/world/maps/tiled/mixins.lua @@ -0,0 +1,81 @@ +local TiledMixins = Object:extend() + +-- ACTOR ADDING FUNCTIONS +-- Add actor related to the map + +function TiledMixins:batchActor(objectlayer, object, layerx, layery) + local name = objectlayer.name + local gwidth = object.properties.gwidth or self.sti.tilewidth + local gheight = object.properties.gheight or self.sti.tileheight + local x = object.x + layerx + local y = object.y + layery + local z = object.properties.z or 0 + local w = object.width + local h = object.height + + local cellHor = math.ceil(w / gwidth) + local cellVert = math.ceil(h / gheight) + + for i = 1, cellHor do + for j = 1, cellVert do + self.world:newActor(name, x + (i - 1) * gwidth, y + (j - 1) * gheight, z, object.properties) + end + end +end + +function TiledMixins:newActor(objectlayer, object, layerx, layery) + local z = object.properties.z or 0 + local adaptPosition = object.properties.adaptPosition or false + + local x = object.x + layerx + local y = object.y + layery + if (adaptPosition) then + y = y + z + end + + self.world:newActor(objectlayer.name, x, y, z, object.properties, self.mapname) +end + +function TiledMixins:newCollision(objectlayer, object, layerx, layery) + local z = object.properties.z or 0 + local d = object.properties.d or 16 + local fromTop = object.properties.fromTop or false + local x = object.x + layerx + local y = object.y + layery + if (fromTop) then + local poschange = z .. ";" .. y .. " => " .. z - d .. ";" .. y + z + core.debug:print("map/sti", "create from top, set z and y: " .. poschange) + y = y + z + z = z - d + end + + self.world:newCollision(objectlayer.name, x, y, z, object.width, object.height, d) +end + +function TiledMixins:newPlayer(object, i, layerx, layery) + local z = object.properties.z or 0 + local adaptPosition = object.properties.adaptPosition or false + + local x = object.x + layerx + + local y = object.y + layery + if (adaptPosition) then + core.debug:print("map/sti", "adapting position, set y: " .. y .. " => ", y + z) + y = y + z + end + + self.world:addPlayer(x, y, z, i) +end + +-- INDEXATION FUNCTIONS +-- Verify if something is indexed + +function TiledMixins:isCollisionIndexed(name) + return self.world:isCollisionIndexed(name) +end + +function TiledMixins:isActorIndexed(name) + return self.world:isActorIndexed(name) +end + +return TiledMixins diff --git a/sonic-radiance.love/core/modules/world/maps/tiled/stiwrapper.lua b/sonic-radiance.love/core/modules/world/maps/tiled/stiwrapper.lua new file mode 100644 index 0000000..df81759 --- /dev/null +++ b/sonic-radiance.love/core/modules/world/maps/tiled/stiwrapper.lua @@ -0,0 +1,204 @@ +local StiWrapper = Object:extend() +local STI = require "core.modules.world.maps.tiled.libs.sti" + +function StiWrapper:new(owner, mapfile, x, y) + self.sti = STI(mapfile) + self.owner = owner + self.x = x or 0 + self.y = y or 0 + + self.objectlayer = 0 +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.sti:update(dt) +end + +-- OBJECT FUNCTIONS +-- Handle objets + +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 + 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 + 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: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() + if (self.objectlayer > 0) then + for i = self.objectlayer, self.nbrLayer, 1 do + self:drawLayer(i) + end + end +end + +function StiWrapper:drawLowerLayers() + for i = 1, self.objectlayer, 1 do + self:drawLayer(i) + 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 diff --git a/sonic-radiance.love/core/modules/world/world2D.lua b/sonic-radiance.love/core/modules/world/world2D.lua index 11417ef..189d53a 100644 --- a/sonic-radiance.love/core/modules/world/world2D.lua +++ b/sonic-radiance.love/core/modules/world/world2D.lua @@ -27,7 +27,6 @@ local BaseWorld = require(cwd .. "baseworld") local World2D = BaseWorld:extend() local Bump = require(cwd .. "libs.bump") -local CameraSystem = require(cwd .. "camera") function World2D:new(scene, actorlist, mapfile, maptype) World2D.super.new(self, scene, actorlist, mapfile, maptype) diff --git a/sonic-radiance.love/scenes/overworld/screens/parent.lua b/sonic-radiance.love/scenes/overworld/screens/parent.lua index 19e177a..fb625ef 100644 --- a/sonic-radiance.love/scenes/overworld/screens/parent.lua +++ b/sonic-radiance.love/scenes/overworld/screens/parent.lua @@ -30,7 +30,7 @@ end function MenuScreenParent:drawForeground() self.scene.assets.fonts["SA2font"]:print(self.title, 160, 12) - love.graphics.rectangle("line", const.X, const.Y, const.WIDTH, const.HEIGHT) + --love.graphics.rectangle("line", const.X, const.Y, const.WIDTH, const.HEIGHT) self:draw() end