changeset 294:94c636f8f863

Add player lasers for MarisaB.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Tue, 21 Feb 2012 14:28:38 +0100
parents ab618c2bbce8
children 2a60642e8892
files pytouhou/game/enemy.py pytouhou/game/game.py pytouhou/game/laser.py pytouhou/game/player.py pytouhou/ui/gamerenderer.pyx pytouhou/vm/anmrunner.py
diffstat 6 files changed, 109 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/pytouhou/game/enemy.py
+++ b/pytouhou/game/enemy.py
@@ -286,6 +286,21 @@ class Enemy(object):
                     damages += bullet.damage
                 self.drop_particles(1, 1)
 
+        # Check for enemy-laser collisions
+        for laser in self._game.players_lasers:
+            if not laser:
+                continue
+
+            half_size = laser.hitbox_half_size
+            lx, ly = laser.x, laser.y * 2.
+            lx1, lx2 = lx - half_size[0], lx + half_size[0]
+
+            if not (lx2 < ex1 or lx1 > ex2
+                    or ly < ey1):
+                if self.damageable:
+                    damages += laser.damage
+                self.drop_particles(1, 1)
+
         # Check for enemy-player collisions
         ex1, ex2 = ex - ehalf_size_x * 2. / 3., ex + ehalf_size_x * 2. / 3.
         ey1, ey2 = ey - ehalf_size_y * 2. / 3., ey + ehalf_size_y * 2. / 3.
--- a/pytouhou/game/game.py
+++ b/pytouhou/game/game.py
@@ -46,6 +46,7 @@ class Game(object):
         self.lasers = []
         self.cancelled_bullets = []
         self.players_bullets = []
+        self.players_lasers = [None, None]
         self.items = []
 
         self.stage = stage
@@ -83,6 +84,10 @@ class Game(object):
         return []
 
 
+    def lasers_sprites(self):
+        return [laser for laser in self.players_lasers if laser]
+
+
     def modify_difficulty(self, diff):
         self.difficulty_counter += diff
         while self.difficulty_counter < 0:
@@ -236,6 +241,10 @@ class Game(object):
         for bullet in self.bullets:
             bullet.update()
 
+        for laser in self.players_lasers:
+            if laser:
+                laser.update()
+
         for item in self.items:
             item.update()
 
@@ -315,6 +324,9 @@ class Game(object):
                             if not bullet._removed]
         self.players_bullets = [bullet for bullet in self.players_bullets
                             if not bullet._removed]
+        for i, laser in enumerate(self.players_lasers):
+            if laser and laser._removed:
+                self.players_lasers[i] = None
         self.cancelled_bullets = [bullet for bullet in self.cancelled_bullets
                             if not bullet._removed]
         self.effects = [effect for effect in self.effects if not effect._removed]
--- a/pytouhou/game/laser.py
+++ b/pytouhou/game/laser.py
@@ -192,3 +192,66 @@ class Laser(object):
 
         self.frame += 1
 
