Mercurial > touhou
comparison pytouhou/game/bullet.pyx @ 442:6b4c3e250bd6
Type Bullet more, to improve performances.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Sat, 10 Aug 2013 15:21:39 +0200 |
parents | b9d2db93972f |
children | 78e1c3864e73 |
comparison
equal
deleted
inserted
replaced
441:e8dc95a2a287 | 442:6b4c3e250bd6 |
---|---|
10 ## but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 ## but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 ## GNU General Public License for more details. | 12 ## GNU General Public License for more details. |
13 ## | 13 ## |
14 | 14 |
15 from math import cos, sin, atan2, pi | 15 from libc.math cimport cos, sin, atan2, M_PI as pi |
16 | 16 |
17 from pytouhou.utils.interpolator import Interpolator | |
18 from pytouhou.vm.anmrunner import ANMRunner | 17 from pytouhou.vm.anmrunner import ANMRunner |
19 from pytouhou.game.sprite import Sprite | 18 from pytouhou.game.sprite cimport Sprite |
20 from pytouhou.game.element cimport Element | |
21 | 19 |
22 | 20 |
23 LAUNCHING, LAUNCHED, CANCELLED = range(3) | 21 LAUNCHING, LAUNCHED, CANCELLED = range(3) |
24 | 22 |
25 cdef class Bullet(Element): | 23 cdef class Bullet(Element): |
26 cdef public unsigned int state, flags, frame, sprite_idx_offset | 24 def __init__(self, pos, bullet_type, unsigned long sprite_idx_offset, |
27 cdef public double dx, dy, angle, speed #TODO | 25 double angle, double speed, attributes, unsigned long flags, target, game, |
28 cdef public object player_bullet, target | 26 bint player_bullet=False, unsigned long damage=0, hitbox=None): |
29 cdef public object _game, _bullet_type | 27 cdef double launch_mult |
30 cdef public object was_visible | 28 |
31 cdef public object attributes, damage, hitbox, speed_interpolator, grazed | |
32 | |
33 def __init__(self, pos, bullet_type, sprite_idx_offset, | |
34 angle, speed, attributes, flags, target, game, | |
35 player_bullet=False, damage=0, hitbox=None): | |
36 Element.__init__(self, pos) | 29 Element.__init__(self, pos) |
37 | 30 |
38 self._game = game | 31 self._game = game |
39 self._bullet_type = bullet_type | 32 self._bullet_type = bullet_type |
40 self.state = LAUNCHING | 33 self.state = LAUNCHING |
41 self.was_visible = True | 34 self.was_visible = True |
42 | 35 |
43 if hitbox: | 36 if hitbox is not None: |
44 self.hitbox = (hitbox[0], hitbox[1]) | 37 self.hitbox = hitbox |
45 else: | 38 else: |
46 self.hitbox = (bullet_type.hitbox_size, bullet_type.hitbox_size) | 39 self.hitbox = (bullet_type.hitbox_size, bullet_type.hitbox_size) |
47 | 40 |
48 self.speed_interpolator = None | 41 self.speed_interpolator = None |
49 self.frame = 0 | 42 self.frame = 0 |
86 self.sprite.angle = angle - pi | 79 self.sprite.angle = angle - pi |
87 else: | 80 else: |
88 self.sprite.angle = angle | 81 self.sprite.angle = angle |
89 | 82 |
90 | 83 |
91 cpdef is_visible(self, screen_width, screen_height): | 84 cdef bint is_visible(self, unsigned int screen_width, unsigned int screen_height): |
92 tx, ty, tw, th = self.sprite.texcoords | 85 cdef double tw, th |
86 | |
87 tw, th = self.sprite.texcoords[2:] | |
93 x, y = self.x, self.y | 88 x, y = self.x, self.y |
94 | 89 |
95 max_x = tw / 2. | 90 max_x = tw / 2 |
96 max_y = th / 2. | 91 max_y = th / 2 |
97 | 92 |
98 if (max_x < x - screen_width | 93 if (max_x < x - screen_width |
99 or max_x < -x | 94 or max_x < -x |
100 or max_y < y - screen_height | 95 or max_y < y - screen_height |
101 or max_y < -y): | 96 or max_y < -y): |
102 return False | 97 return False |
103 return True | 98 return True |
104 | 99 |
105 | 100 |
106 def set_anim(self, sprite_idx_offset=None): | 101 cpdef set_anim(self, sprite_idx_offset=None): |
107 if sprite_idx_offset is not None: | 102 if sprite_idx_offset is not None: |
108 self.sprite_idx_offset = sprite_idx_offset | 103 self.sprite_idx_offset = sprite_idx_offset |
109 | 104 |
110 bt = self._bullet_type | 105 bt = self._bullet_type |
111 self.sprite = Sprite() | 106 self.sprite = Sprite() |
115 self.sprite.angle = self.angle | 110 self.sprite.angle = self.angle |
116 self.anmrunner = ANMRunner(bt.anm, bt.anim_index, | 111 self.anmrunner = ANMRunner(bt.anm, bt.anim_index, |
117 self.sprite, self.sprite_idx_offset) | 112 self.sprite, self.sprite_idx_offset) |
118 | 113 |
119 | 114 |
120 def launch(self): | 115 cdef void launch(self): |
121 self.state = LAUNCHED | 116 self.state = LAUNCHED |
122 self.frame = 0 | 117 self.frame = 0 |
123 self.set_anim() | 118 self.set_anim() |
124 self.dx, self.dy = cos(self.angle) * self.speed, sin(self.angle) * self.speed | 119 self.dx, self.dy = cos(self.angle) * self.speed, sin(self.angle) * self.speed |
125 | 120 |
126 if self.flags & 1: | 121 if self.flags & 1: |
127 self.speed_interpolator = Interpolator((self.speed + 5.,), 0, | 122 self.speed_interpolator = Interpolator((self.speed + 5.,), 0, |
128 (self.speed,), 16) | 123 (self.speed,), 16) |
129 | 124 |
130 | 125 |
131 def collide(self): | 126 cpdef collide(self): |
132 self.cancel() | 127 self.cancel() |
133 self._game.new_particle((self.x, self.y), 10, 256) #TODO: find the real size. | 128 self._game.new_particle((self.x, self.y), 10, 256) #TODO: find the real size. |
134 | 129 |
135 | 130 |
136 def cancel(self): | 131 cpdef cancel(self): |
137 # Cancel animation | 132 # Cancel animation |
138 bt = self._bullet_type | 133 bt = self._bullet_type |
139 self.sprite = Sprite() | 134 self.sprite = Sprite() |
140 if self.player_bullet: | 135 if self.player_bullet: |
141 self.sprite.angle = self.angle - pi | 136 self.sprite.angle = self.angle - pi |
146 self.dx, self.dy = self.dx / 2., self.dy / 2. | 141 self.dx, self.dy = self.dx / 2., self.dy / 2. |
147 | 142 |
148 self.state = CANCELLED | 143 self.state = CANCELLED |
149 | 144 |
150 | 145 |
151 def update(self): | 146 cpdef update(self): |
147 cdef int frame, count, game_width, game_height | |
148 cdef double length, angle, speed, acceleration, angular_speed | |
149 | |
152 if self.anmrunner is not None and not self.anmrunner.run_frame(): | 150 if self.anmrunner is not None and not self.anmrunner.run_frame(): |
153 if self.state == LAUNCHING: | 151 if self.state == LAUNCHING: |
154 #TODO: check if it doesn't skip a frame | 152 #TODO: check if it doesn't skip a frame |
155 self.launch() | 153 self.launch() |
156 elif self.state == CANCELLED: | 154 elif self.state == CANCELLED: |
195 elif self.flags & 448: | 193 elif self.flags & 448: |
196 #TODO: check | 194 #TODO: check |
197 frame, count = self.attributes[0:2] | 195 frame, count = self.attributes[0:2] |
198 angle, speed = self.attributes[4:6] | 196 angle, speed = self.attributes[4:6] |
199 if self.frame % frame == 0: | 197 if self.frame % frame == 0: |
200 count = count - 1 | 198 count -= 1 |
201 | 199 |
202 if self.frame != 0: | 200 if self.frame != 0: |
203 self.speed = self.speed if speed < -900 else speed | 201 self.speed = self.speed if speed < -900 else speed |
204 | 202 |
205 if self.flags & 64: | 203 if self.flags & 64: |
235 self.x += self.dx | 233 self.x += self.dx |
236 self.y += self.dy | 234 self.y += self.dy |
237 | 235 |
238 self.frame += 1 | 236 self.frame += 1 |
239 | 237 |
238 game_width, game_height = self._game.width, self._game.height | |
239 | |
240 # Filter out-of-screen bullets and handle special flags | 240 # Filter out-of-screen bullets and handle special flags |
241 if self.flags & 448: | 241 if self.flags & 448: |
242 self.was_visible = False | 242 self.was_visible = False |
243 elif self.is_visible(self._game.width, self._game.height): | 243 elif self.is_visible(game_width, game_height): |
244 self.was_visible = True | 244 self.was_visible = True |
245 elif self.was_visible: | 245 elif self.was_visible: |
246 self.removed = True | 246 self.removed = True |
247 if self.flags & (1024 | 2048) and self.attributes[0] > 0: | 247 if self.flags & (1024 | 2048) and self.attributes[0] > 0: |
248 # Bounce! | 248 # Bounce! |
249 if self.x < 0 or self.x > self._game.width: | 249 if self.x < 0 or self.x > game_width: |
250 self.angle = pi - self.angle | 250 self.angle = pi - self.angle |
251 self.removed = False | 251 self.removed = False |
252 if self.y < 0 or ((self.flags & 1024) and self.y > self._game.height): | 252 if self.y < 0 or ((self.flags & 1024) and self.y > game_height): |
253 self.angle = -self.angle | 253 self.angle = -self.angle |
254 self.removed = False | 254 self.removed = False |
255 self.sprite.angle = self.angle | 255 self.sprite.angle = self.angle |
256 if self.sprite.automatic_orientation: | 256 if self.sprite.automatic_orientation: |
257 self.sprite.changed = True | 257 self.sprite.changed = True |
258 self.dx = cos(self.angle) * self.speed | 258 self.dx = cos(self.angle) * self.speed |
259 self.dy = sin(self.angle) * self.speed | 259 self.dy = sin(self.angle) * self.speed |
260 self.attributes[0] -= 1 | 260 self.attributes[0] -= 1 |
261 |