-
Notifications
You must be signed in to change notification settings - Fork 1
/
enemy.go
127 lines (114 loc) · 2.44 KB
/
enemy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package main
import (
"math/rand"
"github.com/faiface/pixel"
"golang.org/x/image/colornames"
)
type Slime struct {
Entity
speed float64
drainRate float64
rotation float64
fixedDirection pixel.Vec
fixed bool
Alive bool
}
func NewSlime(spr *pixel.Sprite) *Slime {
sl := &Slime{Entity: *NewEntity(spr, pixel.ZV)}
sl.ScaleXY = pixel.V(1, 1)
sl.Color = colornames.Red
s := float64(world.gridSize) / 2.5
r := pixel.R(-s, -s, s, s)
sl.Collider = &r
sl.speed = 40
sl.drainRate = 120
sl.Active = false
sl.Visible = false
sl.Alive = false
return sl
}
func (s *Slime) Spawn() {
p := world.RandomVec()
for hero.Pos.Sub(p).Len() < 102 {
p = world.RandomVec()
}
s.Pos = p
s.rotation = rand.Float64() + 0.2
s.speed = s.rotation*40 + 30 + engine.elapsed/5
// s.speed /= 1000
s.Active = true
s.Visible = true
s.Alive = true
}
func (s *Slime) Kill() {
s.Alive = false
s.Color = colornames.Grey
}
func (s *Slime) Update(arrows []*Arrow) {
// Slimes should "see" the player and fly to touch the player.
// TODO: Implement spiralled movement.
if !s.Alive || !s.Active {
return
}
var dir pixel.Vec
dir = hero.Pos.Sub(s.Pos).Unit()
if s.fixed {
// Slime sticks to some constant directing until it goes out of range.
dir = s.fixedDirection.Add(dir.Scaled(0.5)).Unit()
}
delta := dir.Scaled(s.speed * engine.dt)
s.Pos = s.Pos.Add(delta)
s.Angle += (s.rotation + 0.2) * engine.dt
wallCollided := false
wcol := s.AbsCollider()
if collides(wcol, hero.AbsCollider()) {
hero.Damage(-s.drainRate * engine.dt)
hero.SlowDown(0.7)
} else {
colWorld := s.AbsCollider()
walls := world.GetColliders(colWorld)
c := colWorld.Moved(delta)
for _, wall := range walls {
if collides(c, wall) {
s.Pos = s.Pos.Sub(delta)
wallCollided = true
if s.fixed {
s.fixed = false
}
}
}
}
diff := hero.Pos.Sub(s.Pos).Len()
if diff <= 92 && !wallCollided {
if diff < 48 && !s.fixed {
s.fixedDirection = dir
s.fixed = true
}
rate := (42 - diff) / 92
// Speed up when diff==92 and then slow down when diff < 32
s.Pos = s.Pos.Sub(delta.Scaled(rate))
} else if s.fixed {
s.fixed = false
}
if diff < 92 {
rate := (92 - diff) / 300
s.Angle += rate
}
for _, arrow := range arrows {
if arrow.Kills(wcol) {
s.Kill()
arrow.Stick()
break
}
}
}
func firstFreeSlime(s []*Slime) int {
free := -1
for i := range s {
if !s[i].Active {
free = i
break
}
}
return free
}