Пример #1
0
    def startup(self, **kwargs):
        self.state = "normal"

        # this sprite is used to display the item
        # its also animated to pop out of the backpack
        self.item_center = self.rect.width * .164, self.rect.height * .13
        self.item_sprite = Sprite()
        self.item_sprite.image = None
        self.sprites.add(self.item_sprite)

        # do not move this line
        super(ItemMenuState, self).startup(**kwargs)
        self.menu_items.line_spacing = tools.scale(7)

        # this is the area where the item description is displayed
        rect = self.game.screen.get_rect()
        rect.top = tools.scale(106)
        rect.left = tools.scale(3)
        rect.width = tools.scale(250)
        rect.height = tools.scale(32)
        self.text_area = TextArea(self.font, self.font_color, (96, 96, 128))
        self.text_area.rect = rect
        self.sprites.add(self.text_area, layer=100)

        # load the backpack icon
        self.backpack_center = self.rect.width * .16, self.rect.height * .45
        self.load_sprite("gfx/ui/item/backpack.png",
                         center=self.backpack_center,
                         layer=100)
Пример #2
0
    def startup(self, **kwargs):
        self.state = "normal"

        # this sprite is used to display the item
        # its also animated to pop out of the backpack
        self.item_center = self.rect.width * .164, self.rect.height * .13
        self.item_sprite = Sprite()
        self.item_sprite.image = None
        self.sprites.add(self.item_sprite)

        # do not move this line
        super(ItemMenuState, self).startup(**kwargs)
        self.menu_items.line_spacing = tools.scale(7)

        # this is the area where the item description is displayed
        rect = self.game.screen.get_rect()
        rect.top = tools.scale(106)
        rect.left = tools.scale(3)
        rect.width = tools.scale(250)
        rect.height = tools.scale(32)
        self.text_area = TextArea(self.font, self.font_color, (96, 96, 128))
        self.text_area.rect = rect
        self.sprites.add(self.text_area, layer=100)

        # load the backpack icon
        self.backpack_center = self.rect.width * .16, self.rect.height * .45
        self.load_sprite("gfx/ui/item/backpack.png", center=self.backpack_center, layer=100)
Пример #3
0
    def set_font(self, size=5, font=None, color=(10, 10, 10), line_spacing=10):
        """Set the font properties that the menu uses including font _color, size, typeface,
        and line spacing.

        The size and line_spacing parameters will be adjusted the
        the screen scale.  You should pass the original, unscaled values.

        :param size: The font size in pixels.
        :param font: Path to the typeface file (.ttf)
        :param color: A tuple of the RGB _color values
        :param line_spacing: The spacing in pixels between lines of text

        :type size: Integer
        :type font: String
        :type color: Tuple
        :type line_spacing: Integer

        :rtype: None
        :returns: None

        .. image:: images/menu/set_font.png

        """
        if font is None:
            font = prepare.BASEDIR + self.font_filename

        if size < self.min_font_size:
            size = self.min_font_size

        self.line_spacing = tools.scale(line_spacing)
        self.font_size = tools.scale(size)
        self.font_color = color
        self.font = pygame.font.Font(font, self.font_size)
Пример #4
0
    def _initialize_items(self):
        """ Internal use only.  Will reset the items in the menu

        Reset the menu items and get new updated ones.

        :rtype: collections.Iterable[MenuItem]
        """
        self.selected_index = 0
        self.menu_items.empty()
        for item in self.initialize_items():
            self.menu_items.add(item)
        if self.menu_items:
            self.show_cursor()

        # call item selection change to trigger callback for first time
        self.on_menu_selection_change()

        if self.shrink_to_items:
            center = self.rect.center
            rect1 = self.menu_items.calc_bounding_rect()
            rect2 = self.menu_sprites.calc_bounding_rect()
            rect1 = rect1.union(rect2)

            # TODO: do not hardcode these values
            # border is 12, padding is the rest
            rect1.width += tools.scale(18)
            rect1.height += tools.scale(19)
            rect1.topleft = 0, 0

            # self.rect = rect1.union(rect2)
            # self.rect.width += tools.scale(20)
            # self.rect.topleft = 0, 0
            self.rect = rect1
            self.rect.center = center
            self.position_rect()
Пример #5
0
    def _initialize_items(self):
        """ Internal use only.  Will reset the items in the menu

        Reset the menu items and get new updated ones.

        :rtype: collections.Iterable[MenuItem]
        """
        self.selected_index = 0
        self.menu_items.empty()
        for item in self.initialize_items():
            self.menu_items.add(item)
        if self.menu_items:
            self.show_cursor()

        # call item selection change to trigger callback for first time
        self.on_menu_selection_change()

        if self.shrink_to_items:
            center = self.rect.center
            rect1 = self.menu_items.calc_bounding_rect()
            rect2 = self.menu_sprites.calc_bounding_rect()
            rect1 = rect1.union(rect2)

            # TODO: do not hardcode these values
            # border is 12, padding is the rest
            rect1.width += tools.scale(18)
            rect1.height += tools.scale(19)
            rect1.topleft = 0, 0

            # self.rect = rect1.union(rect2)
            # self.rect.width += tools.scale(20)
            # self.rect.topleft = 0, 0
            self.rect = rect1
            self.rect.center = center
            self.position_rect()
