summaryrefslogtreecommitdiff
path: root/player.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 /player.lua
parent8514ffe0a1aa2febe989b2ff0b3044150492a1b2 (diff)
basic water render and physics
Diffstat (limited to 'player.lua')
-rw-r--r--player.lua53
1 files changed, 48 insertions, 5 deletions
diff --git a/player.lua b/player.lua
index 7995cc6..b6bc4b5 100644
--- a/player.lua
+++ b/player.lua
@@ -5,7 +5,8 @@ local Player = {}
Player.__index = Player
setmetatable(Player, { __index = Entity })
-local MOVE_SPEED = 70
+local MOVE_SPEED = 65
+local SWIM_SPEED = 15
local JUMP_FORCE = -200
local GROUND_LAYER = "ground"
@@ -57,6 +58,9 @@ function Player.new(world, spawnX, spawnY)
self.vy = 0
self.grounded = false
+ self.isInLiquid = false
+ self.wasInLiquid = false
+ self.waterSurfaceContact = false
return self
end
@@ -98,6 +102,7 @@ function Player:update(dt)
local c = self.contact or { floor = 0, wall = 0, ceiling = 0 }
local onFloor = c.floor == 1
+ local onWaterSurface = self.waterSurfaceContact
local prevOnFloor = self.wasOnFloor
local prevState = self.state
@@ -105,7 +110,35 @@ function Player:update(dt)
if love.keyboard.isDown("left", "a") then move = move - 1 end
if love.keyboard.isDown("right", "d") then move = move + 1 end
- if onFloor then
+ if self.isInLiquid then
+ local vx, vy = self.body:getLinearVelocity()
+ local mass = self.body:getMass()
+ local gx, gy = self.body:getWorld():getGravity()
+
+ if not self.wasInLiquid then
+ vx = vx * 0.4
+ vy = math.min(vy, 60)
+ self.body:setLinearVelocity(vx, vy)
+ end
+
+ self.body:setLinearDamping(6)
+
+ local buoyancy = 0.9
+ self.body:applyForce(0, -gy * mass * buoyancy)
+
+ local moveY = 0
+ if love.keyboard.isDown("up", "w") then moveY = moveY - 1 end
+ if love.keyboard.isDown("down", "s") then moveY = moveY + 1 end
+
+ local inputLen = math.sqrt(move * move + moveY * moveY)
+ if inputLen > 1 then
+ move = move / inputLen
+ moveY = moveY / inputLen
+ end
+
+ self.body:applyForce(move * SWIM_SPEED, moveY * SWIM_SPEED)
+ elseif onFloor or onWaterSurface then
+ self.body:setLinearDamping(0)
self.availableJumps = 1
if move ~= 0 then
self.lastFacing = move
@@ -114,18 +147,23 @@ function Player:update(dt)
self.body:setLinearVelocity(0, vy)
end
else
+ self.body:setLinearDamping(0)
if move ~= 0 then self.lastFacing = move end
self.body:setLinearVelocity(move * MOVE_SPEED * 0.7, vy)
end
local desiredState
- if onFloor then
+ if self.isInLiquid then
+ desiredState = "swimming"
+ elseif onFloor then
desiredState = (move ~= 0) and "running" or "idle"
else
desiredState = (vy < 0) and "jumping" or "falling"
end
- if self.state == "ground_hit" or self.state == "stop_running" then
+ if self.isInLiquid then
+ self.state = desiredState
+ elseif self.state == "ground_hit" or self.state == "stop_running" then
if not onFloor or self.currentAnim:isFinished() then
self.state = desiredState
end
@@ -143,12 +181,14 @@ function Player:update(dt)
end
self.wasOnFloor = onFloor
+ self.wasInLiquid = self.isInLiquid
local animMap = {
idle = self.animations.idle,
running = self.animations.running,
jumping = self.animations.going_up,
falling = self.animations.going_down,
+ swimming = self.animations.going_down,
stop_running = self.animations.stop_running,
ground_hit = self.animations.ground_hit,
}
@@ -158,7 +198,10 @@ end
function Player:jump()
local c = self.contact or { floor = 0, wall = 0, ceiling = 0 }
- local canJump = (c.floor == 1 or c.wall == 1) and (self.availableJumps or 0) > 0
+ local onWaterSurface = self.waterSurfaceContact
+ local canJump = (c.floor == 1 or c.wall == 1 or onWaterSurface) and (self.availableJumps or 0) > 0
+ if not canJump then return false end
+ if self.isInLiquid and not onWaterSurface then return false end
if canJump then
self.body:setLinearVelocity(self.body:getLinearVelocity(), JUMP_FORCE)
self.state = "jumping"