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