doodle/pkg/player_physics.go
Noah Petherbridge 94d0da78e7 Swimming Physics and Bubble Pattern
Water pixels finally do something other than turn your character blue!

* When the player character is "wet" (touching water pixels, and so appearing in
  a blue mask), water physics apply: gravity is slower, your jump height is
  halved, but you get infinite jumps to swim higher in the water.
* Holding the jump key under water will incur a short delay between jumps, so
  that you don't just fly straight up to the surface. Tap the jump button to
  move up quicker, you can spam it all you want.

Azulians are also able to handle being under water:

* They'll sink to the bottom and keep walking back and forth normally.
* If you are above them and noticed, they'll jump (swim) up towards you,
  aware of the water and it jumps like you do.
* The Blue Azulian has the poorest vertical aggro range so it isn't a
  very good swimmer. The White Azulian is very good at navigating water
  as it can pursue the player from the furthest distance of them all.

Changes to the editor:

* New brush pattern added: bubbles.png
  * It's the default pattern now for the "water" color of all
    of the built-in palettes instead of ink.png
  * A repeating pattern of bubbles carved out showing the
    level wallpaper.
  * The old "Bubbles (circles.png)" is renamed "Circles"
* The last scroll position is saved with the Level file, so when you reload
  the level later it's scrolled at where you left it.
2022-05-05 21:35:32 -07:00

120 lines
3.1 KiB
Go

package doodle
// Subset of the PlayScene that is responsible for movement of the player character.
import (
"git.kirsle.net/apps/doodle/pkg/balance"
"git.kirsle.net/apps/doodle/pkg/keybind"
"git.kirsle.net/apps/doodle/pkg/physics"
"git.kirsle.net/apps/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
// holdingJump bool // holding down the jump button vs. tapping it
)
// 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*s.playerPhysics.MaxSpeed.X,
s.playerPhysics.Acceleration,
)
} else {
// Slow them back to zero using friction.
velocity.X = physics.Lerp(
velocity.X,
0,
s.playerPhysics.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))
s.scripting.To(s.Player.ID()).Events.RunKeypress(keybind.FromEvent(ev))
}