summaryrefslogtreecommitdiff
path: root/world.lua
diff options
context:
space:
mode:
authorcursed22bc <admin@pixeldawn.org>2026-03-07 23:43:32 +0200
committercursed22bc <admin@pixeldawn.org>2026-03-07 23:43:32 +0200
commitaeb596379bbf1bec84efb294ff5bbbee922364ba (patch)
treedeaf13edba484c5d4013dfd094e515b103e2c9d9 /world.lua
parent8514ffe0a1aa2febe989b2ff0b3044150492a1b2 (diff)
basic water render and physics
Diffstat (limited to 'world.lua')
-rw-r--r--world.lua87
1 files changed, 86 insertions, 1 deletions
diff --git a/world.lua b/world.lua
index 16324bb..5eaf1ce 100644
--- a/world.lua
+++ b/world.lua
@@ -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)