def __init__(self, x, y, speed, damage, angle, homing_shots) -> pygame.sprite.Sprite: pygame.sprite.Sprite.__init__(self) self.move_speed = ml.normalize_target_fps(float(speed)) self.damage = damage self.current_angle = ml.normalize_angle(angle) self.angle_r = math.radians(angle) self.turning_rate = ml.normalize_target_fps(3.5) self.homing = homing_shots # Set up image, rect, and mask if self.homing: self.image = ml.get_bullet_image('homing') else: self.image = ml.get_bullet_image('player') self.width = self.image.get_width() self.height = self.image.get_height() self.original_image = self.image # self.image = pygame.transform.rotate(self.image, angle) self.x = x self.y = y self.rect = pygame.Rect(0, 0, self.width, self.height) self.rect.center = self.x, self.y self.mask = pygame.mask.from_surface(self.image) # Add sprite to group self.add(ml.player_bullet_group)
def phase4(self): self.rotation_rate = ml.normalize_target_fps(6) if self.move_speed >= self.max_speed: self.move_speed = self.max_speed else: self.move_speed += ml.normalize_target_fps(0.015) if self.turning_rate >= self.max_turning_rate: self.turning_rate = self.max_turning_rate else: self.turning_rate += ml.normalize_target_fps(0.005) self.circle_random_timer = self.shoot(self.circle_random_timer, self.circle_random_bd, self.circle_random_fd) self.move()
def phase2(self): if ml.time() - self.spiral_timer >= self.spiral_fd.firing_speed: self.spiral_bd.turning_rate *= -1 self.rotation_rate = ml.normalize_target_fps(1.5) self.spiral_timer = self.shoot(self.spiral_timer, self.spiral_bd, self.spiral_fd) self.explode_shot_timer = self.shoot(self.explode_shot_timer, self.explode_shot_bd, self.explode_shot_fd)
def __init__(self, start_point, target_point, image_name) -> pygame.sprite.Sprite: pygame.sprite.Sprite.__init__(self) self.x, self.y = start_point self.falling_speed = ml.normalize_target_fps(1) self.homing_speed = ml.normalize_target_fps(4) self.from_spawn_speed = ml.normalize_target_fps(7) self.homing_distance = 75 self.moving_from_spawn = True self.target_point = target_point # Set up image, rect, and mask self.image_path = os.path.join('graphics', image_name) self.image = pygame.image.load(self.image_path).convert_alpha() self.rect = self.image.get_rect() self.mask = pygame.mask.from_surface(self.image) self.rect.center = self.x, self.y # Add sprite to group self.add(ml.powerup_group)
def phase3(self): self.turning_rate = ml.normalize_target_fps(10) # Match the player's speed self.move_speed = ml.normalize_target_fps( float(ml.get_upgrade_values('Movement Speed')) - 1) # Keep the boss positioned above the player above_player = (ml.player.rect.centerx, ml.player.rect.centery - 350) self.x, self.y, self.movement_angle = ml.move_point( self, above_player, self.move_speed, self.movement_angle, self.turning_rate) # Keep boss on screen if self.rect.centery < 0: self.y = 0 # Face the player self.current_angle = ml.angle_to_point(self.rect.center, ml.player.rect.center) # Shoot self.phase2_bd = BulletData(self, coords=self.rect.center, speed=7) self.phase2_timer = self.shoot(self.phase2_timer, self.phase2_bd, self.phase2_fd) self.phase2spread_timer = self.shoot(self.phase2spread_timer, self.phase2spread_bd, self.phase2spread_fd) # Left arc self.phase2arc_bd.coords = self.rect.midleft self.phase2arc_fd.angle = ml.burst_angles(20, 180, 10)[self.phase2arc_counter] self.phase2arc_timer, self.phase2arc_counter = \ self.shoot(self.phase2arc_timer, self.phase2arc_bd, self.phase2arc_fd, self.phase2arc_counter) # Right arc self.phase2arc_bd.coords = self.rect.midright self.phase2arc_fd.angle = ml.burst_angles(20, 0, -10)[self.phase2arc2_counter] self.phase2arc2_timer, self.phase2arc2_counter = \ self.shoot(self.phase2arc2_timer, self.phase2arc_bd, self.phase2arc_fd, self.phase2arc2_counter)
def phase2(self): # Mirror player movement rotation_rate = 15 if not self.current_angle % rotation_rate: self.current_angle -= self.current_angle % rotation_rate mirror_point = ml.player.rect.centerx * -1 + ml.window_width, \ ml.player.rect.centery * -1 + ml.window_height self.x, self.y, _ = ml.move_point(self, mirror_point, 20, 0, 360) # Rotate if player moves above/below if self.y > ml.player.rect.centery: if self.current_angle != 90 and self.x > ml.player.rect.centerx: self.current_angle -= rotation_rate elif self.current_angle != 90 and self.x < ml.player.rect.centerx: self.current_angle += rotation_rate else: if self.current_angle != 270 and self.x > ml.player.rect.centerx: self.current_angle += rotation_rate elif self.current_angle != 270 and self.x < ml.player.rect.centerx: self.current_angle -= rotation_rate # Shoot self.phase1homing_timer = self.shoot(self.phase1homing_timer, self.phase1homing_bd, self.phase1homing_fd) bullet_speed = 7 distance = abs(ml.player.rect.centery - self.rect.centery) duration_f = distance / bullet_speed duration_s = duration_f / ml.normalize_target_fps(60) self.phase1_bd = BulletData(self, speed=bullet_speed, duration=duration_s, exploding=self.phase1explode) self.phase1_fd = FiringData(firing_speed=2, angle=self.current_angle) self.phase1_timer = self.shoot(self.phase1_timer, self.phase1_bd, self.phase1_fd)
def update_move_speed(self): self.move_speed = ml.normalize_target_fps( float(ml.get_upgrade_values('Movement Speed'))) self.diagonal_move_speed = self.move_speed * math.sin(math.pi / 4)
def __init__(self) -> pygame.sprite.Sprite: pygame.sprite.Sprite.__init__(self) self.health = ml.get_upgrade_values('Max Health') self.hitbox_width = 5 self.move_speed = float(ml.get_upgrade_values('Movement Speed')) self.shift_speed = ml.normalize_target_fps(2) self.diagonal_move_speed = 0 self.invincibility_duration = 1 # Seconds of invulnerability after taking damage self.last_hit_time = -999 self.hit_toggle_time = ml.time() self.invincibility_active = False # Shooting self.firing_timer = ml.time() # Set up image, rect, and mask self.image_path = os.path.join('graphics', 'player.png') self.homing_image_path = os.path.join('graphics', 'player_homing.png') self.invisible_image_path = os.path.join('graphics', 'player_invisible.png') self.image = pygame.image.load(self.image_path).convert_alpha() self.homing_image = pygame.image.load( self.homing_image_path).convert_alpha() self.invisible_image = pygame.image.load( self.invisible_image_path).convert_alpha() self.image_original = self.image # Even width prevents proper centering of hitbox and mouse movement assert self.image.get_width() % 2, "Player image width must be odd." self.x = ml.window_width / 2 self.y = ml.window_height - 100 self.rect = pygame.Rect(0, 0, self.image.get_width(), self.image.get_height()) self.mask = pygame.mask.from_surface(self.image, 250) self.mask_original = self.mask self.hitbox = pygame.Rect(self.rect.centerx, self.rect.centerx, self.hitbox_width, self.hitbox_width) # Create mask for hitbox to deal with enemy collision self.hitbox_mask = pygame.mask.Mask(self.rect.size) self.rect.topleft = 0, 0 top_left = self.rect.centerx - self.hitbox_width // 2, \ self.rect.centery - self.hitbox_width // 2 for x in range(self.hitbox_width): current_x = top_left[0] + x for y in range(self.hitbox_width): current_y = top_left[1] + y self.hitbox_mask.set_at((current_x, current_y), 1) self.rect.center = self.x, self.y # Powerups self.shield_active = False self.shield = None self.heal_amount = 1 self.homing_shots_active = False self.homing_shots_activation_time = None self.toggle_time = None # Add sprite to group self.add(ml.player_group) ml.update_player_data(self) ml.update_player_health()
def __init__(self, bullet_data, angle) -> pygame.sprite.Sprite: pygame.sprite.Sprite.__init__(self) self.infinite_explosion = bullet_data.infinite_explosion self.original_bullet_data = bullet_data self.despawn_range = 200 self.original_parent = bullet_data.original_parent if bullet_data.random_speed != (0, 0): a, b = bullet_data.random_speed self.move_speed = ml.normalize_target_fps(random.uniform(a, b)) else: self.move_speed = bullet_data.speed self.damage = bullet_data.damage self.angle = angle # normalized by FiringData self.angle_r = math.radians(angle) if bullet_data.random_duration == (0, 0): self.duration = bullet_data.duration else: a, b = bullet_data.random_duration self.duration = random.uniform(a, b) self.homing_shots_active = bullet_data.homing self.turning_rate = bullet_data.turning_rate if bullet_data.exploding: self.exploding = True self.exploding_list = bullet_data.exploding[:] self.exploding_bullet_data, self.exploding_firing_data = self.exploding_list[ 0] if not self.infinite_explosion: del self.exploding_list[0] else: self.exploding = False self.spawn_time = ml.time() self.diag_move_x = self.move_speed * math.cos(math.radians(self.angle)) self.diag_move_y = self.move_speed * math.sin(math.radians(self.angle)) # Set up image, rect, and mask if bullet_data.homing: self.image = ml.get_bullet_image('homing') elif bullet_data.exploding: self.image = ml.get_bullet_image('exploding') else: self.image = ml.get_bullet_image('enemy') self.rect = pygame.Rect(0, 0, self.image.get_width(), self.image.get_height()) if bullet_data.coords: self.x, self.y = bullet_data.coords else: self.x, self.y = bullet_data.parent.rect.center self.spawn_point = self.x, self.y self.spiral = bullet_data.spiral self.radial_growth = bullet_data.radial_growth self.radius = 0 self.rect.center = self.x, self.y self.mask = pygame.mask.from_surface(self.image, 250) self.mask_rect = self.mask.get_bounding_rects()[ 0] # Set in get_mask_rect() # Add to group self.add(ml.enemy_bullet_group)
def __init__(self, original_parent, parent=None, coords=None, damage=1, speed=0, random_speed=(0, 0), duration=5, random_duration=(0, 0), homing=False, turning_rate=0, spiral=False, radial_growth=0, exploding=None, infinite_explosion=False): """ This class is for storing data that will be passed to EnemyBullets through Enemy.shoot() -- coords is a 2-tuple of the coordinates to spawn the bullet at. This should usually be the center of the shooting sprite. -- random_speed, if defined, will be passed to random.uniform() to determine the speed of the bullets, and will override speed. -- random_duration, if defined, will be passed to random.uniform() to determine the duration of the bullets. random_duration overrides duration. -- homing and turning_rate must both be defined for bullets to home on player. -- exploding should be a list of tuples: (BulletData, FiringData). Each tuple in the list represents one stage of explosion. If infinite_explosion is set to True on both the original BulletData and the BulletData of the exploding tuple, the first tuple of exploding will be used for every explosion, and it will not stop until the bullets are killed by an outside force. Note: infinite_explosion WILL lag unless it is either only spawning 1 bullet to replace the one exploding, or if something else is killing the bullets. -- spiral will set the bullet to spiral mode. In spiral mode, turning_rate will determine the speed that the bullet spirals outward from its spawn point. spiral overrides homing. radial_growth is the amount that the radius of the spiral will increase by each frame. """ self.original_parent = original_parent if parent: self.parent = parent else: self.parent = self.original_parent self.coords = coords self.damage = damage self.random_speed = random_speed self.speed = ml.normalize_target_fps(speed) self.duration = duration self.random_duration = random_duration self.homing = homing self.turning_rate = ml.normalize_target_fps(turning_rate) self.exploding = exploding self.infinite_explosion = infinite_explosion self.spiral = spiral self.radial_growth = ml.normalize_target_fps(radial_growth)
def __init__(self) -> pygame.sprite.Sprite: # General data self.image_name = 'ring.png' self.invisible_image_path = os.path.join('graphics', 'ring_invisible.png') self.boss_invisible_image = \ pygame.image.load(self.invisible_image_path).convert_alpha() self.health = ring_health self.collision_damage = 1 self.move_speed = ml.normalize_target_fps(0) self.turning_rate = ml.normalize_target_fps(2) self.base_turning_rate = ml.normalize_target_fps(2) self.name = 'Ring' super().__init__(ml.window_width / 2, self.move_speed, self.health, self.collision_damage, self.image_name, turning_rate=self.turning_rate, y=300, boss=True, name=self.name) # Spawn parts (in draw order) self.ring1 = BossPart('ring1_red.png') self.ring2 = BossPart('ring2_red.png') self.part_color = 'red' # Phase data self.phase_change_time = ml.time() - 2 self.phase_change_delay = 5 self.phase1_delay = self.phase_change_delay - 2 self.circle_angle = 90 # self.shield_radius = (self.shield.get_mask_rect().width / 2) - 6 # Phase 1 phase1_firing_speed = 1 self.phase1bd = BulletData(self, speed=4) # angle will be modified in phase1() self.phase1fd = FiringData(firing_speed=phase1_firing_speed, multi=9) self.phase1timer1 = ml.time() + self.phase1_delay self.phase1timer2 = ml.time() + self.phase1_delay self.phase1timer3 = ml.time() + self.phase1_delay + ( 1 / (2 * phase1_firing_speed)) self.phase1timer4 = ml.time() + self.phase1_delay + ( 1 / (2 * phase1_firing_speed)) # Phase 2 self.phase2exbd = BulletData(self, speed=5, random_duration=(1.2, 1.5), infinite_explosion=True) self.phase2exfd = FiringData(aim=True) self.phase2ex = [(self.phase2exbd, self.phase2exfd)] self.phase2bd = BulletData(self, speed=3, duration=2, exploding=self.phase2ex, infinite_explosion=True) self.phase2fd = FiringData(firing_speed=0.2, aim=True) self.phase2timer = ml.time() self.shot_alive = False # Fake exploding data to make the bullets orange self.fakebd = BulletData(self, duration=0) self.fakefd = FiringData() self.fakeex = [(self.fakebd, self.fakefd)] self.phase2minionbd = BulletData(self, duration=0.5, turning_rate=6, spiral=True, radial_growth=3, exploding=self.fakeex) self.phase2minionfd = FiringData(firing_speed=5, interval=45, multi=8, aim=True) self.phase2minion_timer = ml.time() # Phase 3 self.phase3exbd = BulletData(self, speed=8, homing=True, turning_rate=0.6) self.phase3exfd = FiringData(aim=True) self.phase3ex = [(self.phase3exbd, self.phase3exfd)] self.phase3bd = BulletData(self, speed=6, duration=0.4, exploding=self.phase3ex) self.phase3fd = FiringData(firing_speed=0.6, multi=5, interval=35) self.phase3timer = ml.time() self.phase3minionbd1 = BulletData(self, speed=5, homing=True, turning_rate=0.4) self.phase3minionbd2 = BulletData(self, speed=5, homing=True, turning_rate=0.4) self.phase3minionfd = FiringData(firing_speed=0.5, aim=True) self.phase3miniontimer1 = ml.time() self.phase3miniontimer2 = ml.time() # Phase 4 self.laser_damage = 2 # These methods are called depending on the boss's current phase self.phase_method_list = [ self.phase1, self.phase2, self.phase3, self.phase4 ] self.num_phases = len(self.phase_method_list) self.test_timer = ml.time()
def __init__(self) -> pygame.sprite.Sprite: # General data self.image_name = 'boss1.png' self.invisible_image_path = os.path.join('graphics', 'boss_invisible.png') self.boss_invisible_image = \ pygame.image.load(self.invisible_image_path).convert_alpha() self.health = starburst_health self.collision_damage = 2 self.move_speed = ml.normalize_target_fps(0) self.max_speed = ml.normalize_target_fps(3.5) self.turning_rate = ml.normalize_target_fps(0) self.max_turning_rate = ml.normalize_target_fps(1.4) self.name = 'Star Burst' super().__init__(ml.window_width / 2, self.move_speed, self.health, self.collision_damage, self.image_name, turning_rate=self.turning_rate, y=350, boss=True, name=self.name) # Animation data self.rotation_angle = 0 self.rotation_rate = ml.normalize_target_fps(0.5) # Phase data self.phase = 1 self.phase_change_time = ml.time() - 2 self.phase_change_delay = 5 # These methods are called depending on the boss's current phase self.phase_method_list = [ self.phase1, self.phase2, self.phase3, self.phase4 ] self.num_phases = len(self.phase_method_list) # Shooting data self.circle_timer = ml.time() self.circle_bd = BulletData(self, speed=2, duration=5.2) self.circle_fd = FiringData(aim=True, multi=36) self.ring_bd = BulletData(self, speed=4) self.ring_firing_speed = 30 self.ring_fd = FiringData(firing_speed=self.ring_firing_speed, interval=180, multi=2, angle=0) self.ring_timer = ml.time() self.spiral_bd = BulletData(self, spiral=True, radial_growth=2.5, turning_rate=0.5) self.spiral_fd = FiringData(multi=18, interval=20) self.spiral_timer = ml.time() self.explode_shot_timer = ml.time() self.explode_bd = [(BulletData(self, speed=3), FiringData(multi=36))] self.explode_shot_bd = BulletData(self, damage=2, speed=2, random_duration=(1.5, 3), exploding=self.explode_bd) self.explode_shot_fd = FiringData(firing_speed=0.5) self.circle_random_bd = BulletData(self, random_speed=(1, 5), duration=10) self.circle_random_fd = FiringData(firing_speed=15) self.circle_random_timer = ml.time()
def __init__(self) -> pygame.sprite.Sprite: # General data self.image_name = 'enemy_clone.png' self.invisible_image_path = os.path.join('graphics', 'enemy_clone_invisible.png') self.boss_invisible_image = \ pygame.image.load(self.invisible_image_path).convert_alpha() self.health = doppelganger_health self.collision_damage = 1 self.move_speed = ml.normalize_target_fps(0) self.turning_rate = ml.normalize_target_fps(2) self.base_turning_rate = ml.normalize_target_fps(2) self.name = 'Doppelganger' super().__init__(ml.window_width / 2, self.move_speed, self.health, self.collision_damage, self.image_name, turning_rate=self.turning_rate, y=300, boss=True, name=self.name) # Phase data self.phase_change_time = ml.time() - 2 self.phase_change_delay = 5 # Phase 4 self.moving_x = True self.moving_y = False self.circle_bd = BulletData(self, speed=2.5, duration=8) self.circle_fd = FiringData(aim=True, multi=36) # Phase 3 self.move_speed_scale = ml.normalize_target_fps(800) self.min_move_speed = ml.normalize_target_fps(3) self.max_move_speed = ml.normalize_target_fps(13) self.movement_angle = self.current_angle # Phase 2 self.phase2_bd = None self.phase2_fd = FiringData(firing_speed=1.2, aim=True, multi=3) self.phase2_timer = ml.time() self.phase2spread_bd = BulletData(self, speed=4) self.phase2spread_fd = FiringData(firing_speed=0.7, interval=8, aim=True, multi=9) self.phase2spread_timer = ml.time() self.phase2arc_bd = BulletData(self, speed=3) self.phase2arc_fd = FiringData(firing_speed=0.7, angle=None, burst=9, burst_delay=0.1) self.phase2arc_timer = ml.time() self.phase2arc_counter = 0 self.phase2arc2_timer = ml.time() self.phase2arc2_counter = 0 # Phase 1 self.phase1homing_bd = BulletData(self, speed=5, duration=7, homing=True, turning_rate=1.7) self.phase1homing_fd = FiringData(firing_speed=0.15, interval=180, angle=0, multi=2) self.phase1homing_timer = ml.time() self.phase1_timer = ml.time() self.phase1explode_bd = BulletData(self, speed=10) self.phase1explode_fd = FiringData(interval=180, angle=0, multi=2) self.phase1explode = [(self.phase1explode_bd, self.phase1explode_fd)] self.phase1_bd = None self.phase1_fd = None # These methods are called depending on the boss's current phase self.phase_method_list = [ self.phase1, self.phase2, self.phase3, self.phase4 ] self.num_phases = len(self.phase_method_list) # Shooting data self.mine_timer = ml.time() self.mine_explosion_bd = BulletData(self, speed=5) self.mine_explosion_fd = FiringData(interval=36, angle=45, multi=10, aim=True) self.mine_explosion_data = (self.mine_explosion_bd, self.mine_explosion_fd) self.mine_bd = BulletData(self, duration=2, damage=2, exploding=[self.mine_explosion_data]) self.mine_fd = FiringData() self.test_timer = ml.time()
def phase3(self): self.rotation_rate = ml.normalize_target_fps(3.5) self.explode_shot_fd.firing_speed = 3 self.explode_shot_timer = self.shoot(self.explode_shot_timer, self.explode_shot_bd, self.explode_shot_fd)