Beispiel #1
0
class Frostbeam(PlayerMove):
    """Class for representing the player's frostbeam move."""
    def __init__(self):
        super().__init__(30)
        self.icon = Image("player/frostbeam_move_icon_solid.png")
        self.icon_faded = Image("player/frostbeam_move_icon_faded.png")
        self.info = Image("player/frostbeam_move_info.png")
        self.sound = Audio("player/frostbeam_move.ogg", 0.2)

        self.frostbeam_start = Image("player/frostbeam_start.png", (215, 381))
        self.frostbeam_middle = Image("player/frostbeam_middle.png")
        self.frostbeam_end = Image("player/frostbeam_end.png")

        self.duration = 0
        self.total_duration = 2 * self.game.fps

    def run(self):
        self.opponent.display()
        self.user.character_frostbeam_stance.display()
        if self.duration < self.total_duration:
            if self.duration == 0:
                self.play_sound()
            elif self.duration == self.total_duration // 2:
                self.opponent.damage(random.randint(15, 30))
            self.frostbeam_start.display()
            for x in range(14):
                self.frostbeam_middle.display(265 + 50 * x, 383 + 2 * x)
            self.duration += 1
        else:  # Resetting variables for next time
            self.duration = 0
            self.opponent.next_move()
Beispiel #2
0
class KanyeSnake(Opponent):
    """Class representing the Kanye Snake opponent."""
    def __init__(self, game, max_hp=120, max_mana=120):
        super().__init__(game, "Kanye Snake", max_hp, max_mana)
        self.x = 930
        self.y = 440

        self.snake_normal = Image("kanye_snake/snake_normal.png",
                                  (self.x, self.y))
        self.snake_dead = Image("kanye_snake/snake_dead.png", (self.x, self.y))
        self.snake_backwards = Image("kanye_snake/snake_backwards.png")
        self.snake_moving = Image("kanye_snake/snake_moving.png")
        self.snake_venom_stance = Image("kanye_snake/snake_venom_stance.png",
                                        (self.x, self.y))
        self.snake_laser_stance = Image("kanye_snake/snake_laser_stance.png",
                                        (self.x, self.y))

        Moves = namedtuple("Moves", "heal confuse venom laser")
        self.moves = Moves(OpponentHeal(1005, 230, 410), Confuse(), Venom(),
                           Laser())

    def choose_move(self):
        """Return the move that the snake decides to use."""
        if self.current_mana < 10:  # Only usable move
            return self.moves.confuse

        if self.game.player.current_hp < 20:
            return random.choice(self.attack_options(favour_damage=True))

        if self.current_hp < self.max_hp / 5:
            if random.randint(1, 10) == 1:
                return random.choice(self.attack_options())
            return self.moves.heal

        options = self.attack_options()
        if self.current_hp <= 3 * (self.max_hp / 4):
            options.append(self.moves.heal)
        return random.choice(options)

    def attack_options(self, *, favour_damage=False):  # pylint: disable=arguments-differ
        """Return the options the snake can/would choose from for attacking based on his mana."""
        moves = super().attack_options()
        if len(moves) > 1 and favour_damage:
            moves.remove(self.moves.confuse)
        return moves

    def _idle_display(self):
        self.snake_normal.display()

    def _dead_display(self):
        self.snake_dead.display()
Beispiel #3
0
class MemeDog(Opponent):
    """Class representing the Meme Dog opponent."""
    def __init__(self, game, max_hp=100, max_mana=100):
        super().__init__(game, "Meme Dog", max_hp, max_mana)
        self.x = 930
        self.y = 440

        self.dog_normal = Image("meme_dog/dog_normal.png", (self.x, self.y))
        self.dog_dead = Image("meme_dog/dog_dead.png", (self.x, self.y))
        self.dog_backwards = Image("meme_dog/dog_backwards.png")
        self.dog_bark_stance = Image("meme_dog/dog_bark_stance.png",
                                     (self.x, self.y))

        Moves = namedtuple("Moves", "heal bark bite spin")
        self.moves = Moves(OpponentHeal(1005, 230, 410), Bark(), Bite(),
                           Spin())

    def choose_move(self):
        """Return the name of the next move that the dog decides to use."""
        if self.current_mana < 10:  # Only usable move
            return self.moves.bark

        if self.game.player.current_hp < 15:  # Try to finish the player off
            return random.choice(self.attack_options())

        if self.current_hp < self.max_hp / 4:  # Low - prefer to heal but chance of attacking
            if random.randint(1, 10) == 1:
                return random.choice(self.attack_options())
            return self.moves.heal

        options = self.attack_options()
        if self.current_hp <= 3 * (self.max_hp / 4):
            options.append(self.moves.heal)
        return random.choice(options)

    def _idle_display(self):
        self.dog_normal.display()

    def _dead_display(self):
        self.dog_dead.display()