Пример #6
0
    def animate_capture_monster(self, is_captured, num_shakes, monster):
        """ Animation for capturing monsters.

        :param is_captured: boolean representing success of capture
        :param num_shakes: number of shakes before animation ends
        :param monster: the monster
        :return:
        """
        monster_sprite = self._monster_sprite_map.get(monster, None)
        capdev = self.load_sprite('gfx/items/capture_device.png')
        animate = partial(self.animate, capdev.rect, transition='in_quad', duration=1.0)
        scale_sprite(capdev, .4)
        capdev.rect.center = scale(0), scale(0)
        animate(x=monster_sprite.rect.centerx)
        animate(y=monster_sprite.rect.centery)
        self.task(partial(toggle_visible, monster_sprite), 1.0) # make the monster go away temporarily

        def kill():
            self._monster_sprite_map[monster].kill()
            self.hud[monster].kill()
            del self._monster_sprite_map[monster]
            del self.hud[monster]

        # TODO: cache this sprite from the first time it's used.
        # also, should loading animated sprites be more convenient?
        images = list()
        for fn in ["capture%02d.png" % i for i in range(1, 10)]:
            fn = 'animations/technique/' + fn
            image = tools.load_and_scale(fn)
            images.append((image, .07))

        tech = PygAnimation(images, False)
        sprite = Sprite()
        sprite.image = tech
        sprite.rect = tech.get_rect()
        self.task(tech.play, 1.0)
        self.task(partial(self.sprites.add, sprite), 1.0)
        sprite.rect.midbottom = monster_sprite.rect.midbottom

        def shake_ball(initial_delay):
            animate = partial(self.animate, duration=0.1, transition='linear', delay=initial_delay)
            animate(capdev.rect, y=scale(3), relative=True)

            animate = partial(self.animate, duration=0.2, transition='linear', delay=initial_delay + 0.1)
            animate(capdev.rect, y=-scale(6), relative=True)

            animate = partial(self.animate, duration=0.1, transition='linear', delay=initial_delay + 0.3)
            animate(capdev.rect, y=scale(3), relative=True)

        for i in range(0, num_shakes):
            shake_ball(1.8 + i * 1.0) # leave a 0.6s wait between each shake

        if is_captured:
            self.task(kill, 2 + num_shakes)
        else:
            self.task(partial(toggle_visible, monster_sprite), 1.8 + num_shakes * 1.0) # make the monster appear again!
            self.task(tech.play, 1.8 + num_shakes * 1.0)
            self.task(capdev.kill, 1.8 + num_shakes * 1.0)
Пример #7
0
        def shake_ball(initial_delay):
            animate = partial(self.animate, duration=0.1, transition='linear', delay=initial_delay)
            animate(capdev.rect, y=scale(3), relative=True)

            animate = partial(self.animate, duration=0.2, transition='linear', delay=initial_delay + 0.1)
            animate(capdev.rect, y=-scale(6), relative=True)

            animate = partial(self.animate, duration=0.1, transition='linear', delay=initial_delay + 0.3)
            animate(capdev.rect, y=scale(3), relative=True)
Пример #8
0
    def animate_monster_release_bottom(self, feet, monster):
        """

        :type feet: sequence
        :type monster: core.components.monster.Monster
        :return:
        """
        capdev = self.load_sprite('gfx/items/capture_device.png')
        scale_sprite(capdev, .4)
        capdev.rect.center = feet[0], feet[1] - scale(60)

        # animate the capdev falling
        fall_time = .7
        animate = partial(self.animate, duration=fall_time, transition='out_quad')
        animate(capdev.rect, bottom=feet[1], transition='in_back')
        animate(capdev, rotation=720, initial=0)

        # animate the capdev fading away
        delay = fall_time + .6
        fade_duration = .9
        h = capdev.rect.height
        animate = partial(self.animate, duration=fade_duration, delay=delay)
        animate(capdev, width=1, height=h * 1.5)
        animate(capdev.rect, y=-scale(14), relative=True)

        # convert the capdev sprite so we can fade it easily
        def func():
            capdev.image = tools.convert_alpha_to_colorkey(capdev.image)
            self.animate(capdev.image, set_alpha=0, initial=255, duration=fade_duration)

        self.task(func, delay)
        self.task(capdev.kill, fall_time + delay + fade_duration)

        # load monster and set in final position
        monster_sprite = self.load_sprite(monster.back_battle_sprite, midbottom=feet)
        self._monster_sprite_map[monster] = monster_sprite

        # position monster_sprite off screen and set animation to move it back to final spot
        monster_sprite.rect.top = self.game.screen.get_height()
        self.animate(monster_sprite.rect, bottom=feet[1], transition='out_back',
                     duration=.9, delay=fall_time + .5)

        # capdev opening animation
        images = list()
        for fn in ["capture%02d.png" % i for i in range(1, 10)]:
            fn = 'animations/technique/' + fn
            image = tools.load_and_scale(fn)
            images.append((image, .07))

        delay = 1.3
        tech = PygAnimation(images, False)
        sprite = Sprite()
        sprite.image = tech
        sprite.rect = tech.get_rect()
        sprite.rect.midbottom = feet
        self.task(tech.play, delay)
        self.task(partial(self.sprites.add, sprite), delay)
