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