+
+class PlayerLaser(object):
+    def __init__(self, laser_type, sprite_idx_offset, hitbox, damage,
+                 angle, offset, duration, origin):
+        self._sprite = None
+        self._anmrunner = None
+        self._removed = False
+        self._laser_type = laser_type
+        self.origin = origin
+
+        self.hitbox_half_size = hitbox[0] / 2., hitbox[1] / 2.
+
+        self.frame = 0
+        self.duration = duration
+
+        self.sprite_idx_offset = sprite_idx_offset
+        self.angle = angle
+        self.offset = offset
+        self.damage = damage
+
+        self.set_anim()
+
+
+    @property
+    def x(self):
+        return self.origin.x + self.offset * cos(self.angle)
+
+
+    @property
+    def y(self):
+        return self.origin.y / 2. + self.offset * sin(self.angle)
+
+
+    def set_anim(self, sprite_idx_offset=None):
+        if sprite_idx_offset is not None:
+            self.sprite_idx_offset = sprite_idx_offset
+
+        lt = self._laser_type
+        self._sprite = Sprite()
+        self._anmrunner = ANMRunner(lt.anm_wrapper, lt.anim_index,
+                                    self._sprite, self.sprite_idx_offset)
+        #self._sprite.blendfunc = 1 #XXX
+        self._anmrunner.run_frame()
+
+
+    def cancel(self):
+        self._anmrunner.interrupt(1)
+
+
+    def update(self):
+        if self._anmrunner is not None and not self._anmrunner.run_frame():
+            self._anmrunner = None
+            self._removed = True
+
+        length = self.origin.y
+        if self.frame == self.duration:
+            self.cancel()
+
+        self._sprite.height_override = length or 0.01 #TODO
+        self._sprite._changed = True #TODO
+
+        self.frame += 1
+
--- a/pytouhou/game/player.py
+++ b/pytouhou/game/player.py
@@ -17,6 +17,8 @@ from pytouhou.game.sprite import Sprite
 from pytouhou.vm.anmrunner import ANMRunner
 from pytouhou.game.bullettype import BulletType
 from pytouhou.game.bullet import Bullet
+from pytouhou.game.lasertype import LaserType
+from pytouhou.game.laser import PlayerLaser
 
 from math import pi
 
@@ -110,10 +112,22 @@ class Player(object):
         power = min(power for power in sht.shots if self.state.power < power)
 
         bullets = self._game.players_bullets
+        lasers = self._game.players_lasers
         nb_bullets_max = self._game.nb_bullets_max
 
         for shot in sht.shots[power]:
-            if shot.type == 3: # TODO: Lasers aren't implemented yet
+            origin = self.orbs[shot.orb - 1] if shot.orb else self.state
+
+            if shot.type == 3:
+                if self.fire_time != 30:
+                    continue
+
+                number = shot.delay #TODO: number can do very surprising things, like removing any bullet creation from enemies with 3. For now, crash when not 0 or 1.
+                if lasers[number]:
+                    continue
+
+                laser_type = LaserType(self.anm_wrapper, shot.sprite % 256, 68)
+                lasers[number] = PlayerLaser(laser_type, 0, shot.hitbox, shot.damage, shot.angle, shot.speed, shot.interval, origin)
                 continue
 
             if (self.fire_time + shot.delay) % shot.interval != 0:
@@ -122,7 +136,6 @@ class Player(object):
             if nb_bullets_max is not None and len(bullets) == nb_bullets_max:
                 break
 
-            origin = self.orbs[shot.orb - 1] if shot.orb else self
             x = origin.x + shot.pos[0]
             y = origin.y + shot.pos[1]
 
@@ -130,7 +143,7 @@ class Player(object):
             bullet_type = BulletType(self.anm_wrapper, shot.sprite % 256,
                                      shot.sprite % 256 + 32, #TODO: find the real cancel anim
                                      0, 0, 0, 0.)
-            #TODO: Type 1 (homing bullets) and type 3 (laser)
+            #TODO: Type 1 (homing bullets)
             if shot.type == 2:
                 #TODO: triple-check acceleration!
                 bullets.append(Bullet((x, y), bullet_type, 0,
--- a/pytouhou/ui/gamerenderer.pyx
+++ b/pytouhou/ui/gamerenderer.pyx
@@ -84,6 +84,7 @@ cdef class GameRenderer(Renderer):
             self.render_elements(enemy for enemy in game.enemies if enemy._visible)
             self.render_elements(game.effects)
             self.render_elements(chain(game.players_bullets,
+                                       game.lasers_sprites(),
                                        game.players,
                                        game.msg_sprites(),
                                        *(player.objects() for player in game.players)))
--- a/pytouhou/vm/anmrunner.py
+++ b/pytouhou/vm/anmrunner.py
@@ -137,7 +137,8 @@ class ANMRunner(object):
 
     @instruction(4)
     def set_color(self, b, g, r):
-        self._sprite.color = (r, g, b)
+        if not self._sprite.fade_interpolator:
+            self._sprite.color = (r, g, b)
 
 
     @instruction(5)