Пример #9
0
    def draw_hp_bars(self):
        """ Go through the HP bars and redraw them

        :returns: None
        """
        for monster, hud in self.hud.items():
            rect = pygame.Rect(0, 0, tools.scale(70), tools.scale(8))
            rect.right = hud.image.get_width() - tools.scale(8)
            rect.top += tools.scale(12)
            self._hp_bars[monster].draw(hud.image, rect)
Пример #10
0
    def draw_hp_bars(self):
        """ Go through the HP bars and redraw them

        :returns: None
        """
        for monster, hud in self.hud.items():
            rect = pygame.Rect(0, 0, tools.scale(70), tools.scale(8))
            rect.right = hud.image.get_width() - tools.scale(8)
            rect.top += tools.scale(12)
            self._hp_bars[monster].draw(hud.image, rect)
Пример #11
0
    def animate_sprite_take_damage(self, sprite):
        """

        :type sprite: core.components.sprite.Sprite
        :return:
        """
        original_x, original_y = sprite.rect.topleft
        animate = partial(self.animate, sprite.rect, duration=1, transition='in_out_elastic')
        ani = animate(x=original_x, initial=original_x + scale(400))
        ani._elapsed = .735  # just want the end of the animation, not the entire thing
        ani = animate(y=original_y, initial=original_y - scale(400))
        ani._elapsed = .735  # just want the end of the animation, not the entire thing
Пример #12
0
    def animate_parties_in(self):
        # TODO: break out functions here for each
        left_trainer, right_trainer = self.players
        right_monster = right_trainer.monsters[0]

        surface = pygame.display.get_surface()
        x, y, w, h = surface.get_rect()

        # TODO: not hardcode this
        player, opponent = self.players
        player_home = self._layout[player]['home'][0]
        opp_home = self._layout[opponent]['home'][0]

        y_mod = scale(50)
        duration = 3

        back_island = self.load_sprite('gfx/ui/combat/back_island.png',
                                       bottom=opp_home.bottom + y_mod, right=0)

        monster1 = self.load_sprite(right_monster.front_battle_sprite,
                                    bottom=back_island.rect.bottom - scale(12),
                                    centerx=back_island.rect.centerx)
        self.build_hud(self._layout[opponent]['hud'][0], right_monster)
        self.monsters_in_play[self.players[1]].append(right_monster)
        self._monster_sprite_map[right_monster] = monster1
        self.alert('A wild %s appeared!' % right_monster.name.upper())

        front_island = self.load_sprite('gfx/ui/combat/front_island.png',
                                        bottom=player_home.bottom - y_mod, left=w)

        trainer1 = self.load_sprite('gfx/sprites/player/player_front.png',
                                    bottom=front_island.rect.centery + scale(6),
                                    centerx=front_island.rect.centerx)
        self._monster_sprite_map[left_trainer] = trainer1

        def flip():
            monster1.image = pygame.transform.flip(monster1.image, 1, 0)
            trainer1.image = pygame.transform.flip(trainer1.image, 1, 0)

        flip()                       # flip images to opposite
        self.task(flip, 1.5)         # flip the images to proper direction

        animate = partial(self.animate, transition='out_quad', duration=duration)

        # top trainer
        animate(monster1.rect, back_island.rect, centerx=opp_home.centerx)
        animate(monster1.rect, back_island.rect, y=-y_mod,
                transition='out_back', relative=True)

        # bottom trainer
        animate(trainer1.rect, front_island.rect, centerx=player_home.centerx)
        animate(trainer1.rect, front_island.rect, y=y_mod,
                transition='out_back', relative=True)
Пример #13
0
    def calc_menu_items_rect(self):
        """ Calculate the area inside the internal rect where items are listed

        :rtype: pygame.Rect
        """
        # WARNING: hardcoded values related to menu arrow size
        #          if menu arrow image changes, this should be adjusted
        cursor_margin = -tools.scale(11), -tools.scale(5)
        inner = self.calc_internal_rect()
        menu_rect = inner.inflate(*cursor_margin)
        menu_rect.bottomright = inner.bottomright
        return menu_rect
Пример #14
0
    def animate_monster_leave(self, monster):
        """

        :type monster: core.components.monster.Monster
        :return:
        """
        sprite = self._monster_sprite_map[monster]
        if self.get_side(sprite.rect) == "left":
            x_diff = -scale(150)
        else:
            x_diff = scale(150)

        self.animate(sprite.rect, x=x_diff, relative=True, duration=2)
