You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
268 lines
7.1 KiB
Go
268 lines
7.1 KiB
Go
package system
|
|
|
|
import (
|
|
"image"
|
|
"log"
|
|
"os"
|
|
|
|
"code.rocketnine.space/tslocum/doctorlectro/asset"
|
|
|
|
"code.rocketnine.space/tslocum/doctorlectro/entity"
|
|
|
|
"code.rocketnine.space/tslocum/doctorlectro/component"
|
|
"code.rocketnine.space/tslocum/doctorlectro/world"
|
|
"code.rocketnine.space/tslocum/gohan"
|
|
"github.com/hajimehoshi/ebiten/v2"
|
|
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
|
)
|
|
|
|
type playerMoveSystem struct {
|
|
Position *component.Position
|
|
Velocity *component.Velocity
|
|
Sprite *component.Sprite
|
|
Player *component.Player
|
|
}
|
|
|
|
func NewPlayerMoveSystem() *playerMoveSystem {
|
|
return &playerMoveSystem{}
|
|
}
|
|
|
|
func (s *playerMoveSystem) Update(e gohan.Entity) error {
|
|
if ebiten.IsKeyPressed(ebiten.KeyEscape) && !world.DisableEsc {
|
|
os.Exit(0)
|
|
return nil
|
|
}
|
|
|
|
if world.GameOver {
|
|
return nil
|
|
}
|
|
|
|
if ebiten.IsKeyPressed(ebiten.KeyControl) && inpututil.IsKeyJustPressed(ebiten.KeyV) {
|
|
v := world.Debug + 1
|
|
if v > 2 {
|
|
v = 0
|
|
}
|
|
world.Debug = v
|
|
return nil
|
|
}
|
|
|
|
// Find the nearest surface and magnetize.
|
|
magnetActive := ebiten.IsKeyPressed(ebiten.KeySpace) && world.CanMagnetize
|
|
if magnetActive {
|
|
printCollision := func(m string) {
|
|
if world.Debug > 1 {
|
|
log.Println(m)
|
|
}
|
|
}
|
|
|
|
boxOffset := 4
|
|
collisionSize := 12
|
|
wallThreshold := 16
|
|
position := world.PlayerBody.Position()
|
|
|
|
px1, py1 := int(position.X)+boxOffset, int(position.Y)+boxOffset
|
|
px2, py2 := px1+collisionSize-(boxOffset*2), py1+collisionSize-(boxOffset*2)
|
|
|
|
playerRectD := image.Rect(px1, py1, px2, py2+wallThreshold)
|
|
playerRectDL := image.Rect(px1-wallThreshold, py1, px2, py2+wallThreshold)
|
|
playerRectL := image.Rect(px1-wallThreshold, py1, px2, py2)
|
|
playerRectUL := image.Rect(px1-wallThreshold, py1-wallThreshold, px2, py2)
|
|
playerRectU := image.Rect(px1, py1-wallThreshold, px2, py2)
|
|
playerRectUR := image.Rect(px1, py1-wallThreshold, px2+wallThreshold, py2)
|
|
playerRectR := image.Rect(px1, py1, px2+wallThreshold, py2)
|
|
playerRectDR := image.Rect(px1, py1, px2+wallThreshold, py2+wallThreshold)
|
|
|
|
var (
|
|
collideL bool
|
|
collideR bool
|
|
collideU bool
|
|
collideD bool
|
|
collideUL bool
|
|
collideUR bool
|
|
collideDL bool
|
|
collideDR bool
|
|
)
|
|
checkCollisions := func(r image.Rectangle) {
|
|
if !collideL && r.Overlaps(playerRectL) {
|
|
collideL = true
|
|
}
|
|
if !collideR && r.Overlaps(playerRectR) {
|
|
collideR = true
|
|
}
|
|
if !collideU && r.Overlaps(playerRectU) {
|
|
collideU = true
|
|
}
|
|
if !collideD && r.Overlaps(playerRectD) {
|
|
collideD = true
|
|
}
|
|
if !collideUL && r.Overlaps(playerRectUL) {
|
|
collideUL = true
|
|
}
|
|
if !collideUR && r.Overlaps(playerRectUR) {
|
|
collideUR = true
|
|
}
|
|
if !collideDL && r.Overlaps(playerRectDL) {
|
|
collideDL = true
|
|
}
|
|
if !collideDR && r.Overlaps(playerRectDR) {
|
|
collideDR = true
|
|
}
|
|
}
|
|
for i := range world.MetalRects {
|
|
checkCollisions(world.MetalRects[i])
|
|
}
|
|
for i := range world.DestructibleRects {
|
|
checkCollisions(world.DestructibleRects[i])
|
|
}
|
|
printCollision("COLLIDE")
|
|
if collideD {
|
|
if collideR {
|
|
world.MagnetDirection = world.MagnetizeDownRight
|
|
printCollision("DOWN RIGHT")
|
|
} else if collideL {
|
|
world.MagnetDirection = world.MagnetizeDownLeft
|
|
printCollision("DOWN LEFT")
|
|
} else {
|
|
world.MagnetDirection = world.MagnetizeDown
|
|
printCollision("DOWN")
|
|
}
|
|
} else if collideU {
|
|
printCollision("U")
|
|
if collideR {
|
|
world.MagnetDirection = world.MagnetizeUpRight
|
|
printCollision("UP RIGHT")
|
|
} else if collideL {
|
|
world.MagnetDirection = world.MagnetizeUpLeft
|
|
printCollision("UP LEFT")
|
|
} else {
|
|
world.MagnetDirection = world.MagnetizeUp
|
|
printCollision("UP")
|
|
}
|
|
} else if collideR {
|
|
printCollision("R")
|
|
if collideU {
|
|
world.MagnetDirection = world.MagnetizeUpRight
|
|
printCollision("UP RIGHT")
|
|
} else if collideD {
|
|
world.MagnetDirection = world.MagnetizeDownRight
|
|
printCollision("DOWN RIGHT")
|
|
} else {
|
|
world.MagnetDirection = world.MagnetizeRight
|
|
printCollision("RIGHT")
|
|
}
|
|
} else if collideL {
|
|
printCollision("L")
|
|
if collideU {
|
|
world.MagnetDirection = world.MagnetizeUpLeft
|
|
printCollision("UP LEFT")
|
|
} else if collideD {
|
|
world.MagnetDirection = world.MagnetizeDownLeft
|
|
printCollision("DOWN LEFT")
|
|
} else {
|
|
world.MagnetDirection = world.MagnetizeLeft
|
|
printCollision("LEFT")
|
|
}
|
|
} else if collideUL {
|
|
printCollision("UL")
|
|
world.MagnetDirection = world.MagnetizeUpLeft
|
|
} else if collideUR {
|
|
printCollision("UR")
|
|
world.MagnetDirection = world.MagnetizeUpRight
|
|
} else if collideDL {
|
|
printCollision("DL")
|
|
world.MagnetDirection = world.MagnetizeDownLeft
|
|
} else if collideDR {
|
|
printCollision("DR")
|
|
world.MagnetDirection = world.MagnetizeDownRight
|
|
} else {
|
|
printCollision("NONE")
|
|
magnetActive = false
|
|
}
|
|
}
|
|
world.MagnetActive = magnetActive
|
|
|
|
// Jump.
|
|
grounded := world.PlayerNormal.X != 0 || world.PlayerNormal.Y != 0
|
|
if inpututil.IsKeyJustPressed(ebiten.KeyJ) && grounded && world.CanJump {
|
|
const jumpVelocity = 333
|
|
vel := world.PlayerBody.Velocity()
|
|
switch world.PlayerDirection {
|
|
case world.MagnetizeDown:
|
|
vel.Y = -jumpVelocity
|
|
case world.MagnetizeDownLeft:
|
|
vel.X = jumpVelocity / 2
|
|
vel.Y = -jumpVelocity / 2
|
|
case world.MagnetizeLeft:
|
|
vel.X = jumpVelocity
|
|
case world.MagnetizeUpLeft:
|
|
vel.X = jumpVelocity / 2
|
|
vel.Y = jumpVelocity / 2
|
|
case world.MagnetizeUp:
|
|
vel.Y = jumpVelocity
|
|
case world.MagnetizeUpRight:
|
|
vel.X = -jumpVelocity / 2
|
|
vel.Y = jumpVelocity / 2
|
|
case world.MagnetizeRight:
|
|
vel.X = -jumpVelocity
|
|
case world.MagnetizeDownRight:
|
|
vel.X = -jumpVelocity / 2
|
|
vel.Y = -jumpVelocity / 2
|
|
}
|
|
world.PlayerBody.SetVelocity(vel.X, vel.Y)
|
|
}
|
|
|
|
// Fire.
|
|
const fireRate = 144 / 2
|
|
if ebiten.IsKeyPressed(ebiten.KeyK) && world.CanFire && (world.LastFire == 0 || world.Tick-world.LastFire >= fireRate) {
|
|
asset.SoundFire.Rewind()
|
|
asset.SoundFire.Play()
|
|
|
|
bullet := entity.NewBullet()
|
|
playerPosition := world.PlayerBody.Position()
|
|
bullet.With(func(position *component.Position, velocity *component.Velocity) {
|
|
bulletSpeed := 8.0
|
|
switch world.PlayerDirection {
|
|
case world.MagnetizeDown:
|
|
if world.LastWalkDirL {
|
|
velocity.X, velocity.Y = bulletSpeed, 0
|
|
} else {
|
|
velocity.X, velocity.Y = -bulletSpeed, 0
|
|
}
|
|
position.X, position.Y = playerPosition.X-2, playerPosition.Y-9
|
|
case world.MagnetizeLeft:
|
|
if world.LastWalkDirU {
|
|
velocity.X, velocity.Y = 0, -bulletSpeed
|
|
} else {
|
|
velocity.X, velocity.Y = 0, bulletSpeed
|
|
}
|
|
position.X, position.Y = playerPosition.X+7, playerPosition.Y-2
|
|
case world.MagnetizeUp:
|
|
if world.LastWalkDirL {
|
|
velocity.X, velocity.Y = bulletSpeed, 0
|
|
} else {
|
|
velocity.X, velocity.Y = -bulletSpeed, 0
|
|
}
|
|
position.X, position.Y = playerPosition.X-2, playerPosition.Y+7
|
|
case world.MagnetizeRight:
|
|
if world.LastWalkDirU {
|
|
velocity.X, velocity.Y = 0, -bulletSpeed
|
|
} else {
|
|
velocity.X, velocity.Y = 0, bulletSpeed
|
|
}
|
|
position.X, position.Y = playerPosition.X-9, playerPosition.Y-2
|
|
}
|
|
})
|
|
|
|
world.LastFire = world.Tick
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *playerMoveSystem) Draw(_ gohan.Entity, _ *ebiten.Image) error {
|
|
return gohan.ErrUnregister
|
|
}
|
|
|
|
func (s *playerMoveSystem) updateSprite() {
|
|
}
|