class PointMass: def __init__(self, x, y, inverse_mass): self.inverse_mass = inverse_mass self.position = Point(x, y) self.velocity = Point(0, 0) self.acceleration = Point(0, 0) self.damping = MASS_DAMPING def apply(self, force): self.acceleration += force * self.inverse_mass def update(self): if (self.acceleration.length_sqr() == 0 and self.velocity.length_sqr() == 0): return self.velocity += self.acceleration self.position += self.velocity self.acceleration.coords = (0, 0) if (self.velocity.length_sqr() < sys.float_info.epsilon): self.velocity.coords = (0, 0) self.velocity *= self.damping self.damping = self.damping
class Avoider(Enemy): def __init__(self, scene, x, y): super().__init__(scene, x, y) self._velocity = Point(0, 0) self.set_shape(sh.STAR_SHAPE, Colors.avoid, True, 5) def update(self): player = self._scene.player vec_to_player = player.position - self.position dir_to_player = math.atan2(vec_to_player.y, vec_to_player.x) angle = self._angle_distance(player.direction, dir_to_player) if angle < math.pi/2: dirvec = vec_to_player speed = ACCELERATION else: avoid_point = Point(1, 1) avoid_count = 0 for obj in self.scene.objects: if isinstance(obj, pl.Bullet): distance = (obj.position - self.position).length_sqr() if distance <= DISTANCE_SQR: avoid_point += obj.position avoid_count += 1 if avoid_count > 0: avoid_point /= avoid_count dirvec = self.position - avoid_point speed = DODGE else: dirvec = vec_to_player speed = ACCELERATION self._velocity += dirvec * speed / dirvec.length() if self._velocity.length_sqr() > SPEED_SQR: self._velocity.normalize() self._velocity *= SPEED self.position += self._velocity self.direction += ANGULAR_SPEED super().update() def _angle_distance(self, alpha, beta): phi = abs(beta - alpha) % 360 distance = 360 - phi if phi > 180 else phi return distance
class Brick(Enemy): def __init__(self, scene, x, y, n=2): super().__init__(scene, x, y) self._velocity = Point(0, 0) self._size = n myscale = SCALE - n*2 self.set_shape(sh.BRICK_SHAPE[n], Colors.split, True, myscale) self._sleep = SLEEP_TIME if n < 2 else 0 def destroy(self): if self._size > 0: s = SCALE off = self._size*s n = self._size - 1 for x in range(0, 2): for y in range(0, 2): celloffset = Point(off + x*s, off + y*s) cellpos = self.position + celloffset child = Brick(self._scene, cellpos.x, cellpos.y, n) child._velocity = (cellpos - self.position)*2 self._scene.add_object(child) super().destroy() def update(self): if self._sleep <= 0: player = self._scene.player dirvec = player.position - self.position self._velocity += dirvec * ACCELERATION / dirvec.length() else: self._sleep -= 1 if self._velocity.length_sqr() > SPEED: self._velocity.normalize() self._velocity *= SPEED self.position += self._velocity self.direction += self._velocity.length()*ANGULAR_SPEED super().update()