Mercurial > touhou
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)) |