comparison pytouhou/game/enemymanager.py @ 83:fc0294c745b6

Basic bullet handling! Clean up as soon as possible :p
author Thibaut Girka <thib@sitedethib.com>
date Sat, 03 Sep 2011 22:22:58 +0200
parents ffe2c2b9912c
children 3804f07d3b0e
comparison
equal deleted inserted replaced
82:de48213a02bf 83:fc0294c745b6
19 from struct import unpack, pack 19 from struct import unpack, pack
20 from pytouhou.utils.interpolator import Interpolator 20 from pytouhou.utils.interpolator import Interpolator
21 from pytouhou.vm.eclrunner import ECLRunner 21 from pytouhou.vm.eclrunner import ECLRunner
22 from pytouhou.vm.anmrunner import ANMRunner 22 from pytouhou.vm.anmrunner import ANMRunner
23 from pytouhou.game.sprite import Sprite 23 from pytouhou.game.sprite import Sprite
24 from pytouhou.game.bullet import Bullet
24 from math import cos, sin, atan2, pi 25 from math import cos, sin, atan2, pi
25 26
26 27
27 class Enemy(object): 28 class Enemy(object):
28 def __init__(self, pos, life, _type, anm_wrapper, game_state): 29 def __init__(self, pos, life, _type, anm_wrapper, game_state):
40 self.life = life 41 self.life = life
41 self.max_life = life 42 self.max_life = life
42 self.touchable = True 43 self.touchable = True
43 self.damageable = True 44 self.damageable = True
44 self.death_flags = 0 45 self.death_flags = 0
45 self.pending_bullets = [] 46 self.bullets = []
46 self.extended_bullet_attributes = (0, 0, 0, 0, 0., 0., 0., 0.) 47 self.extended_bullet_attributes = (0, 0, 0, 0, 0., 0., 0., 0.)
47 self.bullet_attributes = None 48 self.bullet_attributes = None
48 self.bullet_launch_offset = (0, 0) 49 self.bullet_launch_offset = (0, 0)
49 self.death_callback = None 50 self.death_callback = None
50 self.low_life_callback = None 51 self.low_life_callback = None
54 self.remaining_lives = -1 55 self.remaining_lives = -1
55 56
56 self.automatic_orientation = False 57 self.automatic_orientation = False
57 58
58 self.bullet_launch_interval = 0 59 self.bullet_launch_interval = 0
60 self.bullet_launch_timer = 0
59 self.delay_attack = False 61 self.delay_attack = False
60 62
61 self.death_anim = None 63 self.death_anim = None
62 self.movement_dependant_sprites = None 64 self.movement_dependant_sprites = None
63 self.direction = None 65 self.direction = None
70 72
71 self.hitbox = (0, 0) 73 self.hitbox = (0, 0)
72 self.screen_box = None 74 self.screen_box = None
73 75
74 76
75 def set_bullet_attributes(self, type_, bullet_anim, launch_anim, 77 def set_bullet_attributes(self, type_, anim, sprite_idx_offset,
76 bullets_per_shot, number_of_shots, speed, speed2, 78 bullets_per_shot, number_of_shots, speed, speed2,
77 launch_angle, angle, flags): 79 launch_angle, angle, flags):
78 self.bullet_attributes = (type_, bullet_anim, launch_anim, bullets_per_shot, 80 self.bullet_attributes = (type_, anim, sprite_idx_offset, bullets_per_shot,
79 number_of_shots, speed, speed2, launch_angle, 81 number_of_shots, speed, speed2, launch_angle,
80 angle, flags) 82 angle, flags)
81 if not self.delay_attack: 83 if not self.delay_attack:
82 self.fire() 84 self.fire()
83 85
84 86
85 def fire(self): 87 def fire(self):
86 (type_, bullet_anim, launch_anim, bullets_per_shot, number_of_shots, 88 (type_, anim, sprite_idx_offset, bullets_per_shot, number_of_shots,
87 speed, speed2, launch_angle, angle, flags) = self.bullet_attributes 89 speed, speed2, launch_angle, angle, flags) = self.bullet_attributes
90
91 self.bullet_launch_timer = 0
92
93 player = self.select_player()
94
88 if type_ in (67, 69, 71): 95 if type_ in (67, 69, 71):
89 launch_angle += self.get_player_angle() 96 launch_angle += self.get_player_angle(player)
90 if type_ in (69, 70, 71): 97 if type_ in (69, 70, 71):
91 angle = 2. * pi / bullets_per_shot 98 angle = 2. * pi / bullets_per_shot
92 if type_ == 71: 99 if type_ == 71:
93 launch_angle += pi / bullets_per_shot 100 launch_angle += pi / bullets_per_shot
94 #TODO 101
95 pass 102 launch_angle -= angle * (bullets_per_shot - 1) / 2.
103
104 for shot_nb in range(number_of_shots):
105 shot_speed = speed if shot_nb == 0 else speed + (speed2 - speed) * float(shot_nb) / float(number_of_shots)
106 bullet_angle = launch_angle
107 for bullet_nb in range(bullets_per_shot):
108 self.bullets.append(Bullet((self.x, self.y),
109 anim, sprite_idx_offset,
110 bullet_angle, shot_speed,
111 self.extended_bullet_attributes,
112 flags, player, self._game_state))
113 bullet_angle += angle
96 114
97 115
98 def select_player(self, players=None): 116 def select_player(self, players=None):
99 return (players or self._game_state.players)[0] #TODO 117 return (players or self._game_state.players)[0] #TODO
100 118
154 return False 172 return False
155 return True 173 return True
156 174
157 175
158 def get_objects_by_texture(self): 176 def get_objects_by_texture(self):
177 objects_by_texture = {}
178
179 for bullet in self.bullets:
180 objects_by_texture.update(bullet.get_objects_by_texture())
181
159 if not self._sprite: 182 if not self._sprite:
160 return {} 183 return objects_by_texture
161 184
162 objects_by_texture = {}
163 key = self._sprite.anm.first_name, self._sprite.anm.secondary_name 185 key = self._sprite.anm.first_name, self._sprite.anm.secondary_name
164 key = (key, self._sprite.blendfunc) 186 key = (key, self._sprite.blendfunc)
165 if not key in objects_by_texture: 187 if not key in objects_by_texture:
166 objects_by_texture[key] = (0, [], [], []) 188 objects_by_texture[key] = (0, [], [], [])
167 vertices = tuple((x + self.x, y + self.y, z) for x, y, z in self._sprite._vertices) 189 vertices = tuple((x + self.x, y + self.y, z) for x, y, z in self._sprite._vertices)
229 self._sprite.update() 251 self._sprite.update()
230 if self._sprite._changed or self.automatic_orientation: 252 if self._sprite._changed or self.automatic_orientation:
231 angle_base = self.angle if self.automatic_orientation else 0. 253 angle_base = self.angle if self.automatic_orientation else 0.
232 self._sprite.update_vertices_uvs_colors(angle_base=angle_base) 254 self._sprite.update_vertices_uvs_colors(angle_base=angle_base)
233 255
256
257 if self.bullet_launch_interval != 0:
258 self.bullet_launch_timer += 1
259 if self.bullet_launch_timer == self.bullet_launch_interval:
260 self.fire()
261
262
263 for bullet in self.bullets:
264 bullet.update()
265
266
234 self.frame += 1 267 self.frame += 1
235 268
236 269
237 270
238 class EnemyManager(object): 271 class EnemyManager(object):
243 self.main = [] 276 self.main = []
244 self.ecl = ecl 277 self.ecl = ecl
245 self.objects_by_texture = {} 278 self.objects_by_texture = {}
246 self.enemies = [] 279 self.enemies = []
247 self.processes = [] 280 self.processes = []
281 self.bullets = []
248 282
249 # Populate main 283 # Populate main
250 for frame, sub, instr_type, args in ecl.main: 284 for frame, sub, instr_type, args in ecl.main:
251 if not self.main or self.main[-1][0] < frame: 285 if not self.main or self.main[-1][0] < frame:
252 self.main.append((frame, [(sub, instr_type, args)])) 286 self.main.append((frame, [(sub, instr_type, args)]))
278 self.enemies[:] = (enemy for enemy in self.enemies if not enemy._removed) 312 self.enemies[:] = (enemy for enemy in self.enemies if not enemy._removed)
279 313
280 # Update enemies 314 # Update enemies
281 for enemy in self.enemies: 315 for enemy in self.enemies:
282 enemy.update() 316 enemy.update()
317 for bullet in enemy.bullets:
318 if bullet._launched:
319 enemy.bullets.remove(bullet)
320 self.bullets.append(bullet)
321
322 # Update bullets
323 for bullet in self.bullets:
324 bullet.update()
283 325
284 # Filter out non-visible enemies 326 # Filter out non-visible enemies
285 visible_enemies = [enemy for enemy in self.enemies if enemy.is_visible(384, 448)] #TODO 327 visible_enemies = [enemy for enemy in self.enemies if enemy.is_visible(384, 448)] #TODO
286 for enemy in visible_enemies: 328 for enemy in visible_enemies:
287 enemy._was_visible = True 329 enemy._was_visible = True
290 for enemy in tuple(self.enemies): 332 for enemy in tuple(self.enemies):
291 if enemy._was_visible and not enemy in visible_enemies: 333 if enemy._was_visible and not enemy in visible_enemies:
292 enemy._removed = True 334 enemy._removed = True
293 self.enemies.remove(enemy) 335 self.enemies.remove(enemy)
294 336
337 # Filter out-of-scren bullets
338 for bullet in self.bullets:
339 if not bullet.is_visible(384, 448):
340 self.bullets.remove(bullet)
341
342
295 #TODO: disable boss mode if it is dead/it has timeout 343 #TODO: disable boss mode if it is dead/it has timeout
296 if self._game_state.boss and self._game_state.boss._removed: 344 if self._game_state.boss and self._game_state.boss._removed:
297 self._game_state.boss = None 345 self._game_state.boss = None
298 346
299 # Add enemies to vertices/uvs 347 # Add enemies to vertices/uvs
300 self.objects_by_texture = {} 348 self.objects_by_texture = {}
301 for enemy in visible_enemies: 349 for enemy in visible_enemies:
302 if enemy.is_visible(384, 448): #TODO 350 for key, (count, vertices, uvs, colors) in enemy.get_objects_by_texture().items():
303 for key, (count, vertices, uvs, colors) in enemy.get_objects_by_texture().items(): 351 if not key in self.objects_by_texture:
304 if not key in self.objects_by_texture: 352 self.objects_by_texture[key] = (0, [], [], [])
305 self.objects_by_texture[key] = (0, [], [], []) 353 self.objects_by_texture[key][1].extend(vertices)
306 self.objects_by_texture[key][1].extend(vertices) 354 self.objects_by_texture[key][2].extend(uvs)
307 self.objects_by_texture[key][2].extend(uvs) 355 self.objects_by_texture[key][3].extend(colors)
308 self.objects_by_texture[key][3].extend(colors) 356
357 # Add bullets to vertices/uvs
358 for bullet in self.bullets:
359 for key, (count, vertices, uvs, colors) in bullet.get_objects_by_texture().items():
360 if not key in self.objects_by_texture:
361 self.objects_by_texture[key] = (0, [], [], [])
362 self.objects_by_texture[key][1].extend(vertices)
363 self.objects_by_texture[key][2].extend(uvs)
364 self.objects_by_texture[key][3].extend(colors)
365
309 for key, (nb_vertices, vertices, uvs, colors) in self.objects_by_texture.items(): 366 for key, (nb_vertices, vertices, uvs, colors) in self.objects_by_texture.items():
310 nb_vertices = len(vertices) 367 nb_vertices = len(vertices)
311 vertices = pack('f' * (3 * nb_vertices), *chain(*vertices)) 368 vertices = pack('f' * (3 * nb_vertices), *chain(*vertices))
312 uvs = pack('f' * (2 * nb_vertices), *chain(*uvs)) 369 uvs = pack('f' * (2 * nb_vertices), *chain(*uvs))
313 colors = pack('B' * (4 * nb_vertices), *chain(*colors)) 370 colors = pack('B' * (4 * nb_vertices), *chain(*colors))