summaryrefslogtreecommitdiff
path: root/world.lua
diff options
context:
space:
mode:
Diffstat (limited to 'world.lua')
-rw-r--r--world.lua167
1 files changed, 167 insertions, 0 deletions
diff --git a/world.lua b/world.lua
new file mode 100644
index 0000000..2098040
--- /dev/null
+++ b/world.lua
@@ -0,0 +1,167 @@
+local Tilemap = require("tilemap")
+local Entity = require("entity")
+local Camera = require("camera")
+
+local World = {}
+World.__index = World
+
+local GRAVITY = 9.81 * 64
+local PHYSICS_DT = 1 / 60
+
+function World:new()
+ local self = setmetatable({}, World)
+ self.physicsWorld = nil
+ self.tilemap = nil
+ self.mapData = nil
+ self.groundEntities = {}
+ self.player = nil
+ self.enemies = {}
+ self.entities = {}
+ self.camera = nil
+ return self
+end
+
+function World:load(levelPath)
+ if self.physicsWorld then
+ self.groundEntities = {}
+ end
+ self.physicsWorld = love.physics.newWorld(0, GRAVITY)
+ self.physicsWorld:setCallbacks(nil, nil, nil, nil)
+
+ self.tilemap = Tilemap:new(levelPath)
+ self.mapData = self.tilemap:getMapData()
+ if not self.mapData then
+ error("World:load - no map data from " .. tostring(levelPath))
+ end
+
+ local tileWidth = self.tilemap:getTileWidth()
+ local tileHeight = self.tilemap:getTileHeight()
+
+ local groundLayer = self.tilemap:getGroundLayer()
+ if groundLayer and groundLayer.data then
+ local w = self.mapData.width or 0
+ local data = groundLayer.data
+ for i, gid in ipairs(data) do
+ if gid and gid ~= 0 then
+ local idx = i - 1
+ local tx = idx % w
+ local ty = math.floor(idx / w)
+ local x = tx * tileWidth
+ local y = ty * tileHeight
+ local tileEntity = Entity:new(x, y, tileWidth, tileHeight)
+ tileEntity:enablePhysics(self.physicsWorld, "static")
+ table.insert(self.groundEntities, tileEntity)
+ end
+ end
+ end
+
+ self.player = nil
+ self.enemies = {}
+ self.entities = {}
+ local spawns = self.tilemap:getEntitiesSpawns()
+ for _, spawn in ipairs(spawns) do
+ local entityType = spawn:get("entity", "")
+ if entityType == "Player" and not self.player then
+ self.player = Entity:new(spawn.x, spawn.y, spawn.width, spawn.height)
+ self.player:enablePhysics(self.physicsWorld, "dynamic")
+ self.player.isPlayer = true
+ table.insert(self.entities, self.player)
+ else
+ local e = Entity:new(spawn.x, spawn.y, spawn.width, spawn.height)
+ e:setPropertiesFromOptions({ properties = spawn.properties or {}, name = spawn.name, type = spawn.type })
+ if entityType ~= "" then
+ table.insert(self.enemies, e)
+ end
+ table.insert(self.entities, e)
+ end
+ end
+
+end
+
+function World:setCamera(camera)
+ self.camera = camera
+ self.camera:setLimits(self.tilemap:getCameraLimits())
+end
+
+function World:getPlayer()
+ return self.player
+end
+
+function World:getPhysicsWorld()
+ return self.physicsWorld
+end
+
+function World:getMapData()
+ return self.mapData
+end
+
+local function drawTileLayer(layer, tileWidth, tileHeight, tilesetImage, tileQuads)
+ if not layer or not layer.visible or not layer.data then return end
+ local w = layer.width or 0
+ local data = layer.data
+ for i, gid in ipairs(data) do
+ if gid and gid ~= 0 then
+ local idx = i - 1
+ local tx = idx % w
+ local ty = math.floor(idx / w)
+ local x = tx * tileWidth
+ local y = ty * tileHeight
+ if tilesetImage and tileQuads and tileQuads[gid] then
+ love.graphics.draw(tilesetImage, tileQuads[gid], x, y)
+ else
+ local r = ((gid * 17) % 256) / 255
+ local g = ((gid * 31 + 50) % 256) / 255
+ local b = ((gid * 47 + 100) % 256) / 255
+ love.graphics.setColor(r, g, b, 1)
+ love.graphics.rectangle("fill", x, y, tileWidth, tileHeight)
+ love.graphics.setColor(1, 1, 1, 1)
+ end
+ end
+ end
+end
+
+function World:draw()
+ local tw = self.tilemap:getTileWidth()
+ local th = self.tilemap:getTileHeight()
+ local tilesetImage = self.tilemap:getTilesetImage()
+ local tileQuads = self.tilemap:getTileQuads()
+
+ drawTileLayer(self.tilemap:getBackgroundLayer(), tw, th, tilesetImage, tileQuads)
+
+ drawTileLayer(self.tilemap:getGroundLayer(), tw, th, tilesetImage, tileQuads)
+
+ for _, e in ipairs(self.entities) do
+ if e.draw then e:draw() else World.drawEntityDefault(e) end
+ end
+
+ drawTileLayer(self.tilemap:getForegroundLayer(), tw, th, tilesetImage, tileQuads)
+end
+
+-- TODO remove. draw method handled by each entity
+function World.drawEntityDefault(entity)
+ love.graphics.setColor(0.2, 0.6, 1, 1)
+ if entity.isPlayer then
+ love.graphics.setColor(1, 0.3, 0.2, 1)
+ end
+ love.graphics.rectangle("fill", entity.x, entity.y, entity.width, entity.height)
+ love.graphics.setColor(1, 1, 1, 1)
+end
+
+function World:update(dt)
+ if not self.physicsWorld then return end
+ self.physicsWorld:update(PHYSICS_DT)
+
+ if self.camera then
+ self.camera:setTarget(self.player)
+ self.camera:update(dt)
+ end
+
+ for _, e in ipairs(self.entities) do
+ if e.body then
+ e:syncFromPhysicsBody()
+ end
+ if e.update then e:update(dt) end
+ end
+end
+
+return World