Ejemplo n.º 1
0
 def phase1(self):
     self.move_speed = 2
     # After y is lined up, turn toward player and starting moving on the y axis
     if self.moving_x and \
             abs(self.x - ml.player.rect.centerx) <= \
             self.move_speed + float(ml.get_upgrade_values('Movement Speed')):
         self.moving_x = False
         self.moving_y = True
         _ = self.shoot(-999, self.circle_bd, self.circle_fd)
     # After x is lined up, turn toward player and starting moving on the x axis
     if self.moving_y and \
             abs(self.y - ml.player.rect.centery) <= \
             self.move_speed + float(ml.get_upgrade_values('Movement Speed')):
         self.moving_x = True
         self.moving_y = False
         _ = self.shoot(-999, self.circle_bd, self.circle_fd)
     # Move until self.x lines up with player's x
     if self.rect.centerx != ml.player.rect.centerx and self.moving_x:
         self.x, self.y, self.current_angle = ml.move_point(
             self, (ml.player.rect.centerx, self.rect.centery),
             self.move_speed, 0, 360)
     else:
         self.moving_x = False
         self.moving_y = True
     # Move until self.y lines up with player's y
     if self.rect.centery != ml.player.rect.centery and self.moving_y:
         self.x, self.y, self.current_angle = ml.move_point(
             self, (self.rect.centerx, ml.player.rect.centery),
             self.move_speed, 0, 360)
     else:
         self.moving_x = True
         self.moving_y = False
Ejemplo n.º 2
0
    def update_powerups(self):
        # Update shield
        if self.shield and not self.shield.alive():
            self.shield_active = False
            self.shield = None
        elif self.shield:
            self.shield_active = True

        # Update homing shots
        if self.homing_shots_active:
            if ml.time() - self.homing_shots_activation_time >= \
                    ml.get_upgrade_values('Homing Duration'):
                self.homing_shots_active = False
                self.image = self.image_original
            if not self.invincibility_active:
                self.image = self.homing_image
            # Flicker sprite color when Homing duration is low
            if ml.time() - self.homing_shots_activation_time > \
                    ml.get_upgrade_values('Homing Duration') - 1:
                if ml.time() - self.toggle_time > 0.15:
                    if self.image == self.image_original:
                        self.toggle_time = ml.time()
                        self.image = self.homing_image
                    else:
                        self.toggle_time = ml.time()
                        self.image = self.image_original
Ejemplo n.º 3
0
 def reset_duration(self):
     if not ml.time() - self.spawn_time > self.duration:
         self.duration = ml.get_upgrade_values('Shield Duration')
     self.spawn_tick = ml.ticks
     self.bar_stage_duration = (ml.get_upgrade_values('Shield Duration') *
                                ml.framerate) / len(self.bar_stage_images)
     self.ticks_elapsed = 0
     self.spawn_time = ml.time()
Ejemplo n.º 4
0
 def shoot(self):
     if ml.time() - self.firing_timer >= (
             1 / ml.get_upgrade_values('Attack Speed')):
         shot_angles = ml.multi_shot_angles(
             ml.get_upgrade_values('Multi Shot'), 90, 10)
         for i in range(ml.get_upgrade_values('Multi Shot')):
             PlayerBullet(self.rect.centerx, self.rect.y,
                          ml.get_upgrade_values('Bullet Speed'),
                          ml.get_upgrade_values('Damage'), shot_angles[i],
                          self.homing_shots_active)
         self.firing_timer = ml.time()
Ejemplo n.º 5
0
 def damage(self, damage: int):
     if damage > 0 and not self.shield_active and \
                             ml.time() - self.last_hit_time > self.invincibility_duration:
         self.health -= damage
         self.invincibility_active = True
         self.last_hit_time = ml.time()
         self.hit_toggle_time = ml.time()
     # Heal
     elif damage < 0:
         self.health -= damage
     if self.health > ml.get_upgrade_values('Max Health'):
         self.health = ml.get_upgrade_values('Max Health')
     ml.update_player_health()
