diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d07600..ddfb9f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Changed + +- **world:** extract map module from the world module + ## [0.6.0] - 2019-07-20 - Meta: Add proper crediting diff --git a/gamecore/modules/world/baseworld.lua b/gamecore/modules/world/baseworld.lua index f2a7d54..9ac5ac7 100644 --- a/gamecore/modules/world/baseworld.lua +++ b/gamecore/modules/world/baseworld.lua @@ -26,7 +26,7 @@ local cwd = (...):gsub('%.baseworld$', '') .. "." local BaseWorld = Object:extend() -local Sti = require(cwd .. "libs.sti") +local mapObjects = require(cwd .. "maps") local CameraSystem = require(cwd .. "camera") local PADDING_VALUE = 10/100 @@ -34,17 +34,18 @@ local PADDING_VALUE = 10/100 -- INIT FUNCTIONS -- All functions to init the world and the map -function BaseWorld:new(scene, actorlist, mapfile) +function BaseWorld:new(scene, actorlist, mapfile, maptype) self.scene = scene self.actorlist = actorlist self.mapfile = mapfile + self.mapObjects = mapObjects self.cameras = CameraSystem(self) self:initActors() self:initPlayers() self:setActorList(self.actorlist) - self:initMap(self.mapfile) + self:initMap(self.mapfile, maptype) self:setGravity() self:register() @@ -60,10 +61,13 @@ function BaseWorld:setActorList(actorlist) end end -function BaseWorld:initMap(mapfile) - self.haveMap = false - self.haveBackgroundColor = false - self.backcolor = {128, 128, 128} +function BaseWorld:initMap(mapfile, maptype) + if (mapfile ~= nil) then + self.maptype = maptype or "sti" + else + self.maptype = "empty" + end + self.mapfile = mapfile end @@ -83,7 +87,7 @@ end function BaseWorld:reset() self:initActors() self:initPlayers() - self:initMap(self.mapfile) + self:initMap(self.mapfile, self.maptype) self.cameras:initViews() collectgarbage() @@ -98,11 +102,12 @@ function BaseWorld:initActors( ) self.currentCreationID = 0 end -function BaseWorld:newActor(name, x, y) +function BaseWorld:newActor(name, x, y, z) self.obj.index[name](self, x, y) end -function BaseWorld:newCollision(name, x, y, w, h) +function BaseWorld:newCollision(name, x, y, z, w, h, d) + print("Creating collision " .. name .. " at position " .. x .. ";" .. y .. ". Size is " .. w .. ";" .. h) self.obj.collisions[name](self, x, y, w, h) end @@ -216,21 +221,6 @@ end -- PLAYER MANAGEMENT FUNCTIONS -- Basic function to handle player actors -function BaseWorld:loadMap() - local mapfile = self.mapfile - if mapfile == nil then - self.haveMap = false - self.haveBackgroundColor = false - self.backcolor = {128, 128, 128} - else - self.haveMap = true - self.map = Sti(mapfile) - self.haveBackgroundColor = true - self.backcolor = self.map.backgroundcolor or {128, 128, 128} - self:loadMapObjects() - end -end - function BaseWorld:initPlayers() self.players = {} self.playerNumber = 1 @@ -240,14 +230,20 @@ function BaseWorld:setPlayerNumber(playerNumber) self.playerNumber = playerNumber or 1 end -function BaseWorld:addPlayer(actor, sourceid) +function BaseWorld:addPlayer(x, y, z, id) local player = {} - player.actor = actor - player.sourceid = sourceid or 1 + if id <= self.playerNumber then + player.actor = self:newPlayer(x, y, z) + player.sourceid = sourceid or 1 - table.insert(self.players, player) + table.insert(self.players, player) - self.cameras:addTarget(player.actor) + self.cameras:addTarget(player.actor) + end +end + +function BaseWorld:newPlayer(x, y, z) + return self.obj.Player(self, x, y) end function BaseWorld:sendInputToPlayers(actor) @@ -269,112 +265,55 @@ end -- MAP FUNCTIONS -- All map wrappers +function BaseWorld:loadMap() + self:createMapController() + self:loadMapObjects() +end + +function BaseWorld:createMapController() + if (self.maptype == "empty") then + self.mapObjects.Base(self) + elseif (self.maptype == "sti") then + self.mapObjects.Sti(self, self.mapfile) + end +end + function BaseWorld:loadMapObjects() - self:loadMapCollisions() - self:loadMapPlayers() - self:loadMapActors() -end - -function BaseWorld:loadMapCollisions() - for k, objectlayer in pairs(self.map.layers) do - if self:isCollisionIndexed(objectlayer.name) then - print("DEBUG: loading actors in " .. objectlayer.name .. " collision layer") - for k, object in pairs(objectlayer.objects) do - self:newCollisionFromMap(objectlayer, object) - end - self.map:removeLayer(objectlayer.name) - end - end -end - -function BaseWorld:loadMapActors() - for k, objectlayer in pairs(self.map.layers) do - if self:isActorIndexed(objectlayer.name) then - print("DEBUG: loading actors in " .. objectlayer.name .. " actor layer") - for k, object in pairs(objectlayer.objects) do - if (object.properties.batchActor) then - self:batchActor(objectlayer, object) - else - self:newActorFromMap(objectlayer, object) - end - end - self.map:removeLayer(objectlayer.name) - end - end -end - -function BaseWorld:batchActor(objectlayer, object) - local name = objectlayer.name - local gwidth = object.properties.gwidth or self.map.tilewidth - local gheight = object.properties.gheight or self.map.tileheight - local x = object.x - local y = object.y - 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:newActor(name, x + (i-1)*gwidth, y + (j-1)*gheight) - end - end -end - -function BaseWorld:newActorFromMap(objectlayer, object) - self:newActor(objectlayer.name, object.x, object.y) -end - -function BaseWorld:newCollisionFromMap(objectlayer, object) - self:newCollision(objectlayer.name, object.x, object.y, object.width, object.height) -end - -function BaseWorld:addPlayerFromMap(object, i) - self:addPlayer(self.obj.Player(self, object.x, object.y), i) -end - -function BaseWorld:loadMapPlayers() - for k, objectlayer in pairs(self.map.layers) do - if (objectlayer.name == "player") then - print("DEBUG: loading actors in player layer") - local i = 1 - for k, object in pairs(objectlayer.objects) do - if (i <= self.playerNumber) then - -- TODO: don't hardcode camera handling - self:addPlayerFromMap(object, i) - end - i = i + 1 - end - self.map:removeLayer(objectlayer.name) - end + if (self.map ~= nil) then + self.map:loadObjects() end end function BaseWorld:getDimensions() - if self.haveMap then - return self.map.width * self.map.tilewidth, - self.map.height * self.map.tileheight + if (self.map ~= nil) then + return self.map:getDimensions() else return core.screen:getDimensions() end end function BaseWorld:setBackgroundColor(r, g, b) - self.backcolor = {r, g, b} - self.haveBackgroundColor = true + if (self.map ~= nil) then + self.map:setBackgroundColor(r, g, b) + end end function BaseWorld:removeBackgroundColor() - self.haveBackgroundColor = false + if (self.map ~= nil) then + self.map:setBackgroundColor() + end end function BaseWorld:getBackgroundColor() - return self.backcolor[1]/256, self.backcolor[2]/256, self.backcolor[3]/256 + if (self.map ~= nil) then + return self.map:getBackgroundColor() + else + return 0, 0, 0 + end end function BaseWorld:resizeMap(w, h) - if self.haveMap then + if (self.map ~= nil) then local w, h = utils.math.floorCoord(w, h) self.map:resize(w, h) end @@ -413,12 +352,11 @@ function BaseWorld:updateActors(dt) end function BaseWorld:updateMap(dt) - if self.haveMap then + if (self.map ~= nil) then self.map:update(dt) end end - -- DRAW FUNCTIONS -- All function to draw the map, world and actors @@ -448,21 +386,14 @@ function BaseWorld:drawActors(id) end function BaseWorld:drawMap(id) - if self.haveMap then - for _, layer in ipairs(self.map.layers) do - if layer.visible and layer.opacity > 0 and (layer.type == "tilelayer") then - self.map:drawLayer(layer) - end - end + if (self.map ~= nil) then + self.map:draw() end end function BaseWorld:drawBackgroundColor() - if self.haveBackgroundColor then - local r, g, b = self.backcolor[1], self.backcolor[2], self.backcolor[3] - love.graphics.setColor(r/256, g/256, b/256) - love.graphics.rectangle("fill", 0, 0, 480, 272) - utils.graphics.resetColor() + if (self.map ~= nil) then + self.map:drawBackgroundColor() end end diff --git a/gamecore/modules/world/maps/init.lua b/gamecore/modules/world/maps/init.lua new file mode 100644 index 0000000..369bd99 --- /dev/null +++ b/gamecore/modules/world/maps/init.lua @@ -0,0 +1,7 @@ +local cwd = (...):gsub('%.init$', '') .. "." + +local mapObjects = {} +mapObjects.Sti = require(cwd .. "sti") +mapObjects.Base = require(cwd .. "parent") + +return mapObjects diff --git a/gamecore/modules/world/libs/sti/graphics.lua b/gamecore/modules/world/maps/libs/sti/graphics.lua similarity index 100% rename from gamecore/modules/world/libs/sti/graphics.lua rename to gamecore/modules/world/maps/libs/sti/graphics.lua diff --git a/gamecore/modules/world/libs/sti/init.lua b/gamecore/modules/world/maps/libs/sti/init.lua similarity index 100% rename from gamecore/modules/world/libs/sti/init.lua rename to gamecore/modules/world/maps/libs/sti/init.lua diff --git a/gamecore/modules/world/libs/sti/plugins/box2d.lua b/gamecore/modules/world/maps/libs/sti/plugins/box2d.lua similarity index 100% rename from gamecore/modules/world/libs/sti/plugins/box2d.lua rename to gamecore/modules/world/maps/libs/sti/plugins/box2d.lua diff --git a/gamecore/modules/world/libs/sti/plugins/bump.lua b/gamecore/modules/world/maps/libs/sti/plugins/bump.lua similarity index 100% rename from gamecore/modules/world/libs/sti/plugins/bump.lua rename to gamecore/modules/world/maps/libs/sti/plugins/bump.lua diff --git a/gamecore/modules/world/libs/sti/utils.lua b/gamecore/modules/world/maps/libs/sti/utils.lua similarity index 100% rename from gamecore/modules/world/libs/sti/utils.lua rename to gamecore/modules/world/maps/libs/sti/utils.lua diff --git a/gamecore/modules/world/maps/parent.lua b/gamecore/modules/world/maps/parent.lua new file mode 100644 index 0000000..17207a5 --- /dev/null +++ b/gamecore/modules/world/maps/parent.lua @@ -0,0 +1,81 @@ +local ParentMap = Object:extend() + +-- INIT FUNCTION +-- Initialize the map + +function ParentMap:new(world, r, g, b) + self.world = world + + local r = r or 128 + local g = g or 128 + local b = b or 128 + self.backgroundColor = {r, g, b} + + self:register() +end + +function ParentMap:register() + self.world.map = self +end + +-- UPDATE FUNCTION +-- Update or modify the map + +function ParentMap:resize(w, h) + -- Empty Placeholder function +end + +function ParentMap:update(dt) + -- Empty Placeholder function +end + +function ParentMap:loadObjects() + self:loadCollisions() + self:loadPlayers() + self:loadActors() +end + +function ParentMap:loadCollisions() + -- Empty Placeholder function +end + +function ParentMap:loadPlayers() + -- Empty Placeholder function +end + +function ParentMap:loadActors() + -- Empty Placeholder function +end + +function ParentMap:setBackgroundColor(r, g, b) + local r = r or 128 + local g = g or 128 + local b = b or 128 + self.backgroundColor = {r, g, b} +end + +function ParentMap:setBackgroundColorFromTable(backgroundColor) + self.backgroundColor = backgroundColor or {128, 128, 128} +end + +function ParentMap:getBackgroundColor() + return self.backgroundColor[1]/256, self.backgroundColor[2]/256, self.backgroundColor[3]/256 +end + +function ParentMap:getDimensions() + return core.screen:getDimensions() +end + +function ParentMap:getBox() + local w, h = self:getDimensions() + return 0, 0, w, h +end + +function ParentMap:drawBackgroundColor() + local r, g, b = self.backgroundColor[1], self.backgroundColor[2], self.backgroundColor[3] + love.graphics.setColor(r/256, g/256, b/256) + love.graphics.rectangle("fill", 0, 0, 480, 272) + utils.graphics.resetColor() +end + +return ParentMap diff --git a/gamecore/modules/world/maps/sti.lua b/gamecore/modules/world/maps/sti.lua new file mode 100644 index 0000000..795df2d --- /dev/null +++ b/gamecore/modules/world/maps/sti.lua @@ -0,0 +1,149 @@ +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) +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 + print("DEBUG: loading actors in " .. objectlayer.name .. " collision layer") + 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 + print("DEBUG: loading actors in " .. objectlayer.name .. " actor layer") + 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 + print("DEBUG: loading actors in player layer") + 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 + print("DEBUG:", "Setting the world to create actor " .. name) + self.world:newActor(name, x + (i-1)*gwidth, y + (j-1)*gheight, z) + 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 + + print("DEBUG:", "Setting the world to create actor " .. objectlayer.name) + self.world:newActor(objectlayer.name, object.x, y, z) +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 + print("create from top, set z and y:", z, y, "=>", z-d, y+z) + y = y + z + z = z - d + end + + print("DEBUG:", "Setting the world to create collision " .. objectlayer.name) + self.world:newCollision(objectlayer.name, object.x, y, z, object.width, object.height, d) +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 + y = y + z + end + + print("DEBUG:", "Setting the world to create player " .. i) + self.world:addPlayer(object.x, y, z, i) +end + +-- DRAW FUNCTIONS +-- Draw the map + +function StiMap:draw() + for _, layer in ipairs(self.sti.layers) do + if layer.visible and layer.opacity > 0 and (layer.type == "tilelayer") then + self.sti:drawLayer(layer) + end + end +end + +return StiMap diff --git a/gamecore/modules/world/world2D.lua b/gamecore/modules/world/world2D.lua index 23e7c8e..c29a90d 100644 --- a/gamecore/modules/world/world2D.lua +++ b/gamecore/modules/world/world2D.lua @@ -26,7 +26,6 @@ local cwd = (...):gsub('%.world2D$', '') .. "." local BaseWorld = require(cwd .. "baseworld") local World2D = BaseWorld:extend() -local Sti = require(cwd .. "libs.sti") local Bump = require(cwd .. "libs.bump") local CameraSystem = require(cwd .. "camera") @@ -43,14 +42,6 @@ function World2D:initActors() self.bodies = Bump.newWorld(50) end -function World2D:newActor(name, x, y) - self.obj.index[name](self, x, y) -end - -function World2D:newCollision(name, x, y, w, h) - self.obj.collisions[name](self, x, y, w, h) -end - function World2D:registerActor(actor) World2D.super.registerActor(self, actor) end @@ -72,53 +63,6 @@ function World2D:getActorsInRect(x, y, w, h) return returnquery end --- PLAYER FUNCTIONS --- Load player stuff - -function World2D:addPlayer(actor, sourceid, haveCam) - local player = {} - player.actor = actor - player.sourceid = sourceid or 1 - - table.insert(self.players, player) - - self.cameras:addTarget(player.actor) -end - --- MAP LOADING FUNCTIONS --- Handle loading of actors from map - -function World2D:batchActor(objectlayer, object) - local name = objectlayer.name - local gwidth = object.properties.gwidth or self.map.tilewidth - local gheight = object.properties.gheight or self.map.tileheight - local x = object.x - local y = object.y - 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:newActor(name, x + (i-1)*gwidth, y + (j-1)*gheight) - end - end -end - -function World2D:newActorFromMap(objectlayer, object) - self:newActor(objectlayer.name, object.x, object.y) -end - -function World2D:newCollisionFromMap(objectlayer, object) - self:newCollision(objectlayer.name, object.x, object.y, object.width, object.height) -end - -function World2D:addPlayerFromMap(object, i) - self:addPlayer(self.obj.Player(self, object.x, object.y), i) -end - -- BODIES MANAGEMENT FUNCTIONS -- Basic function to handle bodies. Wrappers around Bump2D functions diff --git a/gamecore/modules/world/world3D.lua b/gamecore/modules/world/world3D.lua index 0b4c12d..ca2eb16 100644 --- a/gamecore/modules/world/world3D.lua +++ b/gamecore/modules/world/world3D.lua @@ -26,7 +26,6 @@ local cwd = (...):gsub('%.world3D$', '') .. "." local BaseWorld = require(cwd .. "baseworld") local World3D = BaseWorld:extend() -local Sti = require(cwd .. "libs.sti") local Bump = require(cwd .. "libs.bump") local Bump3D = require(cwd .. "libs.bump-3dpd") local Tsort = require(cwd .. "libs.tsort") @@ -90,69 +89,8 @@ end -- PLAYER FUNCTIONS -- Load player stuff -function World3D:addPlayer(actor, sourceid, haveCam) - local player = {} - player.actor = actor - player.sourceid = sourceid or 1 - - table.insert(self.players, player) - - self.cameras:addTarget(player.actor) -end - --- MAP LOADING FUNCTIONS --- Handle loading of actors from map - -function World3D:batchActor(objectlayer, object) - local name = objectlayer.name - local gwidth = object.properties.gwidth or self.map.tilewidth - local gheight = object.properties.gheight or self.map.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:newActor(name, x + (i-1)*gwidth, y + (j-1)*gheight, z) - end - end -end - -function World3D:newActorFromMap(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:newActor(objectlayer.name, object.x, y, z) -end - -function World3D:newCollisionFromMap(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 - print("create from top, set z and y:", z, y, "=>", z-d, y+z) - y = y + z - z = z - d - end - - self:newCollision(objectlayer.name, object.x, y, z, object.width, object.height, d) -end - -function World3D:addPlayerFromMap(object, i) - local z = object.properties.z or 0 - self:addPlayer(self.obj.Player(self, object.x, object.y, z), i) +function World3D:newPlayer(x, y, z) + return self.obj.Player(self, x, y, z) end -- BODIES MANAGEMENT FUNCTIONS