Mercurial > touhou
diff pytouhou/game/laser.py @ 274:f037bca24f2d
Partially implement lasers.
“Launch animations”/“energy circles” are missing, aswell as collision and grazing.
author | Thibaut Girka <thib@sitedethib.com> |
---|---|
date | Sun, 05 Feb 2012 23:41:55 +0100 |
parents | |
children | 615c0bb6064b |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/pytouhou/game/laser.py @@ -0,0 +1,121 @@ +# -*- encoding: utf-8 -*- +## +## Copyright (C) 2012 Thibaut Girka <thib@sitedethib.com> +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published +## by the Free Software Foundation; version 3 only. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## + +from math import cos, sin, pi + +from pytouhou.vm.anmrunner import ANMRunner +from pytouhou.game.sprite import Sprite + + +STARTING, STARTED, STOPPING = range(3) + + +class Laser(object): + def __init__(self, pos, laser_type, sprite_idx_offset, + angle, speed, start_offset, end_offset, max_length, width, + start_duration, duration, stop_duration, + grazing_delay, grazing_extra_duration, + game): + self._game = game + #TODO: aux sprite + self._sprite = None + self._anmrunner = None + self._removed = False + self._laser_type = laser_type + self.state = STARTING + + #TODO: hitbox + + self.frame = 0 + self.start_duration = start_duration + self.duration = duration + self.stop_duration = stop_duration + self.grazing_delay = grazing_delay + self.grazing_extra_duration = grazing_extra_duration + + self.sprite_idx_offset = sprite_idx_offset + self.x, self.y = pos + self.angle = angle + self.speed = speed + self.start_offset = start_offset + self.end_offset = end_offset + self.max_length = max_length + self.width = width + + self.set_anim() + + + 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._sprite.angle = self.angle + self._anmrunner = ANMRunner(lt.anm_wrapper, lt.anim_index, + self._sprite, self.sprite_idx_offset) + self._anmrunner.run_frame() + + + def get_bullets_pos(self): + #TODO: check + offset = self.start_offset + length = min(self.end_offset - self.start_offset, self.max_length) + dx, dy = cos(self.angle), sin(self.angle) + while 0 <= offset - self.start_offset <= length: + yield (self.x + offset * dx, self.y + offset * dy) + offset += 48. + + + def cancel(self): + if self.state != STOPPING: + self.frame = 0 + self.state = STOPPING + + + def update(self): + if self._anmrunner is not None and not self._anmrunner.run_frame(): + self._anmrunner = None + + self.end_offset += self.speed + + length = min(self.end_offset - self.start_offset, self.max_length) # TODO + if self.state == STARTING: + if self.frame == self.start_duration: + self.frame = 0 + self.state = STARTED + else: + width = self.width * float(self.frame) / self.start_duration #TODO + if self.state == STARTED: + width = self.width #TODO + if self.frame == self.duration: + self.frame = 0 + self.state = STOPPING + if self.state == STOPPING: + if self.frame == self.stop_duration: + width = 0. + self._removed = True + else: + width = self.width * (1. - float(self.frame) / self.stop_duration) #TODO + + self._sprite.allow_dest_offset = True + self._sprite.dest_offset = (0., self.end_offset - length / 2., 0.) + self._sprite.width_override = width or 0.01 #TODO + self._sprite.height_override = length or 0.01 #TODO + + self._sprite.update_orientation(pi/2. - self.angle, True) + self._sprite._changed = True #TODO + + self.frame += 1 +