Ejemplo n.º 6
0
    def __init__(self) -> pygame.sprite.Sprite:
        pygame.sprite.Sprite.__init__(self)
        self.spawn_time = ml.time()
        self.spawn_tick = ml.ticks
        self.duration = ml.get_upgrade_values('Shield Duration')
        self.image_path = os.path.join('graphics', 'shield.png')
        self.image = pygame.image.load(self.image_path)
        self.image_original = pygame.image.load(self.image_path)
        self.shield_mask = pygame.mask.from_surface(self.image)
        self.rect = self.image.get_rect()
        self.add(ml.powerup_effect_group)

        # Animation
        self.animation_duration = 0.2
        self.duration_ticks = ml.get_upgrade_values('Shield Duration') * ml.framerate
        # 1 animation stage per frame
        self.animation_stages = int(ml.framerate * self.animation_duration)
        self.stage_duration = self.animation_duration / self.animation_stages
        self.stage_width = self.image.get_width() / self.animation_stages
        self.stage_height = self.image.get_height() / self.animation_stages
        self.stage_images = []
        for count in range(self.animation_stages):
            self.stage_images.append(pygame.transform.smoothscale(self.image_original,
                (int(self.stage_width * count), int(self.stage_height * count))))
        self.stage = 0
        self.ticks_elapsed = 0

        # Set up bar
        self.bar_image_path = os.path.join('graphics', 'shield_bar.png')
        self.bar_image = pygame.image.load(self.bar_image_path)
        assert self.bar_image.get_width() % 2, 'bar_image width must be odd.'
        self.bar_image_original = self.bar_image
        self.bar_stage_images = [self.bar_image]
        # Create list of bar surfaces with decreasing widths
        for i in range(self.bar_image.get_width() // 2):
            self.bar_stage_images.append(
                    pygame.transform.smoothscale(self.bar_image_original,
                                                 (self.bar_stage_images[i].get_width() - 2,
                                                  self.bar_image.get_height())
                                                 ))
        self.bar_stage_images.append(
                pygame.transform.smoothscale(self.bar_image_original,
                                             (0, self.bar_image.get_height())))
        self.bar_stage_duration = (self.duration * ml.framerate) / \
            len(self.bar_stage_images)
        self.next_bar_image = None
        self.bar = ShieldBar()
Ejemplo n.º 7
0
 def spawn_random(start_point):
     if ml.time() - PowerUp.spawn_timer > ml.get_upgrade_values('Powerup Interval'):
         PowerUp.spawn_timer = ml.time()
         powerup = random.randint(0, 4)
         if powerup == 0:
             HomingShots(start_point, start_point)
         elif powerup == 1:
             Shield(start_point, start_point)
         elif powerup == 2:
             Heal(start_point, start_point)
         elif powerup == 3:
             Bomb(start_point, start_point)
Ejemplo n.º 8
0
    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)
Ejemplo n.º 9
0
 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)
Ejemplo n.º 10
0
    def check_collision(self):
        """Check and deal with collision between Player and anything else."""

        # Check collision with enemies
        # Check rect collision first
        if not self.shield_active:  # Disable collision when shield is on
            enemies_hit = pygame.sprite.spritecollide(self, ml.enemy_group,
                                                      False)
            if enemies_hit:
                # Change mask to hitbox mask before checking collision
                self.mask = self.hitbox_mask
                for enemy in enemies_hit:
                    if not enemy.invincible:
                        # Check mask collision
                        enemy.update_mask()  # proper mask for rotating enemies
                        if pygame.sprite.collide_mask(self, enemy):
                            self.damage(enemy.get_damage())
                # Change mask back to normal
                self.mask = self.mask_original

        # Check collision with enemy bullets
        enemy_bullets_hit = pygame.sprite.spritecollide(
            self, ml.enemy_bullet_group, False)
        if enemy_bullets_hit:
            for enemy_bullet in enemy_bullets_hit:
                # Hitbox collision
                if self.hitbox.colliderect(enemy_bullet.get_mask_rect()):
                    self.damage(enemy_bullet.get_damage())
                    enemy_bullet.kill()

        # Check collision with powerups
        powerups_hit = pygame.sprite.spritecollide(self, ml.powerup_group,
                                                   False)
        if powerups_hit:
            for powerup in powerups_hit:
                # Mask collision
                if pygame.sprite.collide_mask(self, powerup):
                    if isinstance(powerup, powerups.HomingShots):
                        self.homing_shots_active = True
                        self.homing_shots_activation_time = ml.time()
                        self.image = self.homing_image
                        self.toggle_time = ml.time()
                        powerup.kill()
                    elif isinstance(powerup, powerups.Shield):
                        if not self.shield_active:
                            self.shield = powerups.ShieldEffect()
                        else:
                            self.shield.reset_duration()
                        powerup.kill()
                    elif isinstance(powerup, powerups.Bomb):
                        for enemy in ml.enemy_group.sprites():
                            enemy.damage(ml.get_upgrade_values('Bomb Damage'))
                        powerup.kill()
                    elif isinstance(powerup, powerups.Heal):
                        if self.health < ml.get_upgrade_values('Max Health'):
                            self.damage(-self.heal_amount)
                        if self.health > ml.get_upgrade_values('Max Health'):
                            self.health = ml.get_upgrade_values('Max Health')
                        powerup.kill()
                    elif isinstance(powerup, powerups.Bonus):
                        ml.change_score(500)
                        powerup.kill()
Ejemplo n.º 11
0
    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()
Ejemplo n.º 12
0
 def update_duration(self):
     self.duration = ml.get_upgrade_values('Shield Duration')
     self.bar_stage_duration = (self.duration * ml.framerate) / \
         len(self.bar_stage_images)