Пример #15
0
    def animate_monster_leave(self, monster):
        """

        :type monster: core.components.monster.Monster
        :return:
        """
        sprite = self._monster_sprite_map[monster]
        if self.get_side(sprite.rect) == "left":
            x_diff = -scale(150)
        else:
            x_diff = scale(150)

        self.animate(sprite.rect, x=x_diff, relative=True, duration=2)
Пример #16
0
    def calc_inner_rect(rect):
        """ Calculate the inner rect to draw fg_color that fills bar
            The values here are calculated based on game scale and
            the content of the border image file.

        :param rect:
        :returns:
        """
        inner = rect.copy()
        inner.top += tools.scale(2)
        inner.height -= tools.scale(4)
        inner.left += tools.scale(9)
        inner.width -= tools.scale(11)
        return inner
Пример #17
0
    def animate_sprite_take_damage(self, sprite):
        """

        :type sprite: core.components.sprite.Sprite
        :return:
        """
        original_x, original_y = sprite.rect.topleft
        animate = partial(self.animate,
                          sprite.rect,
                          duration=1,
                          transition='in_out_elastic')
        ani = animate(x=original_x, initial=original_x + scale(400))
        ani._elapsed = .735  # just want the end of the animation, not the entire thing
        ani = animate(y=original_y, initial=original_y - scale(400))
        ani._elapsed = .735  # just want the end of the animation, not the entire thing
Пример #18
0
    def get_side(self, rect):
        """ [WIP] get 'side' of screen rect is in

        :type rect: pygame.Rect
        :return: basestring
        """
        return "left" if rect.centerx < scale(100) else "right"
Пример #19
0
    def animate_sprite_tackle(self, sprite):
        """

        :type sprite: core.components.sprite.Sprite
        :return:
        """
        duration = .3
        original_x = sprite.rect.x

        if self.get_side(sprite.rect) == "left":
            delta = scale(14)
        else:
            delta = -scale(14)

        self.animate(sprite.rect, x=original_x + delta, duration=duration, transition='out_circ')
        self.animate(sprite.rect, x=original_x, duration=duration, transition='in_out_circ', delay=.35)
Пример #20
0
 def animate_monster_up(self):
     ani = self.animate(self.monster_portrait.rect,
                        y=tools.scale(5),
                        duration=1,
                        transition='in_out_quad',
                        relative=True)
     ani.callback = self.animate_monster_down
Пример #21
0
    def get_side(self, rect):
        """ [WIP] get 'side' of screen rect is in

        :type rect: pygame.Rect
        :return: basestring
        """
        return "left" if rect.centerx < scale(100) else "right"
Пример #22
0
    def draw_monster_info(self, surface, monster, rect):
        # position and draw hp bar
        hp_rect = rect.copy()
        left = rect.width * .6
        right = rect.right - tools.scale(4)
        hp_rect.width = right - left
        hp_rect.left = left
        hp_rect.height = tools.scale(8)
        hp_rect.centery = rect.centery

        # draw the hp bar
        self.hp_bar.value = monster.current_hp / monster.hp
        self.hp_bar.draw(surface, hp_rect)

        # draw the name
        text_rect = rect.inflate(-tools.scale(6), -tools.scale(6))
        draw_text(surface, monster.name, text_rect, font=self.font)

        # draw the level info
        text_rect.top = rect.bottom - tools.scale(7)
        draw_text(surface, "  Lv " + str(monster.level), text_rect, font=self.font)

        # draw any status icons
        # TODO: caching or something, idk
        # TODO: not hardcode icon sizes
        for index, status in enumerate(monster.status):
            if status.icon:
                image = tools.load_and_scale(status.icon)
                pos = (rect.width * .4) + (index * tools.scale(32)), rect.y + tools.scale(5)
                surface.blit(image, pos)
Пример #23
0
    def draw_monster_info(self, surface, monster, rect):
        # position and draw hp bar
        hp_rect = rect.copy()
        left = rect.width * .6
        right = rect.right - tools.scale(4)
        hp_rect.width = right - left
        hp_rect.left = left
        hp_rect.height = tools.scale(8)
        hp_rect.centery = rect.centery

        # draw the hp bar
        self.hp_bar.value = monster.current_hp / monster.hp
        self.hp_bar.draw(surface, hp_rect)

        # draw the name
        text_rect = rect.inflate(-tools.scale(6), -tools.scale(6))
        draw_text(surface, monster.name, text_rect, font=self.font)

        # draw the level info
        text_rect.top = rect.bottom - tools.scale(7)
        draw_text(surface,
                  "  Lv " + str(monster.level),
                  text_rect,
                  font=self.font)

        # draw any status icons
        # TODO: caching or something, idk
        # TODO: not hardcode icon sizes
        for index, status in enumerate(monster.status):
            if status.icon:
                image = tools.load_and_scale(status.icon)
                pos = (rect.width *
                       .4) + (index * tools.scale(32)), rect.y + tools.scale(5)
                surface.blit(image, pos)