Beispiel #4
0
class EvilCloud(Opponent):
    """Class representing the Evil Cloud opponent."""
    def __init__(self, game, max_hp=180, max_mana=300):
        super().__init__(game, "Evil Cloud", max_hp, max_mana)
        self.x = 930
        self.y = 400

        self.normal = Image("evil_cloud/evil_cloud_normal.png",
                            (self.x, self.y))

        Moves = namedtuple("Moves", "heal")
        self.moves = Moves(OpponentHeal(1005, 230, 410))

    def choose_move(self):
        """Return the move that the spook cloud decides to use."""
        return self.moves.heal

    def _idle_display(self):
        self.normal.display()

    def _dead_display(self):
        pass
Beispiel #5
0
class Heal(PlayerMove):
    """Class for representing the player's heal move."""
    def __init__(self, heart_x, start_y, end_y):
        super().__init__(10)
        self.icon = Image("player/heal_move_icon_solid.png")
        self.icon_faded = Image("player/heal_move_icon_faded.png")
        self.info = Image("player/heal_move_info.png")
        self.sound = Audio("player/heal_move.ogg", 0.1)

        self.heart = Image("player/heal_heart.png")

        self.heart_x = heart_x
        self.start_y = start_y
        self.end_y = end_y
        self.heart_y = self.start_y
        self.delay_duration = 0

    @property
    def total_delay_duration(self):
        return self.user.display_stat_change_duration

    def run(self):
        self.user.display()
        self.opponent.display()
        if self.heart_y < self.end_y:
            if self.heart_y == self.start_y:
                self.play_sound()
            self.heart.display(self.heart_x, self.heart_y)
            self.heart_y += 5
        elif self.delay_duration < self.total_delay_duration:  # Allow time for stat change to show
            if self.delay_duration == 0:
                self.user.restore_hp(random.randint(5, 15))
            self.delay_duration += 1
        else:
            self.delay_duration = 0
            self.heart_y = self.start_y
            self.opponent.next_move()
Beispiel #6
0
class SpookDog(Opponent):
    """Class representing the Spook Dog opponent."""
    def __init__(self, game, max_hp=200, max_mana=150):
        super().__init__(game, "Spook Dog", max_hp, max_mana)
        self.x = 930
        self.y = 440
        self.num_idle_frames = 20
        self.idle_fps = 20
        self.idle_frames = [
            Image(f"spook_dog/ghost_dog_normal{n}.png")
            for n in range(self.num_idle_frames)
        ]

        self.ghost_dog_dead = Image("spook_dog/ghost_dog_dead.png",
                                    (self.x, self.y))

        Moves = namedtuple("Moves", "heal teleport glide claw")
        self.moves = Moves(OpponentHeal(1005, 230, 410), Teleport(), Glide(),
                           Claw())

    def choose_move(self):  # pylint: disable=too-many-branches,too-many-return-statements
        """Return the move that the ghost dog decides to use."""
        if self.current_mana < 10:  # Only usable move
            return self.moves.teleport

        if self.game.player.current_hp <= 10 and self.current_mana >= self.moves.claw.mana_cost:
            return self.moves.claw
        if self.game.player.current_hp <= 20:
            return self.moves.glide
        if self.game.player.current_hp <= 30:
            if self.current_mana < 50:
                options = {self.moves.teleport: 3, self.moves.glide: 6}
            elif self.current_mana <= 140:
                options = {
                    self.moves.teleport: 1,
                    self.moves.glide: 2,
                    self.moves.claw: 6
                }
            else:
                options = {
                    self.moves.glide: 2.3333333333,
                    self.moves.claw: 6.6666666667
                }
            if self.current_hp <= 180:
                options[self.moves.heal] = 1
            return self.random_weighted(options)

        if self.current_hp < 25:
            if self.current_mana < 50:
                return self.random_weighted({
                    self.moves.teleport: 0.1,
                    self.moves.glide: 0.1,
                    self.moves.heal: 0.8
                })
            if self.game.player.current_hp <= 40:
                return random.choice([self.moves.claw, self.moves.heal])

            if random.random() < 0.1:
                return random.choice(self.attack_options())
            return self.moves.heal

        options = self.attack_options()
        if self.current_hp <= 0.9 * self.max_hp:
            options.append(self.moves.heal)
        return random.choice(options)

    def _idle_display(self):
        self.idle_animation(self.x, self.y)

    def _dead_display(self):
        self.ghost_dog_dead.display()
