doodle/pkg/player_physics.go

138 lines
3.8 KiB
Go

package doodle
// Subset of the PlayScene that is responsible for movement of the player character.
import (
"git.kirsle.net/SketchyMaze/doodle/pkg/balance"
"git.kirsle.net/SketchyMaze/doodle/pkg/keybind"
"git.kirsle.net/SketchyMaze/doodle/pkg/physics"
"git.kirsle.net/SketchyMaze/doodle/pkg/shmem"
"git.kirsle.net/go/render/event"
)
// movePlayer updates the player's X,Y coordinate based on key pressed.
func (s *PlayScene) movePlayer(ev *event.State) {
var (
playerSpeed = float64(balance.PlayerMaxVelocity)
velocity = s.Player.Velocity()
direction float64
jumping bool
phys = s.playerPhysics
// holdingJump bool // holding down the jump button vs. tapping it
)
if s.slippery {
phys = s.slipperyPhysics
}
// Antigravity: player can move anywhere with arrow keys.
if s.antigravity || !s.Player.HasGravity() {
velocity.X = 0
velocity.Y = 0
// Shift to slow your roll to 1 pixel per tick.
if keybind.Shift(ev) {
playerSpeed = 1
}
if keybind.Left(ev) {
velocity.X = -playerSpeed
} else if keybind.Right(ev) {
velocity.X = playerSpeed
}
if keybind.Up(ev) {
velocity.Y = -playerSpeed
} else if keybind.Down(ev) {
velocity.Y = playerSpeed
}
} else {
// Moving left or right.
if keybind.Left(ev) {
direction = -1
} else if keybind.Right(ev) {
direction = 1
}
// Up button to signal they want to jump.
if keybind.Up(ev) {
if s.Player.IsWet() {
// If they are holding Up put a cooldown in how fast they can swim
// to the surface. Tapping the Jump button allows a faster ascent.
if shmem.Tick > s.jumpCooldownUntil {
s.jumpCooldownUntil = shmem.Tick + balance.SwimJumpCooldown
velocity.Y = balance.SwimJumpVelocity
}
} else if s.Player.Grounded() {
velocity.Y = balance.PlayerJumpVelocity
}
} else {
s.jumpCooldownUntil = 0
if velocity.Y < 0 {
velocity.Y = 0
}
}
// Moving left or right? Interpolate their velocity by acceleration.
if direction != 0 {
if s.playerLastDirection != direction {
velocity.X = 0
}
// TODO: fast turn-around if they change directions so they don't
// slip and slide while their velocity updates.
velocity.X = physics.Lerp(
velocity.X,
direction*phys.MaxSpeed.X,
phys.Acceleration,
)
} else {
// Slow them back to zero using friction.
velocity.X = physics.Lerp(
velocity.X,
0,
phys.Friction,
)
}
// Moving upwards (jumping): give them full acceleration upwards.
if jumping {
velocity.Y = -playerSpeed
}
// While in the air, count down their jump counter; when zero they
// cannot jump again until they touch ground.
if !s.Player.Grounded() {
s.playerJumpCounter--
}
}
s.playerLastDirection = direction
// Move the player unless frozen.
// TODO: if Y=0 then gravity fails, but not doing this allows the
// player to jump while frozen. Not a HUGE deal right now as only Warp Doors
// freeze the player currently but do address this later.
if s.Player.IsFrozen() {
velocity.X = 0
}
s.Player.SetVelocity(velocity)
// If the "Use" key is pressed, set an actor flag on the player.
s.Player.SetUsing(keybind.Use(ev))
// Camera behaviors: Anvils can take the camera's focus while they're falling
// but player inputs will take control back to the player. Most anvils will fall
// a couple pixels upon level load - prevent them taking the camera's focus for
// the first few frames of gameplay.
if s.mustFollowPlayerUntil == 0 {
s.mustFollowPlayerUntil = shmem.Tick + balance.FollowPlayerFirstTicks
}
// If we insist that the canvas follow the player doodad.
if shmem.Tick < s.mustFollowPlayerUntil || keybind.Up(ev) || keybind.Left(ev) || keybind.Right(ev) || keybind.Use(ev) {
s.drawing.FollowActor = s.Player.ID()
}
s.scripting.To(s.Player.ID()).Events.RunKeypress(keybind.FromEvent(ev))
}