carotidartillery/creep.go

172 lines
2.8 KiB
Go
Raw Normal View History

2021-10-06 04:05:02 +00:00
package main
import (
2021-10-08 04:00:33 +00:00
"math"
2021-10-06 04:05:02 +00:00
"math/rand"
"sync"
2021-10-11 06:10:58 +00:00
"time"
2021-10-06 04:05:02 +00:00
"github.com/hajimehoshi/ebiten/v2"
)
2021-10-11 06:10:58 +00:00
const (
TypeVampire = iota
TypeBat
TypeGhost
)
2021-10-06 14:18:38 +00:00
type gameCreep struct {
2021-10-11 06:10:58 +00:00
x, y float64
sprites []*ebiten.Image
frame int
frames int
lastFrame time.Time
creepType int
2021-10-06 04:05:02 +00:00
moveX, moveY float64
tick int
nextAction int
2021-10-08 04:00:33 +00:00
level *Level
player *gamePlayer
2021-10-06 14:18:38 +00:00
2021-10-06 15:03:13 +00:00
health int
2021-10-06 04:05:02 +00:00
sync.Mutex
}
2021-10-11 06:10:58 +00:00
func (c *gameCreep) queueNextAction() {
if c.creepType == TypeBat {
c.nextAction = 288 + rand.Intn(288)
return
}
c.nextAction = 144 + rand.Intn(720)
}
2021-10-12 03:22:13 +00:00
func (c *gameCreep) runAway() {
c.queueNextAction()
randMovementA := (rand.Float64() - 0.5) / 7
randMovementB := (rand.Float64() - 0.5) / 7
c.moveX = c.x - c.player.x
if c.moveX < 0 {
c.moveX = math.Abs(randMovementA) * -1
} else {
c.moveX = math.Abs(randMovementA)
}
c.moveY = c.y - c.player.y
if c.moveY < 0 {
c.moveY = math.Abs(randMovementB) * -1
} else {
c.moveY = math.Abs(randMovementB)
}
c.nextAction *= 2
}
2021-10-06 14:18:38 +00:00
func (c *gameCreep) doNextAction() {
2021-10-11 07:52:48 +00:00
c.queueNextAction()
2021-10-08 04:00:33 +00:00
randMovementA := (rand.Float64() - 0.5) / 7
randMovementB := (rand.Float64() - 0.5) / 7
2021-10-11 07:52:48 +00:00
dx, dy := deltaXY(c.x, c.y, c.player.x, c.player.y)
seekDistance := 7.0
if (dx < seekDistance && dy < seekDistance) || rand.Intn(7) == 0 {
2021-10-08 04:00:33 +00:00
// Seek player.
c.moveX = c.x - c.player.x
if c.moveX < 0 {
c.moveX = math.Abs(randMovementA)
} else {
c.moveX = math.Abs(randMovementA) * -1
}
c.moveY = c.y - c.player.y
if c.moveY < 0 {
c.moveY = math.Abs(randMovementB)
} else {
c.moveY = math.Abs(randMovementB) * -1
}
2021-10-11 07:52:48 +00:00
c.nextAction *= 2
2021-10-08 04:00:33 +00:00
} else {
c.moveX = randMovementA
c.moveY = randMovementB
}
2021-10-06 15:03:13 +00:00
if c.x <= 2 && c.moveX < 0 {
c.moveX *= 1
} else if c.x >= float64(c.level.w-3) && c.moveX > 0 {
c.moveX *= 1
}
if c.y <= 2 && c.moveY > 0 {
c.moveY *= 1
} else if c.y >= float64(c.level.h-3) && c.moveY < 0 {
c.moveY *= 1
}
2021-10-06 04:05:02 +00:00
}
2021-10-06 14:18:38 +00:00
func (c *gameCreep) Update() {
2021-10-06 04:05:02 +00:00
c.Lock()
defer c.Unlock()
2021-10-06 15:03:13 +00:00
if c.health == 0 {
return
}
2021-10-06 04:05:02 +00:00
c.tick++
if c.tick >= c.nextAction {
c.doNextAction()
c.tick = 0
}
2021-10-06 15:03:13 +00:00
x, y := c.x+c.moveX, c.y+c.moveY
clampX, clampY := c.level.Clamp(x, y)
c.x, c.y = clampX, clampY
if clampX != x || clampY != y {
c.nextAction = 0
2021-10-12 03:22:13 +00:00
return
}
if !c.player.repelUntil.IsZero() && c.player.repelUntil.Sub(time.Now()) > 0 {
dx, dy := deltaXY(c.x, c.y, c.player.x, c.player.y)
if dx <= 3 && dy <= 3 {
c.runAway()
}
}
for _, item := range c.level.items {
if item.health == 0 {
continue
}
dx, dy := deltaXY(c.x, c.y, item.x, item.y)
if dx <= 2 && dy <= 2 {
c.runAway()
}
2021-10-06 15:03:13 +00:00
}
2021-10-06 04:05:02 +00:00
}
2021-10-06 14:18:38 +00:00
func (c *gameCreep) Position() (float64, float64) {
2021-10-06 04:05:02 +00:00
c.Lock()
defer c.Unlock()
return c.x, c.y
}
2021-10-11 07:52:48 +00:00
func (c *gameCreep) killScore() int {
switch c.creepType {
case TypeVampire:
return 50
case TypeBat:
return 125
case TypeGhost:
return 75
default:
return 0
}
}