diff options
Diffstat (limited to 'player.lua')
| -rw-r--r-- | player.lua | 53 |
1 files changed, 48 insertions, 5 deletions
@@ -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" |
