diff options
| author | cursed22bc <admin@pixeldawn.org> | 2026-02-28 12:38:40 +0200 |
|---|---|---|
| committer | cursed22bc <admin@pixeldawn.org> | 2026-02-28 12:38:40 +0200 |
| commit | 6eacf393b370a7586276108705b805e222a069a5 (patch) | |
| tree | f663881c3eda317ff02f4beb6d2b0e1eb7b8db58 /world.lua | |
| parent | 8e3c37d9e3e3a72eb2a6df4d4f112f6ca172fe2d (diff) | |
tile mapping and drawing
Diffstat (limited to 'world.lua')
| -rw-r--r-- | world.lua | 167 |
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 |
