def maneuver(self, update, signal): if self.health > values.enemy_ace_health / 2: target_vector = Vector(0, 0) # Slow and aim to be the target distance. for player in update.scene.get(kind=Player): # Making moves # TODO: Add some variance to this to keep Aces from locking in position. from_player = self.position - player.position target_vector += from_player.scale(self.max_thrust) towards_player = player.position - self.position strength_of_towards = ( towards_player.length / self.target_attack_range) * self.max_thrust target_vector += (player.position - self.position).scale(strength_of_towards) avoid_left = max(2 - self.position.x, 0) target_vector += Vector(avoid_left, 0).scale(avoid_left**2) avoid_right = max(self.position.x - 8, 0) target_vector += Vector(avoid_right, 0).scale(avoid_right**2) self.heading = target_vector.normalize() self.speed = target_vector.length # Attack time spawn_position = self.position + towards_player.truncate(0.5) if self.bullet_cool_down <= 0: update.scene.add( Bullet(position=spawn_position, heading=towards_player.normalize(), target="player")) self.bullet_cool_down = values.enemy_ace_bullet_cool_down else: self.bullet_cool_down -= update.time_delta if self.tri_missle_cool_down <= 0: if self.tri_missle_count: update.scene.add( Zero(position=spawn_position, heading=towards_player.normalize(), size=.5)) self.tri_missle_count -= 1 self.tri_missle_cool_down = 0.2 else: update.scene.add( Zero(position=spawn_position, heading=towards_player.normalize(), size=.5)) self.tri_missle_count = 2 self.tri_missle_cool_down = values.enemy_ace_tri_missle_cool_down else: self.tri_missle_cool_down -= update.time_delta else: self.heading = Vector(0, -1) self.speed = self.max_thrust
def on_update(self, event, signal): player = event.scene.player if (player.position - self.position).length < .6: push_vector = Vector(0, 0) if self.point_is_in(player.bottom.left): push_vector += UP_RIGHT if self.point_is_in(player.bottom.right): push_vector += UP_LEFT if self.point_is_in(player.top.right): push_vector += DOWN_LEFT if self.point_is_in(player.top.left): push_vector += DOWN_RIGHT player.position += push_vector.normalize() * .3
def on_update(self, event, signal): player = event.scene.player if (player.position - self.position).length < .6: push_vector = Vector(0, 0) if self.point_is_in(player.bottom.left): push_vector += UP_RIGHT if self.point_is_in(player.bottom.right): push_vector += UP_LEFT if self.point_is_in(player.top.right): push_vector += DOWN_LEFT if self.point_is_in(player.top.left): push_vector += DOWN_RIGHT player.position += push_vector.normalize() * .3
def on_update(self, update: ppb_events.Update, signal): if self.escorting is not None or self.escorting not in update.scene: cargo_ships = list(update.scene.get(kind=CargoShip)) if cargo_ships: self.escorting = cargo_ships[ 0] # We can modify this later. Might be better handled by a subsystem. else: self.escorting = None if self.escorting is not None: target = (self.position - self.escorting.position).scale(3) heading = Vector(0, -1) + (target - self.position) self.heading = heading.normalize() else: self.heading = Vector(0, -1) super().on_update(update, signal) self.cooldown_counter += update.time_delta if self.cooldown_counter >= self.next_shot: if not self.shots: players = list(update.scene.get(kind=Player)) if not players: return player = players.pop() self.shots = [ player.position + Vector(0, 2), player.position, player.position + Vector(0, -2) ] shot_target = self.shots.pop() shot_vector = shot_target - self.position bullet = Bullet(position=self.position, heading=shot_vector.normalize(), target="player") bullet.facing = -shot_vector update.scene.add(bullet) self.cooldown_counter = 0 if self.shots: self.next_shot = values.enemy_escort_volley_pause else: self.next_shot = values.enemy_escort_volley_cooldown
class Player(Ship): position = Vector(0, -9) heading = Vector(0, 0) guns = 0 engines = 0 health = values.player_health images = [[ Image(f"shooter/resources/ship/g{g}e{e}.png") for e in range(4) ] for g in range(4)] def on_update(self, update: ppb_events.Update, signal): if self.health <= 0: update.scene.remove(self) update.scene.add( RunOnceAnimation( position=self.position, life_span=0.25, image=Animation( "shooter/resources/explosions/player/sprite_{1..7}.png", 24), end_event=shooter_events.PlayerDied(), size=2)) signal(ppb_events.PlaySound(sounds["dead"])) controller = update.controls self.heading = Vector(controller.get("horizontal"), controller.get("vertical")) if self.heading: self.heading = self.heading.normalize() self.move(update.time_delta) def on_shoot(self, shoot_event: shooter_events.Shoot, signal): scene = shoot_event.scene tags = ["bullet", "friendly"] signal(ppb_events.PlaySound(sounds["player_laser"])) initial_x, initial_y = self.top.center for offset in range(2 * self.guns + 1): scene.add( Bullet(position=Vector( initial_x + (-0.5 * self.guns) + (0.5 * offset), initial_y), tags=tags)) def on_power_up(self, power_up_event: shooter_events.PowerUp, signal): if (power_up_event.kind == PowerUps.GUN and self.guns < values.player_gun_max): self.guns += 1 if (power_up_event.kind == PowerUps.ENGINE and self.engines < values.player_engine_max): self.engines += 1 elif power_up_event.kind == PowerUps.SHIELD: if not list(power_up_event.scene.get(tag="shield")): power_up_event.scene.add(Shield(parent=self, position=self.position), tags=["player"]) @property def speed(self): return values.player_base_speed + (self.engines * values.player_engine_bonus) @property def image(self): return self.images[self.guns][self.engines]