You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
3.5 KiB
134 lines
3.5 KiB
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) |
|
}
|
|
|