-
Notifications
You must be signed in to change notification settings - Fork 0
/
fly_controllers.py
178 lines (142 loc) · 5.56 KB
/
fly_controllers.py
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
from PyQt4.QtCore import *
import math
import random
random.seed()
def getVectorLength(vector):
return math.sqrt(vector[0]**2 + vector[1]**2)
def getNormalizedVector(vector):
length = getVectorLength(vector)
vector_norm = [vector[0]/length, vector[1]/length]
return vector_norm
#Controllers are responsible for AI of fly
#Separate controller for each state
class FlyController(QObject):
flying = pyqtSignal()
standing = pyqtSignal()
walking = pyqtSignal()
dead = pyqtSignal()
def __init__(self, state_duration=(50, 100)):
super(FlyController, self).__init__()
#Some controllers work only certain time.
#If duration time exceeded then controller emit signal for state change
self._stateMinDuration = state_duration[0]
self._stateMaxDuration = state_duration[1]
self._stateDuration = self._stateMaxDuration
self._started = True
#Reset controller when state is entered
def reset(self):
self._stateDuration = random.randint(self._stateMinDuration, self._stateMaxDuration)
self._started = True
def _isFinished(self):
return self._stateDuration <= 0
#Update method is invoked every game frame
def update(self, fly, world):
self._stateDuration -= 1
#Choose direction and destination point to which fly should move
def _directFly(self, fly, world):
cell = world.grid[fly.cellRow][fly.cellCol]
[x, y] = cell.getRandomPoint([fly.width, fly.height])
x = x - fly.x
y = y - fly.y
vector = getNormalizedVector([x, y])
self._maxPathLength = getVectorLength([x, y])
self._origin = [fly.x, fly.y]
self._direction = vector
fly.direction = vector
#Move fly with small step according fly speed.
#If fly has reached destination then return that fly is stopped
def _moveFly(self, fly, world):
x = fly.x + self._direction[0] * fly.speed
y = fly.y + self._direction[1] * fly.speed
path_length = getVectorLength([x - self._origin[0], y - self._origin[1]])
if path_length >= self._maxPathLength:
self._direction = 0
return 0 #fly stopped
else:
fly.x = x
fly.y = y
fly.mileage += path_length
return 1 #fly moved
class FlyingController(FlyController):
def __init__(self):
super(FlyingController, self).__init__()
self._direction = 0
def update(self, fly, world):
super(FlyingController, self).update(fly, world)
if self._started:
self._started = False
self._direction = 0
if not self._direction:
self._directFly(fly, world)
#If fly has reached choosed point it starts to thinking and switches to standing state
if not self._moveFly(fly, world):
fly.goSlowpoke()
self.standing.emit()
return
class WalkingController(FlyController):
def __init__(self, state_duration):
super(WalkingController, self).__init__(state_duration)
self._direction = 0
def update(self, fly, world):
super(WalkingController, self).update(fly, world)
if self._started:
self._started = False
self._direction = 0
if fly.isDead():
self.dead.emit()
return
#If fly is stopped being stupid or stopped walking then switch to standing state
if (not fly.isSlowpoke()) or self._isFinished():
self.standing.emit()
return
if not self._direction:
self._directFly(fly, world)
self._moveFly(fly, world)
class StandingController(FlyController):
def __init__(self, state_duration):
super(StandingController, self).__init__(state_duration)
def update(self, fly, world):
super(StandingController, self).update(fly, world)
if self._started:
self._started = False
self._direction = 0
if fly.isDead():
self.dead.emit()
return
#If fly is stopped being stupid then try to move to another cell
if not fly.isSlowpoke():
cell_neighbor_ind = random.randint(0, 3) #0 - top, 1 - right, 2 - bottom, 3 - left
next_cell_row = -1
next_cell_col = -1
if cell_neighbor_ind == 0:
next_cell_row = fly.cellRow
next_cell_col = fly.cellCol + 1
elif cell_neighbor_ind == 1:
next_cell_row = fly.cellRow + 1
next_cell_col = fly.cellCol
elif cell_neighbor_ind == 2:
next_cell_row = fly.cellRow
next_cell_col = fly.cellCol - 1
elif cell_neighbor_ind == 3:
next_cell_row = fly.cellRow - 1
next_cell_col = fly.cellCol
next_cell = world.getCell(next_cell_row, next_cell_col)
#If cell exists and available then move to it
if next_cell and next_cell.isAvalible():
current_cell = world.getCell(fly.cellRow, fly.cellCol)
current_cell.removeFly(fly)
fly.cellRow = next_cell_row
fly.cellCol = next_cell_col
next_cell.addFly(fly)
self.flying.emit()
return
else:
fly.goSlowpoke()
if self._isFinished():
self.walking.emit()
class DeadController(FlyController):
def __init__(self):
super(DeadController, self).__init__()
#If fly is dead them do nothing
def update(self, fly, world):
pass