generated from sionleroux/ebitengine-game-template
-
Notifications
You must be signed in to change notification settings - Fork 3
/
spawnpoint.go
160 lines (135 loc) · 4.08 KB
/
spawnpoint.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Use of this source code is subject to an MIT-style
// licence which can be found in the LICENSE file.
package main
import (
"math"
"math/rand"
)
// SpawnPoints is an array of SpawnPoint
type SpawnPoints []*SpawnPoint
// Update updates all the SpawnPoints
func (sps *SpawnPoints) Update(g *GameScreen) {
for _, s := range *sps {
s.Update(g)
}
}
// SpawnPosition describes the spawning position related to the SpawnPoint center
type SpawnPosition struct {
Distance int // Distance of the position from the center
Angle int // Angle of the position
}
// SpawnPoint is a point on the map where zombies are spawn
type SpawnPoint struct {
Position Coord
InitialCount int
Continuous bool
Zombies Zombies
InitialSpawned bool
PrevPosition SpawnPosition
NextSpawn int
CanSpawn bool
ZombieType ZombieType
}
// NextPosition gives the offset of the next spawning to the center of the point
func (s *SpawnPoint) NextPosition() Coord {
// Move further if zombies have been spwaned around the whole circle
if s.PrevPosition.Angle == 0 {
s.PrevPosition.Distance = (s.PrevPosition.Distance+1)%2 + 1
}
// Spawn positions in every 60 degress (360 / 6)
s.PrevPosition.Angle = (s.PrevPosition.Angle + 1) % 6
return Coord{
X: math.Cos(-2*math.Pi/6*float64(s.PrevPosition.Angle)) * float64(s.PrevPosition.Distance),
Y: math.Sin(-2*math.Pi/6*float64(s.PrevPosition.Angle)) * float64(s.PrevPosition.Distance),
}
}
// SpawnZombie spawns one zombie
func (s *SpawnPoint) SpawnZombie(g *GameScreen) {
var np, nc Coord
// At least one of the 12 positions should be OK
for i := 0; i < 12; i++ {
np = s.NextPosition()
nc = Coord{s.Position.X + np.X*32, s.Position.Y + np.Y*32}
if g.LevelMap.isFreeAtCoord(nc) {
break
}
}
var sprites *SpriteSheet
switch s.ZombieType {
case zombieNormal:
fallthrough
case zombieCrawler:
zs := rand.Intn(zombieVariants + 1)
if zs == zombieVariants {
// Crawler
sprites = g.Sprites[spriteZombieCrawler]
s.ZombieType = zombieCrawler
} else {
// Normal
sprites = g.ZombieSprites[zs]
s.ZombieType = zombieNormal
}
case zombieSprinter:
sprites = g.Sprites[spriteZombieSprinter]
case zombieBig:
sprites = g.Sprites[spriteZombieBig]
}
z := NewZombie(s, nc, s.ZombieType, sprites)
z.Target = &g.Player.Object.Position
g.Space.Add(z.Object)
if s.ZombieType == zombieBig {
boss := &Boss{Zombie: z}
g.Zombies = append(g.Zombies, boss)
s.Zombies = append(s.Zombies, boss)
} else {
g.Zombies = append(g.Zombies, z)
s.Zombies = append(s.Zombies, z)
}
s.NextSpawn = 180 + rand.Intn(180)
}
// Update updates the state of the spawn point
func (s *SpawnPoint) Update(g *GameScreen) {
// spawnMaxDistance is the distance where the point is activated, if the player is close enough
var spawnMaxDistance = float64(g.Width)/2 + 150
// spawnMinDistance is the distance where the point is deactivated, if the player is too close
var spawnMinDistance = float64(g.Width)/2 + 50
if s.InitialSpawned && !s.Continuous {
return
}
playerDistance := CalcDistance(s.Position.X, s.Position.Y, g.Player.Object.Position.X, g.Player.Object.Position.Y)
// Spawn point is activated if the player is close enougn, but not too close
if playerDistance < spawnMaxDistance && playerDistance > spawnMinDistance {
if !s.InitialSpawned || (g.Tick%s.NextSpawn == 0 && len(s.Zombies) < s.InitialCount) {
s.CanSpawn = true
}
}
if s.CanSpawn {
if !s.InitialSpawned {
for i := 0; i < s.InitialCount; i++ {
s.SpawnZombie(g)
}
s.InitialSpawned = true
} else {
s.SpawnZombie(g)
}
s.CanSpawn = false
}
}
// RemoveZombie removes a dead zombie from the zombie array of the SpawnPoint
func (s *SpawnPoint) RemoveZombie(z Zombielike) {
for i, sz := range s.Zombies {
if sz == z {
s.Zombies[i] = nil
s.Zombies = append((s.Zombies)[:i], (s.Zombies)[i+1:]...)
}
}
}
// Reset removes all the zombies and sets the initial state of the SpawnPoint
func (s *SpawnPoint) Reset() {
for i, _ := range s.Zombies {
s.Zombies[i] = nil
}
s.Zombies = Zombies{}
s.InitialSpawned = false
s.PrevPosition = SpawnPosition{0, 0}
}