Ejemplo n.º 13
0
def upgrade_screen():
    """Shows the upgrade screen."""
    from collections import OrderedDict
    upgrade_list = list(ml.upgrades.keys())
    button_gap = 50
    button_x_list = []
    x_margin = 150
    y_start = 125
    u_button_width = 240
    u_button_height = 75
    name_font_size = 22
    score_margin = 10
    score_font = pygame.font.Font(ml.font, 36)
    value_font = pygame.font.Font(ml.font, 28)
    upgrades_title_font = pygame.font.Font(ml.font, 48)
    upgrades_title = upgrades_title_font.render('Upgrades', True, WHITE)
    continue_button = ml.get_button_surface(button_width, button_height,
                                            'Continue', button_font_size,
                                            WHITE)
    continue_button_rect = pygame.Rect(
        window.get_width() - button_width - x_margin,
        window.get_height() - 75 - continue_button.get_height(), button_width,
        button_height)

    # Creates list with x coordinates alternating between left and right side of window
    for i in range(len(upgrade_list)):
        if i % 2 == 0:
            button_x_list.append(x_margin)
        else:
            button_x_list.append(window.get_width() - x_margin -
                                 u_button_width)

    # Example output: [200, 200, 270, 270, 340, 340, 410, 410, 480, 480]
    button_y_list = [y_start]
    for i in range(len(upgrade_list) - 1):
        if i % 2 == 0:
            button_y_list.append(button_y_list[i])
        else:
            button_y_list.append(button_y_list[i] + button_gap +
                                 u_button_height)

    # Build list of Rects from those x and y coordinates
    button_rect_list = []
    for i, j in enumerate(upgrade_list):
        button_rect_list.append(
            pygame.Rect((button_x_list[i], button_y_list[i]),
                        (u_button_width, u_button_height)))

    # Loop
    while True:
        # Clear the window
        window.fill(BLACK)

        # Show the current score in bottom-left corner
        score_surface = score_font.render('Score: %d' % (ml.score), True,
                                          WHITE)
        window.blit(score_surface, (score_margin, window.get_height() -
                                    score_margin - score_surface.get_height()))

        # Build a list of button surfaces with upgrade names  and values
        button_surfaces = OrderedDict()
        offset = int(-1 * (u_button_height / 4))
        for upgrade in upgrade_list:
            # Create button with upgrade name on it
            button_surfaces[upgrade] = ml.get_button_surface(
                u_button_width, u_button_height, upgrade, name_font_size,
                WHITE, offset)
            value = str(ml.get_upgrade_values(upgrade))
            value_surface = value_font.render(value, True, WHITE)
            # Add the text for the current value of each upgrade
            button_surfaces[upgrade].blit(
                value_surface, ((button_surfaces[upgrade].get_width() / 2) -
                                (value_surface.get_width() / 2),
                                button_surfaces[upgrade].get_height() -
                                value_surface.get_height() -
                                (button_surfaces[upgrade].get_height() / 20)))

        # Handle mouse-over
        pos = pygame.mouse.get_pos()
        for i, rect in enumerate(button_rect_list):
            if rect.collidepoint(pos):
                # Draw upgrade amount next to upgrade value
                upgrade_amount_surface = value_font.render(
                    ('+' if ml.get_upgrade_amount(upgrade_list[i]) >= 0 else
                     '') + str(ml.get_upgrade_amount(upgrade_list[i])), True,
                    GREEN)
                button_surfaces[upgrade_list[i]].blit(
                    upgrade_amount_surface,
                    (button_surfaces[upgrade_list[i]].get_width() -
                     upgrade_amount_surface.get_width() - 10,
                     button_surfaces[upgrade_list[i]].get_height() -
                     upgrade_amount_surface.get_height() -
                     (button_surfaces[upgrade_list[i]].get_height() / 20)))

                # Draw upgrade cost next to score
                cost_surface = score_font.render(
                    '-%d' % ml.get_upgrade_cost(upgrade_list[i]), True, RED)
                window.blit(cost_surface,
                            (score_surface.get_width() + score_margin + 10,
                             window.get_height() - score_margin -
                             cost_surface.get_height()))

        # Event handling
        for event in pygame.event.get():
            if event.type == QUIT:
                terminate()
            # Escape  or space closes the upgrades screen
            elif event.type == KEYDOWN:
                if event.key in (K_ESCAPE, K_SPACE):
                    return
            # Check for click on each button
            elif event.type == MOUSEBUTTONUP:
                for i, rect in enumerate(button_rect_list):
                    if rect.collidepoint(event.pos):
                        ml.purchase_upgrade(upgrade_list[i])
                        break
                # noinspection PyArgumentList
                if continue_button_rect.collidepoint(event.pos):
                    return

        # Draw title
        window.blit(upgrades_title, ((window.get_width() / 2) -
                                     (upgrades_title.get_width() / 2), 30))

        # Draw all of the buttons
        for count, button in enumerate(button_surfaces):
            window.blit(button_surfaces[button], button_rect_list[count])
        window.blit(continue_button, continue_button_rect)

        draw_cursor()
        pygame.display.update()
        clock.tick(FPS)