def tick(self): super(ChaseMixin, self).tick() if self.started: # Figure out how close we are to the player. player = get_engine().player distance_x = abs(player.rect.x - self.rect.x) distance_y = abs(player.rect.y - self.rect.y) if (self.following and (distance_x >= self.STOP_FOLLOWING_DISTANCE or distance_y >= self.STOP_FOLLOWING_DISTANCE)): self.stop_following() if (self.following or (distance_x <= self.APPROACH_DISTANCE and distance_y <= self.APPROACH_DISTANCE and not self.following and (not self.SHOW_EXCLAMATION or not self.exclamation))): if not self.following and not self.exclamation: if self.SHOW_EXCLAMATION: # They haven't noticed the player before, but they # do now! self.show_exclamation(on_done=self.start_following) return else: self.start_following() x_dir = None y_dir = None if player.rect.x > self.rect.x: x = 1 x_dir = Direction.EAST elif player.rect.x < self.rect.x: x = -1 x_dir = Direction.WEST else: x = 0 if player.rect.y > self.rect.y: y = 1 y_dir = Direction.SOUTH elif player.rect.y < self.rect.y: y = -1 y_dir = Direction.NORTH else: y = 0 self.velocity = (x * self.CHASE_SPEED, y * self.CHASE_SPEED) if distance_x > distance_y: self.direction = x_dir elif distance_y > distance_x: self.direction = y_dir self.update_image() super(ChaseMixin, self).tick()
def tick(self): if self.started: engine = get_engine() player = engine.player if (not self.attacking and self.can_attack and self._can_see_player()): self.stop_wandering() self.attacking = True self.autoset_velocity = False self.attack_start_pos = self.rect.topleft self.attack_dest_pos = player.rect.center self.velocity, self.max_attack_ticks = self._get_attack_data() # Let it go a bit longer than that self.max_attack_ticks += self.ATTACK_TICKS_PAD self.attack_ticks = 1 self._update_attack_pos() elif self.attacking: self.attack_ticks += 1 self._update_attack_pos() if self.attack_ticks >= self.max_attack_ticks: self.stop_attacking() else: # Allow normal moving logic to happen. super(AttackLineMixin, self).tick()
def on_dead(self): self.lives -= 1 self.lives_changed.emit() self.stop_moving() engine = get_engine() if self.lives == 0: self.die(engine.game_over) else: self.health = self.MAX_HEALTH self.health_changed.emit() engine.dead()
def __init__(self, ms, cb, one_shot=False, start_automatically=True): self.engine = get_engine() assert self.engine self.ms = ms self.cb = cb self.tick_count_count = 0 self.started = False self.one_shot = one_shot self.tick_cnx = None self.start_automatically = True if ms > 0 and start_automatically: self.start()
def _get_attack_data(self): player = get_engine().player delta_x = player.rect.center[0] - self.rect.topleft[0] delta_y = player.rect.center[1] - self.rect.topleft[1] dist = math.sqrt(delta_x * delta_x + delta_y * delta_y) if dist == 0: return (0, 0), 0 velocity = ((delta_x * (1.0 / dist) * self.ATTACK_SPEED), (delta_y * (1.0 / dist) * self.ATTACK_SPEED)) if velocity[0] == 0: max_attack_ticks = int(delta_y / velocity[1]) else: max_attack_ticks = int(delta_x / velocity[0]) return velocity, max_attack_ticks
def move_by(self, *args, **kwargs): super(Bullet, self).move_by(*args, **kwargs) camera_rect = get_engine().camera.rect if not self.layer: return screen_size = self.layer.parent.size if (self.started and (self.rect.x <= max(camera_rect.x - self.OFFSCREEN_DIST, 0) or self.rect.y <= max(camera_rect.y - self.OFFSCREEN_DIST, 0) or self.rect.right > min(camera_rect.right + self.OFFSCREEN_DIST, screen_size[0]) or self.rect.bottom > min(camera_rect.bottom + self.OFFSCREEN_DIST, screen_size[1]))): # We've hit the edge of the world, or far enough away from the # camera, so disappear. self.remove()
def _can_see_player(self): player = get_engine().player distance_x = abs(player.rect.x - self.rect.x) distance_y = abs(player.rect.y - self.rect.y) if (distance_x <= self.ATTACK_DISTANCE and distance_y <= self.ATTACK_DISTANCE): # See if there's anything in the way. We'll simulate an attack. start_pos = self.rect.topleft velocity, max_attack_ticks = self._get_attack_data() for i in xrange(1, max_attack_ticks - 1): pos = self._get_attack_position(start_pos, velocity, i) rect = pygame.Rect(pos, self.rect.size) for sprite in self.layer.iterate_in_rect(rect): if sprite != self and sprite != player: return False return True return False
def on_collision(self, dx, dy, obj, self_rect, obj_rect): if obj == get_engine().player and not self.showed_exclamation: get_engine().ui.close_monologues() self.show_exclamation('heart_exclamation', self._transition_clean) self.showed_exclamation = True