Пример #24
0
    def draw_monster_info(self, surface, monster, rect):
        # position and draw hp bar
        hp_rect = rect.copy()
        hp_rect.width = rect.width // 2
        hp_rect.left = rect.centerx - tools.scale(2)
        hp_rect.height = tools.scale(8)
        hp_rect.centery = rect.centery

        self.hp_bar.value = monster.current_hp / monster.hp
        self.hp_bar.draw(surface, hp_rect)

        # draw the name
        text_rect = rect.inflate(-tools.scale(6), -tools.scale(6))
        draw_text(surface, monster.name, text_rect, font=self.font)

        # draw the level info
        text_rect.top = rect.bottom - tools.scale(6)
        draw_text(surface, "  Lv " + str(monster.level), text_rect, font=self.font)
Пример #25
0
        def shake_ball(initial_delay):
            animate = partial(self.animate,
                              duration=0.1,
                              transition='linear',
                              delay=initial_delay)
            animate(capdev.rect, y=scale(3), relative=True)

            animate = partial(self.animate,
                              duration=0.2,
                              transition='linear',
                              delay=initial_delay + 0.1)
            animate(capdev.rect, y=-scale(6), relative=True)

            animate = partial(self.animate,
                              duration=0.1,
                              transition='linear',
                              delay=initial_delay + 0.3)
            animate(capdev.rect, y=scale(3), relative=True)
Пример #26
0
    def add_monster_into_play(self, player, monster):
        feet = list(self._layout[player]["home"][0].center)
        feet[1] += tools.scale(11)
        self.animate_monster_release_bottom(feet, monster)
        self.build_hud(self._layout[player]["hud"][0], monster)
        self.monsters_in_play[player].append(monster)

        # TODO: not hardcode
        if player is self.players[0]:
            self.alert("Go %s!" % monster.name.upper())
        else:
            self.alert("A wild %s appeared!" % monster.name.upper())
Пример #27
0
    def add_monster_into_play(self, player, monster):
        feet = list(self._layout[player]['home'][0].center)
        feet[1] += tools.scale(11)
        self.animate_monster_release_bottom(feet, monster)
        self.build_hud(self._layout[player]['hud'][0], monster)
        self.monsters_in_play[player].append(monster)

        # TODO: not hardcode
        if player is self.players[0]:
            self.alert('Go %s!' % monster.name.upper())
        else:
            self.alert('A wild %s appeared!' % monster.name.upper())
Пример #28
0
    def draw_monster_info(self, surface, monster, rect):
        # position and draw hp bar
        hp_rect = rect.copy()
        hp_rect.width = rect.width // 2
        hp_rect.left = rect.centerx - tools.scale(2)
        hp_rect.height = tools.scale(8)
        hp_rect.centery = rect.centery

        self.hp_bar.value = monster.current_hp / monster.hp
        self.hp_bar.draw(surface, hp_rect)

        # draw the name
        text_rect = rect.inflate(-tools.scale(6), -tools.scale(6))
        draw_text(surface, monster.name, text_rect, font=self.font)

        # draw the level info
        text_rect.top = rect.bottom - tools.scale(6)
        draw_text(surface,
                  "  Lv " + str(monster.level),
                  text_rect,
                  font=self.font)
Пример #29
0
    def animate_party_hud_in(self, player, home, slots):
        """ Party HUD is the arrow thing with balls.  Yes, that one.

        :param player: the player
        :type home: pygame.Rect
        :param slots: Number of slots
        :return:
        """
        if self.get_side(home) == "left":
            tray = self.load_sprite('gfx/ui/combat/opponent_party_tray.png',
                                    bottom=home.bottom, right=0, layer=hud_layer)
            self.animate(tray.rect, right=home.right, duration=2, delay=1.5)
            centerx = home.right - scale(13)
            offset = scale(8)
        else:
            tray = self.load_sprite('gfx/ui/combat/player_party_tray.png',
                                    bottom=home.bottom, left=home.right, layer=hud_layer)
            self.animate(tray.rect, left=home.left, duration=2, delay=1.5)
            centerx = home.left + scale(13)
            offset = -scale(8)

        for index in range(slots):
            sprite = self.load_sprite('gfx/ui/combat/empty_slot_icon.png',
                                      top=tray.rect.top + scale(1),
                                      centerx=centerx - index * offset,
                                      layer=hud_layer)

            # convert alpha image to image with a colorkey so we can set_alpha
            sprite.image = tools.convert_alpha_to_colorkey(sprite.image)
            sprite.image.set_alpha(0)
            animate = partial(self.animate, duration=1.5, delay=2.2 + index * .2)
            animate(sprite.image, set_alpha=255, initial=0)
            animate(sprite.rect, bottom=tray.rect.top + scale(3))
