|
|
|
package entity
|
|
|
|
|
|
|
|
import (
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/hajimehoshi/ebiten/v2"
|
|
|
|
|
|
|
|
"github.com/jakecoffman/cp"
|
|
|
|
|
|
|
|
"code.rocketnine.space/tslocum/doctorlectro/world"
|
|
|
|
|
|
|
|
"code.rocketnine.space/tslocum/doctorlectro/asset"
|
|
|
|
|
|
|
|
"code.rocketnine.space/tslocum/doctorlectro/component"
|
|
|
|
"code.rocketnine.space/tslocum/gohan"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
playerVelocity = 120.0
|
|
|
|
playerGroundAccelTime = 0.1
|
|
|
|
playerGroundAccel = playerVelocity / playerGroundAccelTime
|
|
|
|
playerAirAccelTime = 0.5
|
|
|
|
playerAirAccel = playerVelocity / playerAirAccelTime
|
|
|
|
fallVelocity = 900.0
|
|
|
|
)
|
|
|
|
|
|
|
|
func NewPlayer() gohan.Entity {
|
|
|
|
playerBody := world.Space.AddBody(cp.NewBody(1, cp.INFINITY))
|
|
|
|
playerBody.SetPosition(cp.Vector{0, 0})
|
|
|
|
playerBody.SetVelocityUpdateFunc(playerUpdateVelocity)
|
|
|
|
|
|
|
|
playerShape := world.Space.AddShape(cp.NewCircle(playerBody, 7.5, cp.Vector{}))
|
|
|
|
playerShape.SetElasticity(0)
|
|
|
|
playerShape.SetFriction(0)
|
|
|
|
|
|
|
|
world.PlayerBody = playerBody
|
|
|
|
world.PlayerShape = playerShape
|
|
|
|
|
|
|
|
player := gohan.NewEntity()
|
|
|
|
|
|
|
|
player.AddComponent(&component.Position{
|
|
|
|
Body: world.PlayerBody,
|
|
|
|
})
|
|
|
|
|
|
|
|
player.AddComponent(&component.Velocity{})
|
|
|
|
|
|
|
|
player.AddComponent(&component.Sprite{
|
|
|
|
Frames: asset.PlayerIdleFrames,
|
|
|
|
FrameTime: 150 * time.Millisecond,
|
|
|
|
NumFrames: len(asset.PlayerIdleFrames),
|
|
|
|
Layer: world.LayerPlayer,
|
|
|
|
})
|
|
|
|
|
|
|
|
player.AddComponent(&component.Player{})
|
|
|
|
|
|
|
|
world.PlayerIdleFrames = asset.PlayerIdleFrames
|
|
|
|
world.PlayerWalkFrames = asset.PlayerWalkFrames
|
|
|
|
|
|
|
|
return player
|
|
|
|
}
|
|
|
|
|
|
|
|
func playerUpdateVelocity(body *cp.Body, gravity cp.Vector, damping, dt float64) {
|
|
|
|
var normal cp.Vector
|
|
|
|
var grounded bool
|
|
|
|
world.PlayerBody.EachArbiter(func(arb *cp.Arbiter) {
|
|
|
|
normal = arb.Normal().Neg()
|
|
|
|
if normal.X != 0 || normal.Y != 0 {
|
|
|
|
grounded = true
|
|
|
|
}
|
|
|
|
})
|
|
|
|
world.PlayerNormal = normal
|
|
|
|
world.PlayerGrounded = grounded
|
|
|
|
|
|
|
|
// Apply magnetization by overwriting gravity.
|
|
|
|
// Case MagnetizeDown is not handled because gravity is already set to the normal vector.
|
|
|
|
if world.MagnetActive {
|
|
|
|
switch world.MagnetDirection {
|
|
|
|
case world.MagnetizeDownLeft:
|
|
|
|
gravity = cp.Vector{-world.Gravity / 4, world.Gravity / 4}
|
|
|
|
case world.MagnetizeLeft:
|
|
|
|
gravity = cp.Vector{-world.Gravity, 0}
|
|
|
|
case world.MagnetizeUpLeft:
|
|
|
|
gravity = cp.Vector{-world.Gravity / 4, -world.Gravity / 4}
|
|
|
|
case world.MagnetizeUp:
|
|
|
|
gravity = cp.Vector{0, -world.Gravity}
|
|
|
|
case world.MagnetizeUpRight:
|
|
|
|
gravity = cp.Vector{world.Gravity / 4, -world.Gravity / 4}
|
|
|
|
case world.MagnetizeRight:
|
|
|
|
gravity = cp.Vector{world.Gravity, 0}
|
|
|
|
case world.MagnetizeDownRight:
|
|
|
|
gravity = cp.Vector{world.Gravity / 4, world.Gravity / 4}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
body.UpdateVelocity(gravity, damping, dt)
|
|
|
|
|
|
|
|
xDir := 0.0
|
|
|
|
yDir := 0.0
|
|
|
|
if ebiten.IsKeyPressed(ebiten.KeyW) && world.PlayerGrounded {
|
|
|
|
yDir -= 1
|
|
|
|
world.LastWalkDirU = true
|
|
|
|
}
|
|
|
|
if ebiten.IsKeyPressed(ebiten.KeyS) {
|
|
|
|
yDir += 1
|
|
|
|
world.LastWalkDirU = false
|
|
|
|
}
|
|
|
|
if ebiten.IsKeyPressed(ebiten.KeyA) {
|
|
|
|
xDir -= 1
|
|
|
|
world.LastWalkDirL = false
|
|
|
|
}
|
|
|
|
if ebiten.IsKeyPressed(ebiten.KeyD) {
|
|
|
|
xDir += 1
|
|
|
|
world.LastWalkDirL = true
|
|
|
|
}
|
|
|
|
|
|
|
|
targetVelocity := playerVelocity
|
|
|
|
if world.Debug > 0 && ebiten.IsKeyPressed(ebiten.KeyShift) {
|
|
|
|
targetVelocity *= 4
|
|
|
|
}
|
|
|
|
|
|
|
|
// Target velocities based on user input.
|
|
|
|
targetVx := targetVelocity * xDir
|
|
|
|
targetVy := targetVelocity * yDir
|
|
|
|
if targetVx == 0 {
|
|
|
|
targetVx = gravity.X
|
|
|
|
}
|
|
|
|
if targetVy == 0 {
|
|
|
|
targetVy = gravity.Y
|
|
|
|
}
|
|
|
|
|
|
|
|
v := body.Velocity()
|
|
|
|
vx, vy := cp.Clamp(v.X, -fallVelocity, fallVelocity), cp.Clamp(v.Y, -fallVelocity, fallVelocity)
|
|
|
|
vx, vy = cp.LerpConst(vx, targetVx, playerAirAccel*dt), cp.LerpConst(vy, targetVy, playerAirAccel*dt)
|
|
|
|
body.SetVelocity(vx, vy)
|
|
|
|
}
|