/
test_game.py
307 lines (222 loc) · 6.84 KB
/
test_game.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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
#!/usr/bin/env python
class TimeSourceStub(object):
delta = 10
def __init__(self):
self.counter = 0
def now(self):
self.counter += 1
return self.counter
def wait(self, time_point):
print("Waiting for %s" % time_point)
on_schedule = time_point >= self.counter
self.counter = max(self.counter, time_point)
return on_schedule
class Ticker(object):
"""Fake world object."""
mass = 0
radius = 0
def move(self, dt):
print("Tick (%s)" % dt)
class Controller(object):
"""Fake controller."""
def control(self):
print("Controlling the world")
def doctest_PythonTimeSource():
"""Tests for PythonTimeSource
>>> from pyspacewar.game import PythonTimeSource
>>> ts = PythonTimeSource(40)
>>> ts.ticks_per_second
40
>>> round(ts.delta * ts.ticks_per_second, 3)
1.0
You can get a current timestamp and wait for the future
>>> back_then = ts.now()
>>> future = back_then + ts.delta
>>> ts.wait(future)
True
>>> now = ts.now()
>>> eps = 0.01
>>> now >= future - eps or 'error: %r < %r' % (now, future)
True
You can safely wait for the past
>>> ts.wait(back_then)
False
"""
def doctest_Game():
"""Tests for Game
>>> from pyspacewar.game import Game
>>> g = Game()
>>> g.world.objects
[]
>>> g.time_source.ticks_per_second == Game.TICKS_PER_SECOND
True
"""
def doctest_Game_randomly_place_and_position():
"""Tests for Game.randomly_place
Let us create a screaming brick for this test
>>> from pyspacewar.world import Object
>>> class Brick(Object):
... def collision(self, other):
... print("Aaaaargh!")
The game is able to position objects randomly so that they never overlap
>>> from pyspacewar.game import Game
>>> g = Game()
>>> for n in range(100):
... g.randomly_place(Brick(radius=10), 200)
>>> len(g.world.objects)
100
>>> g.world.update(1)
If you do not want to add the object to the world, use randomly_position
instead.
>>> good_place = Brick()
>>> g.randomly_position(good_place, 100)
>>> len(g.world.objects)
100
>>> g.world.add(good_place)
>>> g.world.update(1)
"""
def doctest_Game_respawn():
"""Tests for Game.respawn
>>> from pyspacewar.game import Game
>>> from pyspacewar.world import Ship, Vector
>>> g = Game()
>>> ship = Ship(velocity=Vector(3, 5))
>>> ship.dead = True
A dead ship can come back to life in a new randomly selected place
>>> g.respawn(ship)
>>> ship.velocity
Vector(0, 0)
>>> ship.direction % g.ROTATION_SPEED
0.0
>>> ship.position.length() <= g.respawn_radius
True
>>> ship.dead
False
>>> ship.health
1.0
"""
def doctest_Game_auto_respawn():
"""Tests for Game.auto_respawn
>>> from pyspacewar.game import Game
>>> from pyspacewar.world import Ship
>>> g = Game()
>>> ship1 = Ship()
>>> ship2 = Ship()
>>> ship2.dead = True
>>> g.ships = [ship1, ship2]
The game keeps track of dead ships.
>>> g.auto_respawn()
>>> list(g.timers) == [ship2]
True
>>> g.timers[ship2] == g.respawn_time
True
The timer ticks and ticks
>>> g.auto_respawn()
>>> g.timers[ship2] == g.respawn_time - g.DELTA_TIME
True
and when it reaches zero, the ship comes back to life
>>> g.timers[ship2] = g.DELTA_TIME
>>> g.auto_respawn()
>>> list(g.timers)
[]
>>> ship2.dead
False
"""
def doctest_Game_time_to_respawn():
"""Tests for Game.time_torespawn
>>> from pyspacewar.game import Game
>>> from pyspacewar.world import Ship
>>> g = Game()
>>> ship = Ship()
The game keeps track of dead ships, and keeps a respawn timer for each
of them.
>>> g.timers[ship] = 17.5
You can discover the value of the timer by calling time_to_respawn
>>> g.time_to_respawn(ship)
17.5
If there is no timer for a particular ship ('cause it is not dead),
you will get 0
>>> del g.timers[ship]
>>> g.time_to_respawn(ship)
0
"""
def doctest_Game_skip_a_tick():
"""Tests for Game.skip_a_tick
>>> from pyspacewar.game import Game
>>> g = Game()
>>> ts = g.time_source = TimeSourceStub()
>>> g.world.add(Ticker())
When the game is paused, you should inform it by calling the skip_for_tick
method (so the game won't think the frame rate has dropped and won't start
compensating).
>>> g.skip_a_tick()
>>> g.skip_a_tick()
Waiting for 11
>>> g.skip_a_tick()
Waiting for 22
The waiting time depends on outside delays
>>> ts.counter += 5
>>> g.skip_a_tick()
Waiting for 33
"""
def doctest_Game_wait_for_tick():
"""Tests for Game.wait_for_tick
>>> from pyspacewar.game import Game
>>> g = Game()
>>> ts = g.time_source = TimeSourceStub()
>>> g.world.add(Ticker())
>>> g.controllers.append(Controller())
Initial call to g.wait_for_tick remembers the current time. All other
calls wait the necessary amount. Each call also causes an update in the
game world.
>>> g.wait_for_tick()
True
>>> g.wait_for_tick()
Tick (2.0)
Controlling the world
Waiting for 11
True
>>> g.wait_for_tick()
Tick (2.0)
Controlling the world
Waiting for 21
True
>>> g.wait_for_tick()
Tick (2.0)
Controlling the world
Waiting for 31
True
The waiting time is independent of outside delays
>>> ts.counter += 5
>>> g.wait_for_tick()
Tick (2.0)
Controlling the world
Waiting for 41
True
>>> ts.counter += 105
>>> g.wait_for_tick()
Tick (2.0)
Controlling the world
Waiting for 51
False
After the game world is updated, wait_for_tick also takes care to
look for dead ships.
>>> from pyspacewar.world import Ship
>>> ship = Ship()
>>> ship.dead = True
>>> g.ships.append(ship)
>>> g.wait_for_tick()
Tick (2.0)
Controlling the world
Waiting for 61
False
>>> list(g.timers) == [ship]
True
"""
def doctest_Game_new():
"""Tests for Game.new
>>> from pyspacewar.game import Game
>>> g = Game.new(ships=2)
>>> len(g.ships)
2
"""