Пример #30
0
    def initialize_items(self):
        # get a ref to the combat state
        combat_state = self.game.get_state_name("CombatState")

        # TODO: trainer targeting
        # TODO: cleanup how monster sprites and whatnot are managed
        # TODO: This is going to work fine for simple matches, but controls will be wonky for parties
        # TODO: (cont.) Need better handling of cursor keys for 2d layouts of menu items
        # get all the monster positions

        # this is used to determine who owns what monsters and what not
        # TODO: make less duplication of game data in memory, let combat state have more registers, etc
        self.targeting_map = defaultdict(list)

        for player, monsters in combat_state.monsters_in_play.items():
            for monster in monsters:

                # TODO: more targeting classes
                if player == self.player:
                    targeting_class = "own monster"
                else:
                    targeting_class = "enemy monster"

                self.targeting_map[targeting_class].append(monster)

                # TODO: handle odd cases where a situation creates no valid targets
                # if this target type is not handled by this action, then skip it
                if targeting_class not in self.action.target:
                    continue

                # inspect the monster sprite and make a border image for it
                sprite = combat_state._monster_sprite_map[monster]
                item = MenuItem(None, None, None, monster)
                item.rect = sprite.rect.copy()
                center = item.rect.center
                item.rect.inflate_ip(tools.scale(16), tools.scale(16))
                item.rect.center = center

                yield item
Пример #31
0
    def initialize_items(self):
        # get a ref to the combat state
        combat_state = self.game.get_state_name("CombatState")

        # TODO: trainer targeting
        # TODO: cleanup how monster sprites and whatnot are managed
        # TODO: This is going to work fine for simple matches, but controls will be wonky for parties
        # TODO: (cont.) Need better handling of cursor keys for 2d layouts of menu items
        # get all the monster positions

        # this is used to determine who owns what monsters and what not
        # TODO: make less duplication of game data in memory, let combat state have more registers, etc
        self.targeting_map = defaultdict(list)

        for player, monsters in combat_state.monsters_in_play.items():
            for monster in monsters:

                # TODO: more targeting classes
                if player == self.player:
                    targeting_class = "own monster"
                else:
                    targeting_class = "enemy monster"

                self.targeting_map[targeting_class].append(monster)

                # TODO: handle odd cases where a situation creates no valid targets
                # if this target type is not handled by this action, then skip it
                if targeting_class not in self.action.target:
                    continue

                # inspect the monster sprite and make a border image for it
                sprite = combat_state._monster_sprite_map[monster]
                item = MenuItem(None, None, None, monster)
                item.rect = sprite.rect.copy()
                center = item.rect.center
                item.rect.inflate_ip(tools.scale(16), tools.scale(16))
                item.rect.center = center

                yield item
Пример #32
0
    def animate_sprite_tackle(self, sprite):
        """

        :type sprite: core.components.sprite.Sprite
        :return:
        """
        duration = .3
        original_x = sprite.rect.x

        if self.get_side(sprite.rect) == "left":
            delta = scale(14)
        else:
            delta = -scale(14)

        self.animate(sprite.rect,
                     x=original_x + delta,
                     duration=duration,
                     transition='out_circ')
        self.animate(sprite.rect,
                     x=original_x,
                     duration=duration,
                     transition='in_out_circ',
                     delay=.35)
Пример #33
0
    def startup(self, **kwargs):
        self.state = "normal"
        self.item_center = self.rect.width * .164, self.rect.height * .13
        self.item_sprite = Sprite()
        self.item_sprite.image = None
        self.sprites.add(self.item_sprite)
        super(ItemMenuState, self).startup(**kwargs)
        self.menu_items.line_spacing = tools.scale(5)

        rect = self.game.screen.get_rect()
        center = rect.center
        rect.width *= .95
        rect.height *= .25
        rect.center = center
        rect.top = tools.scale(110)
        self.text_area = TextArea(self.font, self.font_color, (96, 96, 128))
        self.text_area.rect = rect
        self.sprites.add(self.text_area, layer=100)

        # Load the backpack icon
        self.backpack_center = self.rect.width * .16, self.rect.height * .45
        self.load_sprite("gfx/ui/item/backpack.png",
                         center=self.backpack_center,
                         layer=100)
Пример #34
0
    def fit_border(self):
        """ Resize the window border to fit the contents of the menu

        :return:
        """
        # get bounding box of menu items and the cursor
        center = self.rect.center
        rect1 = self.menu_items.calc_bounding_rect()
        rect2 = self.menu_sprites.calc_bounding_rect()
        rect1 = rect1.union(rect2)

        # expand the bounding box by the border and some padding
        # TODO: do not hardcode these values
        # border is 12, padding is the rest
        rect1.width += tools.scale(18)
        rect1.height += tools.scale(19)
        rect1.topleft = 0, 0

        # set our rect and adjust the centers to match
        self.rect = rect1
        self.rect.center = center

        # move the bounding box taking account the anchors
        self.position_rect()