Beispiel #7
0
class Player(Character):
    """Class representing the Player (the character controlled by the user)."""

    CHARACTER_1 = "character1"
    CHARACTER_2 = "character2"

    CHOOSE_CHARACTER = "choose character"
    CHOOSE_ABILITY = "choose ability"
    DEAD = "player dead"

    INFO_X = 10

    def __init__(self, game, name="Sunni", character=None, *, level=1):
        super().__init__(game,
                         name,
                         level=level,
                         display_stat_x=170,
                         display_stat_y_start=360)
        self.calculate_stats()
        self.fully_restore()
        self.x = 150
        self.y = 380
        self.num_idle_frames = 4
        self.idle_fps = 6
        self.character = character

        Moves = namedtuple("Moves", "heal kick headbutt frostbeam")
        self.moves = Moves(Heal(160, 170, 350), Kick(), Headbutt(),
                           Frostbeam())
        self.offensive_moves = [
            self.moves.kick, self.moves.headbutt, self.moves.frostbeam
        ]
        self.defensive_moves = [self.moves.heal]
        self.selected_moves = None

    @property
    def character(self):
        return self._character

    @character.setter
    def character(self, character):
        self._character = character
        if character is None:
            return
        self.idle_frames = [
            Image(f"player/{character}_normal{n}.png")
            for n in range(self.num_idle_frames)
        ]
        self.character_normal = Image(f"player/{character}_normal1.png")
        self.character_backwards = Image(f"player/{character}_backwards.png")
        self.character_scared = Image(f"player/{character}_scared.png",
                                      (self.x, self.y))
        self.character_scared_redflash = Image(
            f"player/{character}_scared_redflash.png", (self.x, self.y))
        self.character_tilt_left = Image(f"player/{character}_tilt_left.png")
        self.character_tilt_right = Image(f"player/{character}_tilt_right.png")
        self.character_dead = Image(f"player/{character}_dead.png")
        self.character_headbutt_stance = Image(
            f"player/{character}_headbutt_stance.png")
        self.character_frostbeam_stance = Image(
            f"player/{character}_frostbeam_stance.png", (self.x, self.y))

    def level_up(self, levels=1.0, restore=True):
        """Level the player up by the given number of levels (default 1).
        Restores the player to full if they pass an integer level and `restore==True` (default).
        """
        old_level = self.level
        self.level += levels
        if int(self.level) > int(old_level):  # i.e. if we actually levelled up
            self.calculate_stats()
            if restore:
                self.fully_restore()

    def calculate_stats(self):
        self.max_hp = 90 + 10 * int(self.level)
        self.max_mana = 95 + 5 * int(self.level)

    def use_move(self, move):
        try:
            self.change_mana(move)
        except NotEnoughManaError:
            self.game.page.show_mana_notification()
        else:
            self.selected_moves = None
            self.game.page.hide_mana_notification()
            self.game.page.current = move

    def next_move(self):
        """Continues to find out the player's next move."""
        if self.is_dead:
            self.game.page.current = self.DEAD
            self.level_up(0.25, restore=False)
            self.game.save()
            return
        self.game.page.current = self.CHOOSE_ABILITY

    def _idle_display(self):
        self.idle_animation(self.x, self.y)

    def _dead_display(self):
        self.character_dead.display(150, 480)