Mercurial > touhou
comparison pytouhou/game/bullet.py @ 256:507dfd6efe0c
Refactor pytouhou.game.bullet.
author | Thibaut Girka <thib@sitedethib.com> |
---|---|
date | Sun, 22 Jan 2012 21:41:18 +0100 |
parents | a0d6b1915591 |
children |
comparison
equal
deleted
inserted
replaced
255:a0d6b1915591 | 256:507dfd6efe0c |
---|---|
17 from pytouhou.utils.interpolator import Interpolator | 17 from pytouhou.utils.interpolator import Interpolator |
18 from pytouhou.vm.anmrunner import ANMRunner | 18 from pytouhou.vm.anmrunner import ANMRunner |
19 from pytouhou.game.sprite import Sprite | 19 from pytouhou.game.sprite import Sprite |
20 | 20 |
21 | 21 |
22 LAUNCHING, LAUNCHED, CANCELLED = range(3) | |
22 | 23 |
23 class Bullet(object): | 24 class Bullet(object): |
24 def __init__(self, pos, bullet_type, sprite_idx_offset, | 25 def __init__(self, pos, bullet_type, sprite_idx_offset, |
25 angle, speed, attributes, flags, target, game, | 26 angle, speed, attributes, flags, target, game, |
26 player_bullet=False, damage=0, hitbox=None): | 27 player_bullet=False, damage=0, hitbox=None): |
27 self._game = game | 28 self._game = game |
28 self._sprite = None | 29 self._sprite = None |
29 self._anmrunner = None | 30 self._anmrunner = None |
30 self._removed = False | 31 self._removed = False |
31 self._launched = False | |
32 self._bullet_type = bullet_type | 32 self._bullet_type = bullet_type |
33 self._was_visible = True | 33 self._was_visible = True |
34 self._state = LAUNCHING | |
34 | 35 |
35 if hitbox: | 36 if hitbox: |
36 self.hitbox_half_size = (hitbox[0] / 2., hitbox[1] / 2.) | 37 self.hitbox_half_size = (hitbox[0] / 2., hitbox[1] / 2.) |
37 else: | 38 else: |
38 self.hitbox_half_size = (bullet_type.hitbox_size / 2., bullet_type.hitbox_size / 2.) | 39 self.hitbox_half_size = (bullet_type.hitbox_size / 2., bullet_type.hitbox_size / 2.) |
49 self.attributes = list(attributes) | 50 self.attributes = list(attributes) |
50 | 51 |
51 self.x, self.y = pos | 52 self.x, self.y = pos |
52 self.angle = angle | 53 self.angle = angle |
53 self.speed = speed | 54 self.speed = speed |
54 dx, dy = cos(angle) * speed, sin(angle) * speed | 55 self.dx, self.dy = cos(angle) * speed, sin(angle) * speed |
55 self.delta = dx, dy | |
56 | 56 |
57 self.player_bullet = player_bullet | 57 self.player_bullet = player_bullet |
58 self.damage = damage | 58 self.damage = damage |
59 | 59 |
60 #TODO | 60 #TODO |
66 index = bullet_type.launch_anim4_index | 66 index = bullet_type.launch_anim4_index |
67 launch_mult = bullet_type.launch_anim_penalties[1] | 67 launch_mult = bullet_type.launch_anim_penalties[1] |
68 else: | 68 else: |
69 index = bullet_type.launch_anim8_index | 69 index = bullet_type.launch_anim8_index |
70 launch_mult = bullet_type.launch_anim_penalties[2] | 70 launch_mult = bullet_type.launch_anim_penalties[2] |
71 self.launch_delta = dx * launch_mult, dy * launch_mult | 71 self.dx, self.dy = self.dx * launch_mult, self.dy * launch_mult |
72 self._sprite = Sprite() | 72 self._sprite = Sprite() |
73 self._anmrunner = ANMRunner(bullet_type.anm_wrapper, | 73 self._anmrunner = ANMRunner(bullet_type.anm_wrapper, |
74 index, self._sprite, | 74 index, self._sprite, |
75 bullet_type.launch_anim_offsets[sprite_idx_offset]) | 75 bullet_type.launch_anim_offsets[sprite_idx_offset]) |
76 self._anmrunner.run_frame() | 76 self._anmrunner.run_frame() |
112 self._sprite, self.sprite_idx_offset) | 112 self._sprite, self.sprite_idx_offset) |
113 self._anmrunner.run_frame() | 113 self._anmrunner.run_frame() |
114 | 114 |
115 | 115 |
116 def launch(self): | 116 def launch(self): |
117 self._launched = True | 117 self._state = LAUNCHED |
118 self.frame = 0 | |
118 self.set_anim() | 119 self.set_anim() |
120 self.dx, self.dy = cos(self.angle) * self.speed, sin(self.angle) * self.speed | |
119 if self.flags & 1: | 121 if self.flags & 1: |
120 self.speed_interpolator = Interpolator((self.speed + 5.,), 0, | 122 self.speed_interpolator = Interpolator((self.speed + 5.,), 0, |
121 (self.speed,), 16) | 123 (self.speed,), 16) |
122 self.update = self.update_speed | |
123 else: | |
124 self.update = self.update_full | |
125 | 124 |
126 | 125 |
127 def collide(self): | 126 def collide(self): |
128 self.cancel() | 127 self.cancel() |
129 | 128 |
137 else: | 136 else: |
138 self._sprite.angle = self.angle | 137 self._sprite.angle = self.angle |
139 self._anmrunner = ANMRunner(bt.anm_wrapper, bt.cancel_anim_index, | 138 self._anmrunner = ANMRunner(bt.anm_wrapper, bt.cancel_anim_index, |
140 self._sprite, bt.launch_anim_offsets[self.sprite_idx_offset]) | 139 self._sprite, bt.launch_anim_offsets[self.sprite_idx_offset]) |
141 self._anmrunner.run_frame() | 140 self._anmrunner.run_frame() |
142 self.delta = self.delta[0] / 2., self.delta[1] / 2. | 141 self.dx, self.dy = self.dx / 2., self.dy / 2. |
143 | 142 |
144 # Change update method | 143 # Change update method |
145 self.update = self.update_cancel | 144 self._state = CANCELLED |
146 | 145 |
147 # Do not use this one for collisions anymore | 146 # Do not use this one for collisions anymore |
148 if self.player_bullet: | 147 if self.player_bullet: |
149 self._game.players_bullets.remove(self) | 148 self._game.players_bullets.remove(self) |
150 else: | 149 else: |
151 self._game.bullets.remove(self) | 150 self._game.bullets.remove(self) |
152 self._game.cancelled_bullets.append(self) | 151 self._game.cancelled_bullets.append(self) |
153 | 152 |
154 | 153 |
155 def update(self): | 154 def update(self): |
156 dx, dy = self.launch_delta | |
157 self.x += dx | |
158 self.y += dy | |
159 | |
160 if not self._anmrunner.run_frame(): | |
161 self.launch() | |
162 | |
163 | |
164 def update_cancel(self): | |
165 dx, dy = self.delta | |
166 self.x += dx | |
167 self.y += dy | |
168 | |
169 if not self._anmrunner.run_frame(): | |
170 self._removed = True | |
171 | |
172 | |
173 def update_simple(self): | |
174 dx, dy = self.delta | |
175 self.x += dx | |
176 self.y += dy | |
177 | |
178 | |
179 def update_speed(self): | |
180 if self.speed_interpolator: | |
181 self.speed_interpolator.update(self.frame) | |
182 self.speed, = self.speed_interpolator.values | |
183 dx, dy = cos(self.angle) * self.speed, sin(self.angle) * self.speed | |
184 self.x, self.y = self.x + dx, self.y + dy | |
185 self.frame += 1 | |
186 else: | |
187 self.update = self.update_full | |
188 self.update() | |
189 | |
190 | |
191 def update_full(self): | |
192 sprite = self._sprite | |
193 | |
194 if self._anmrunner is not None and not self._anmrunner.run_frame(): | 155 if self._anmrunner is not None and not self._anmrunner.run_frame(): |
195 self._anmrunner = None | 156 if self._state == LAUNCHING: |
196 | 157 #TODO: check if it doesn't skip a frame |
197 #TODO: flags | 158 self.launch() |
198 x, y = self.x, self.y | 159 elif self._state == CANCELLED: |
199 dx, dy = self.delta | 160 self._removed = True |
200 | 161 else: |
201 if self.flags & 16: | 162 self._anmrunner = None |
163 | |
164 if self._state == LAUNCHING: | |
165 pass | |
166 elif self._state == CANCELLED: | |
167 pass | |
168 elif self.flags & 1: | |
169 # Initial speed burst | |
170 #TODO: use frame instead of interpolator? | |
171 if not self.speed_interpolator: | |
172 self.flags &= ~1 | |
173 elif self.flags & 16: | |
174 # Each frame, add a vector to the speed vector | |
202 length, angle = self.attributes[4:6] | 175 length, angle = self.attributes[4:6] |
203 angle = self.angle if angle < -900.0 else angle #TODO: is that right? | 176 angle = self.angle if angle < -900.0 else angle #TODO: is that right? |
204 dx, dy = dx + cos(angle) * length, dy + sin(angle) * length | 177 self.dx += cos(angle) * length |
205 self.speed = (dx ** 2 + dy ** 2) ** 0.5 | 178 self.dy += sin(angle) * length |
206 self.angle = sprite.angle = atan2(dy, dx) | 179 self.speed = (self.dx ** 2 + self.dy ** 2) ** 0.5 |
207 if sprite.automatic_orientation: | 180 self.angle = self._sprite.angle = atan2(self.dy, self.dx) |
208 sprite._changed = True | 181 if self._sprite.automatic_orientation: |
209 self.delta = dx, dy | 182 self._sprite._changed = True |
210 if self.frame == self.attributes[0]: #TODO: include last frame, or not? | 183 if self.frame == self.attributes[0]: #TODO: include last frame, or not? |
211 self.flags ^= 16 | 184 self.flags &= ~16 |
212 elif self.flags & 32: | 185 elif self.flags & 32: |
186 # Each frame, accelerate and rotate | |
213 #TODO: check | 187 #TODO: check |
214 acceleration, angular_speed = self.attributes[4:6] | 188 acceleration, angular_speed = self.attributes[4:6] |
215 self.speed += acceleration | 189 self.speed += acceleration |
216 self.angle += angular_speed | 190 self.angle += angular_speed |
217 dx, dy = cos(self.angle) * self.speed, sin(self.angle) * self.speed | 191 self.dx = cos(self.angle) * self.speed |
218 self.delta = dx, dy | 192 self.dy = sin(self.angle) * self.speed |
219 sprite.angle = self.angle | 193 self._sprite.angle = self.angle |
220 if sprite.automatic_orientation: | 194 if self._sprite.automatic_orientation: |
221 sprite._changed = True | 195 self._sprite._changed = True |
222 if self.frame == self.attributes[0]: | 196 if self.frame == self.attributes[0]: |
223 self.flags ^= 32 | 197 self.flags &= ~32 |
224 elif self.flags & 448: | 198 elif self.flags & 448: |
225 #TODO: check | 199 #TODO: check |
226 frame, count = self.attributes[0:2] | 200 frame, count = self.attributes[0:2] |
227 angle, speed = self.attributes[4:6] | 201 angle, speed = self.attributes[4:6] |
228 if self.frame % frame == 0: | 202 if self.frame % frame == 0: |
232 self.speed = speed | 206 self.speed = speed |
233 | 207 |
234 if self.flags & 64: | 208 if self.flags & 64: |
235 self.angle += angle | 209 self.angle += angle |
236 elif self.flags & 128: | 210 elif self.flags & 128: |
237 self.angle = atan2(self.target.y - y, self.target.x - x) + angle | 211 self.angle = atan2(self.target.y - self.y, |
212 self.target.x - self.x) + angle | |
238 elif self.flags & 256: | 213 elif self.flags & 256: |
239 self.angle = angle | 214 self.angle = angle |
240 | 215 |
241 dx, dy = cos(self.angle) * speed, sin(self.angle) * speed | 216 self.dx = cos(self.angle) * self.speed |
242 self.delta = dx, dy | 217 self.dy = sin(self.angle) * self.speed |
243 sprite.angle = self.angle | 218 self._sprite.angle = self.angle |
244 if sprite.automatic_orientation: | 219 if self._sprite.automatic_orientation: |
245 sprite._changed = True | 220 self._sprite._changed = True |
246 | 221 |
247 if count >= 0: | 222 if count >= 0: |
248 self.speed_interpolator = Interpolator((self.speed,), self.frame, | 223 self.speed_interpolator = Interpolator((self.speed,), self.frame, |
249 (0.,), self.frame + frame - 1) | 224 (0.,), self.frame + frame - 1) |
250 else: | 225 else: |
251 self.flags &= ~448 | 226 self.flags &= ~448 |
252 | 227 |
253 self.attributes[1] = count | 228 self.attributes[1] = count |
254 #TODO: other flags | 229 #TODO: other flags |
255 elif not self.speed_interpolator and self._anmrunner is None: | 230 |
256 self.update = self.update_simple | 231 # Common updates |
257 | 232 |
258 if self.speed_interpolator: | 233 if self.speed_interpolator: |
259 self.speed_interpolator.update(self.frame) | 234 self.speed_interpolator.update(self.frame) |
260 self.speed, = self.speed_interpolator.values | 235 self.speed, = self.speed_interpolator.values |
261 dx, dy = cos(self.angle) * self.speed, sin(self.angle) * self.speed | 236 self.dx = cos(self.angle) * self.speed |
262 self.delta = dx, dy | 237 self.dy = sin(self.angle) * self.speed |
263 | 238 |
264 self.x, self.y = x + dx, y + dy | 239 self.x += self.dx |
240 self.y += self.dy | |
265 | 241 |
266 self.frame += 1 | 242 self.frame += 1 |
267 | 243 |