Пример #35
0
    def animate_party_hud_in(self, player, home):
        """ Party HUD is the arrow thing with balls.  Yes, that one.

        :param player: the player
        :type home: pygame.Rect
        :param slots: Number of slots
        :return:
        """
        if self.get_side(home) == "left":
            tray = self.load_sprite('gfx/ui/combat/opponent_party_tray.png',
                                    bottom=home.bottom,
                                    right=0,
                                    layer=hud_layer)
            self.animate(tray.rect, right=home.right, duration=2, delay=1.5)
            centerx = home.right - scale(13)
            offset = scale(8)
        else:
            tray = self.load_sprite('gfx/ui/combat/player_party_tray.png',
                                    bottom=home.bottom,
                                    left=home.right,
                                    layer=hud_layer)
            self.animate(tray.rect, left=home.left, duration=2, delay=1.5)
            centerx = home.left + scale(13)
            offset = -scale(8)

        for index in range(player.party_limit):
            sprite = None
            if len(player.monsters) > index:
                sprite = self.load_sprite(
                    'gfx/ui/icons/party/party_icon01.png',
                    top=tray.rect.top + scale(1),
                    centerx=centerx - index * offset,
                    layer=hud_layer)
            else:
                sprite = self.load_sprite('gfx/ui/combat/empty_slot_icon.png',
                                          top=tray.rect.top + scale(1),
                                          centerx=centerx - index * offset,
                                          layer=hud_layer)

            # convert alpha image to image with a colorkey so we can set_alpha
            sprite.image = tools.convert_alpha_to_colorkey(sprite.image)
            sprite.image.set_alpha(0)
            animate = partial(self.animate,
                              duration=1.5,
                              delay=2.2 + index * .2)
            animate(sprite.image, set_alpha=255, initial=0)
            animate(sprite.rect, bottom=tray.rect.top + scale(3))
Пример #36
0
    def trigger_cursor_update(self, animate=True):
        """ Force the menu cursor to move into the correct position

        :param animate: If True, then arrow will move smoothly into position
        :returns: None or Animation
        """
        selected = self.get_selected_item()
        if not selected:
            return

        x, y = selected.rect.midleft
        x -= tools.scale(2)

        if animate:
            self.remove_animations_of(self.arrow.rect)
            return self.animate(self.arrow.rect, right=x, centery=y, duration=self.cursor_move_duration)
        else:
            self.arrow.rect.midright = x, y
            return None
Пример #37
0
    def add_monster_into_play(self, player, monster):
        """

        :param player:
        :param monster:
        :return:
        """
        # TODO: refactor some into the combat animations
        feet = list(self._layout[player]['home'][0].center)
        feet[1] += tools.scale(11)
        self.animate_monster_release_bottom(feet, monster)
        self.build_hud(self._layout[player]['hud'][0], monster)
        self.monsters_in_play[player].append(monster)

        # TODO: not hardcode
        if player is self.players[0]:
            self.alert(trans('combat_call_tuxemon', {"name": monster.name.upper()}))
        else:
            self.alert(trans('combat_wild_appeared', {"name": monster.name.upper()}))
Пример #38
0
    def animate_parties_in(self):
        # TODO: break out functions here for each
        left_trainer, right_trainer = self.players
        right_monster = right_trainer.monsters[0]

        surface = pygame.display.get_surface()
        x, y, w, h = surface.get_rect()

        # TODO: not hardcode this
        player, opponent = self.players
        player_home = self._layout[player]['home'][0]
        opp_home = self._layout[opponent]['home'][0]

        y_mod = scale(50)
        duration = 3

        back_island = self.load_sprite('gfx/ui/combat/back_island.png',
                                       bottom=opp_home.bottom + y_mod,
                                       right=0)

        monster1 = self.load_sprite(right_monster.front_battle_sprite,
                                    bottom=back_island.rect.bottom - scale(12),
                                    centerx=back_island.rect.centerx)
        self.build_hud(self._layout[opponent]['hud'][0], right_monster)
        self.monsters_in_play[self.players[1]].append(right_monster)
        self._monster_sprite_map[right_monster] = monster1
        self.alert('A wild %s appeared!' % right_monster.name.upper())

        front_island = self.load_sprite('gfx/ui/combat/front_island.png',
                                        bottom=player_home.bottom - y_mod,
                                        left=w)

        trainer1 = self.load_sprite('gfx/sprites/player/player_front.png',
                                    bottom=front_island.rect.centery +
                                    scale(6),
                                    centerx=front_island.rect.centerx)
        self._monster_sprite_map[left_trainer] = trainer1

        def flip():
            monster1.image = pygame.transform.flip(monster1.image, 1, 0)
            trainer1.image = pygame.transform.flip(trainer1.image, 1, 0)

        flip()  # flip images to opposite
        self.task(flip, 1.5)  # flip the images to proper direction

        animate = partial(self.animate,
                          transition='out_quad',
                          duration=duration)

        # top trainer
        animate(monster1.rect, back_island.rect, centerx=opp_home.centerx)
        animate(monster1.rect,
                back_island.rect,
                y=-y_mod,
                transition='out_back',
                relative=True)

        # bottom trainer
        animate(trainer1.rect, front_island.rect, centerx=player_home.centerx)
        animate(trainer1.rect,
                front_island.rect,
                y=y_mod,
                transition='out_back',
                relative=True)
