diff options
| author | cursed22bc <admin@pixeldawn.org> | 2026-03-07 23:43:32 +0200 |
|---|---|---|
| committer | cursed22bc <admin@pixeldawn.org> | 2026-03-07 23:43:32 +0200 |
| commit | aeb596379bbf1bec84efb294ff5bbbee922364ba (patch) | |
| tree | deaf13edba484c5d4013dfd094e515b103e2c9d9 /world.lua | |
| parent | 8514ffe0a1aa2febe989b2ff0b3044150492a1b2 (diff) | |
basic water render and physics
Diffstat (limited to 'world.lua')
| -rw-r--r-- | world.lua | 87 |
1 files changed, 86 insertions, 1 deletions
@@ -18,8 +18,12 @@ function World:new() self.player = nil self.enemies = {} self.entities = {} + self.liquidPolygons = {} + self.liquidSurfaces = {} + self.liquidSurfaceFixtures = {} self.camera = nil self.groundContacts = {} + self.waterContacts = {} self.contactCounts = {} self.contactEntity = {} self.contactKind = {} @@ -94,6 +98,9 @@ function World:load(mapPath, tilesets) self.player = nil self.enemies = {} self.entities = {} + self.liquidPolygons = self.tilemap:getEntitiesLiquidPolygons() or {} + self.liquidSurfaces = self.tilemap:getEntitiesLiquidSurfaces() or {} + self.liquidSurfaceFixtures = {} local spawns = self.tilemap:getEntitiesSpawns() for _, spawn in ipairs(spawns) do local entityType = spawn:get("entity", "") @@ -111,6 +118,17 @@ function World:load(mapPath, tilesets) end end + for _, surface in ipairs(self.liquidSurfaces) do + local cx = (surface.x or 0) + (surface.width or 0) * 0.5 + local cy = (surface.y or 0) + (surface.height or 0) * 0.5 + local body = love.physics.newBody(self.physicsWorld, cx, cy, "static") + local shape = love.physics.newRectangleShape(surface.width or 0, surface.height or 0) + local fixture = love.physics.newFixture(body, shape, 1) + fixture:setSensor(true) + fixture:setUserData({ type = "water", water = surface }) + table.insert(self.liquidSurfaceFixtures, { body = body, fixture = fixture }) + end + end function World:_addContact(entity, kind) @@ -166,6 +184,28 @@ function World:_onBeginContact(udA, udB, nx, ny, contact) self.groundContacts[udA] = (self.groundContacts[udA] or 0) + 1 if self:_isPlayerLike(udA) then udA.grounded = true end end + + local function doWaterSplash(waterData, entity) + if not (waterData and waterData.water and waterData.water.splash) then return end + local centerX = 0 + local ok, x1, y1, x2, y2 = pcall(function() return contact:getPositions() end) + if ok and x1 then + centerX = (x1 + (x2 or x1)) * 0.5 + elseif entity and entity.body then + centerX = entity.body:getX() + else + centerX = waterData.water.x or 0 + end + waterData.water:splash(centerX, 2) + end + + if type(udA) == "table" and udA.type == "water" and self:_isTrackedEntity(udB) then + self.waterContacts[udB] = (self.waterContacts[udB] or 0) + 1 + doWaterSplash(udA, udB) + elseif type(udB) == "table" and udB.type == "water" and self:_isTrackedEntity(udA) then + self.waterContacts[udA] = (self.waterContacts[udA] or 0) + 1 + doWaterSplash(udB, udA) + end end function World:_onEndContact(udA, udB, contact) @@ -176,6 +216,11 @@ function World:_onEndContact(udA, udB, contact) self.contactEntity[contact] = nil self.contactKind[contact] = nil end + if type(udA) == "table" and udA.type == "water" and self:_isTrackedEntity(udB) then + self.waterContacts[udB] = math.max(0, (self.waterContacts[udB] or 0) - 1) + elseif type(udB) == "table" and udB.type == "water" and self:_isTrackedEntity(udA) then + self.waterContacts[udA] = math.max(0, (self.waterContacts[udA] or 0) - 1) + end if udA == "ground" and self:_isTrackedEntity(udB) then self.groundContacts[udB] = math.max(0, (self.groundContacts[udB] or 0) - 1) if self:_isPlayerLike(udB) then @@ -223,7 +268,6 @@ local function drawTileLayer(layer, mapTileW, mapTileH, tileGidInfo, viewMinX, v minRow, maxRow = 0, h - 1 end - -- Collect tiles by image for SpriteBatch (reduces 770 draw calls to 1-2 batch draws) local batches = {} local fallbacks = {} local data = layer.data @@ -284,6 +328,27 @@ function World:draw() drawTileLayer(self.tilemap:getBackgroundLayer(), mapTileW, mapTileH, tileGidInfo, viewMinX, viewMinY, viewMaxX, viewMaxY) drawTileLayer(self.tilemap:getGroundLayer(), mapTileW, mapTileH, tileGidInfo, viewMinX, viewMinY, viewMaxX, viewMaxY) + love.graphics.setColor(0.25, 0.5, 0.9, 0.6) + +for _, liquid in ipairs(self.liquidPolygons) do + if liquid.triangles then + for _, tri in ipairs(liquid.triangles) do + love.graphics.polygon("fill", tri) + end + end +end + +love.graphics.setColor(1,1,1,1) + +for _, surface in ipairs(self.liquidSurfaces) do + if surface.draw then + surface:draw() + end +end + +for _, p in ipairs(self.liquidPolygons) do + love.graphics.circle("fill", p.x, p.y, 3) +end for _, e in ipairs(self.entities) do if e.draw then e:draw() else World.drawEntityDefault(e) end end @@ -328,9 +393,29 @@ function World:update(dt) if e.body then e:syncFromPhysicsBody() end + end + + if self.player then + self.player.isInLiquid = false + self.player.waterSurfaceContact = (self.waterContacts[self.player] or 0) > 0 + for _, liquid in ipairs(self.liquidPolygons) do + if liquid:containsEntity(self.player) then self.player.isInLiquid = true break end + end + end + + + for _, e in ipairs(self.entities) do if e.update then e:update(dt) end end + for _, liquid in ipairs(self.liquidPolygons) do + if liquid.update then liquid:update(dt) end + end + + for _, surface in ipairs(self.liquidSurfaces) do + if surface.update then surface:update(dt) end + end + if self.camera then self.camera:setTarget(self.player) self.camera:update(dt) |