Пример #39
0
 def animate_monster_up(self):
     ani = self.animate(self.monster_portrait.rect, y=tools.scale(5),
                        duration=1, transition='in_out_quad', relative=True)
     ani.callback = self.animate_monster_down
Пример #40
0
    def animate_capture_monster(self, is_captured, num_shakes, monster):
        """ Animation for capturing monsters.

        :param is_captured: boolean representing success of capture
        :param num_shakes: number of shakes before animation ends
        :param monster: the monster
        :return:
        """
        monster_sprite = self._monster_sprite_map.get(monster, None)
        capdev = self.load_sprite('gfx/items/capture_device.png')
        animate = partial(self.animate,
                          capdev.rect,
                          transition='in_quad',
                          duration=1.0)
        scale_sprite(capdev, .4)
        capdev.rect.center = scale(0), scale(0)
        animate(x=monster_sprite.rect.centerx)
        animate(y=monster_sprite.rect.centery)
        self.task(partial(toggle_visible, monster_sprite),
                  1.0)  # make the monster go away temporarily

        def kill():
            self._monster_sprite_map[monster].kill()
            self.hud[monster].kill()
            del self._monster_sprite_map[monster]
            del self.hud[monster]

        # TODO: cache this sprite from the first time it's used.
        # also, should loading animated sprites be more convenient?
        images = list()
        for fn in ["capture%02d.png" % i for i in range(1, 10)]:
            fn = 'animations/technique/' + fn
            image = tools.load_and_scale(fn)
            images.append((image, .07))

        tech = PygAnimation(images, False)
        sprite = Sprite()
        sprite.image = tech
        sprite.rect = tech.get_rect()
        self.task(tech.play, 1.0)
        self.task(partial(self.sprites.add, sprite), 1.0)
        sprite.rect.midbottom = monster_sprite.rect.midbottom

        def shake_ball(initial_delay):
            animate = partial(self.animate,
                              duration=0.1,
                              transition='linear',
                              delay=initial_delay)
            animate(capdev.rect, y=scale(3), relative=True)

            animate = partial(self.animate,
                              duration=0.2,
                              transition='linear',
                              delay=initial_delay + 0.1)
            animate(capdev.rect, y=-scale(6), relative=True)

            animate = partial(self.animate,
                              duration=0.1,
                              transition='linear',
                              delay=initial_delay + 0.3)
            animate(capdev.rect, y=scale(3), relative=True)

        for i in range(0, num_shakes):
            shake_ball(1.8 + i * 1.0)  # leave a 0.6s wait between each shake

        if is_captured:
            self.task(kill, 2 + num_shakes)
        else:
            self.task(partial(toggle_visible, monster_sprite),
                      1.8 + num_shakes * 1.0)  # make the monster appear again!
            self.task(tech.play, 1.8 + num_shakes * 1.0)
            self.task(capdev.kill, 1.8 + num_shakes * 1.0)
Пример #41
0
    def animate_monster_release_bottom(self, feet, monster):
        """

        :type feet: sequence
        :type monster: core.components.monster.Monster
        :return:
        """
        capdev = self.load_sprite('gfx/items/capture_device.png')
        scale_sprite(capdev, .4)
        capdev.rect.center = feet[0], feet[1] - scale(60)

        # animate the capdev falling
        fall_time = .7
        animate = partial(self.animate,
                          duration=fall_time,
                          transition='out_quad')
        animate(capdev.rect, bottom=feet[1], transition='in_back')
        animate(capdev, rotation=720, initial=0)

        # animate the capdev fading away
        delay = fall_time + .6
        fade_duration = .9
        h = capdev.rect.height
        animate = partial(self.animate, duration=fade_duration, delay=delay)
        animate(capdev, width=1, height=h * 1.5)
        animate(capdev.rect, y=-scale(14), relative=True)

        # convert the capdev sprite so we can fade it easily
        def func():
            capdev.image = tools.convert_alpha_to_colorkey(capdev.image)
            self.animate(capdev.image,
                         set_alpha=0,
                         initial=255,
                         duration=fade_duration)

        self.task(func, delay)
        self.task(capdev.kill, fall_time + delay + fade_duration)

        # load monster and set in final position
        monster_sprite = self.load_sprite(monster.back_battle_sprite,
                                          midbottom=feet)
        self._monster_sprite_map[monster] = monster_sprite

        # position monster_sprite off screen and set animation to move it back to final spot
        monster_sprite.rect.top = self.game.screen.get_height()
        self.animate(monster_sprite.rect,
                     bottom=feet[1],
                     transition='out_back',
                     duration=.9,
                     delay=fall_time + .5)

        # capdev opening animation
        images = list()
        for fn in ["capture%02d.png" % i for i in range(1, 10)]:
            fn = 'animations/technique/' + fn
            image = tools.load_and_scale(fn)
            images.append((image, .07))

        delay = 1.3
        tech = PygAnimation(images, False)
        sprite = Sprite()
        sprite.image = tech
        sprite.rect = tech.get_rect()
        sprite.rect.midbottom = feet
        self.task(tech.play, delay)
        self.task(partial(self.sprites.add, sprite), delay)