def make_counter_btn(x: int, y: int, font: pygame.font.Font, align: str="center", vertical_align: str="middle", min_: int=1, max_: int=5, color: Color=(0, 0, 0)): group = pygame.sprite.Group() counter_sprite = CounterSprite(x, y, font, align, vertical_align, min_, max_, color) group.add(counter_sprite) rect = counter_sprite.base_rect w = h = rect.h w = w // 3 points = [ (0, h//2), (w-1, h*0.8-1), (w-1, h*0.2) ] x, y = rect.topleft left_image = Surface((w, h)).convert_alpha() left_image.fill((255, 255, 255)) left_image.set_colorkey(left_image.get_at((0, 0))) pygame.gfxdraw.filled_polygon(left_image, points, color) # left_image = font.render("<", True, color) btn = RichSprite(x-5, y, align="right", vertical_align="top", image=left_image, press_fnc=counter_sprite._count_down) group.add(btn) x, y = rect.topright right_image = pygame.transform.flip(left_image, True, False) right_image.set_colorkey(right_image.get_at((0, 0))) btn = RichSprite(x+5, y, align="left", vertical_align="top", image=right_image, press_fnc=counter_sprite._count_up) group.add(btn) return group, counter_sprite.get_count
def _set_frame(self, clear = True, image = None): if image == None: btn_image = pygame.Surface((self.width, self.height)) btn_image.fill((200, 200, 200)) if clear: btn_image.set_colorkey(btn_image.get_at((0, 0))) self.frame_sprite = RichSprite(0, 0, image = btn_image, align = "left", vertical_align="top") else: btn_image = pygame.transform.smoothscale(image, (self.width, self.height)) self.frame_sprite = RichSprite(0, 0, image = btn_image, align = "left", vertical_align="top") self.frame_sprite.change_press_fnc(self.func, self.func_args)
def _set_next_btn(self): next_btn_image = self.font.render("Next", True, (0, 0, 0)) self.next_btn = RichSprite(*self.display_rect.bottomright, image=next_btn_image, align="right", vertical_align="bottom") self.next_btn.rect.move_ip(-5, -5) outline = make_outline_sprites(self.next_btn.rect, self.outline_image) self.next_btn.change_enter_fnc(self.middle_sprites.add, outline) self.next_btn.change_exit_fnc(self.middle_sprites.remove, outline) self.next_btn.change_press_fnc(self._goto_stage_select) self.front_sprites.add(self.next_btn)
def _set_return_btn(self): #SimpleButton(width=rect.width, height=rect.height, text="Return", outline=self.game_config.components["outline"], func = self._go_to_title) font = pygame.font.Font(None, 60) textsurface = font.render("Return", True, (0, 0, 0)) return_btn = RichSprite(*self.display.get_rect().bottomleft, align="left", vertical_align="bottom", image=textsurface) return_btn.rect.move_ip(10, -10) self.hoverable(return_btn, self.game_config.components["outline"], border_width=5) return_btn.change_press_fnc(self._go_to_title) self.middle_sprites.add(return_btn)
def _set_title(self): title_surfaces = self.components["title"] rect = self.display.get_rect() x = rect.w // 2 y = rect.h // 3 # title_sprite = make_animation_sprites(x, y, images=title_surfaces, interval=3, multiple=1.0) title_sprite = RichSprite(x=x, y=y, images=title_surfaces, interval=4) self.middle_sprites.add(title_sprite)
def __init__(self, base_rect: Rect, values: List[Any], labels: Optional[List[str]]=None, font_name: Optional[str]=None, color: Color=(255, 255, 255), bg_color: Color=(0, 0, 0), bg_alpha: float=1.0, defalut_i: int=0): super().__init__() self.values = values self.i = defalut_i self.base_rect = base_rect if defalut_i < 0 or len(values) <= defalut_i: raise(ValueError("default_i が values のリストの範囲を超えています.")) # ラベルのSpriteのリストを作成 self.labels = labels if labels else [str(v) for v in values] font = pygame.font.Font(font_name, base_rect.h) label_surfaces = [font.render(label, True, color) for label in self.labels] self.label_sprites = [] for surface in label_surfaces: rect = surface.get_rect() rect.center = base_rect.center self.label_sprites.append(SimpleSprite(rect, surface)) # 左右のボタンの作成 size = (int(base_rect.h * 0.5), int(base_rect.h * 0.8)) left_btn_surface_inactive = make_left_triangle(size, color=(192, 192, 192)) left_btn_surface_active = make_left_triangle(size, color=(255, 140, 0)) rect = base_rect self.left_btn_active = RichSprite(*rect.midleft, align="left", vertical_align="middle", image=left_btn_surface_active, press_fnc=self._left) self.left_btn_inactive = RichSprite(*rect.midleft, align="left", vertical_align="middle", image=left_btn_surface_inactive, press_fnc=self._left) self.right_btn_active = RichSprite(*rect.midright, align="right", vertical_align="middle", image=pygame.transform.flip(left_btn_surface_active, True, False), press_fnc=self._right) self.right_btn_inactive = RichSprite(*rect.midright, align="right", vertical_align="middle", image=pygame.transform.flip(left_btn_surface_inactive, True, False), press_fnc=self._right) # 背景作成 size = (base_rect.w, base_rect.h) bg_surface = make_surface(size, alpha=False, bg_color=bg_color) bg_sprite = SimpleSprite(base_rect, bg_surface) self.add(bg_sprite) # 表示のためのグループの作成と追加 self.left_btn = GroupSingle() self.right_btn = GroupSingle() self.single_group = GroupSingle() self.add(self.left_btn) self.add(self.right_btn) self.add(self.single_group) # 初期化 self._update_images()
def _set_back_btn(self): back_btn_image = self.font.render("Back", True, (0, 0, 0)) back_btn = RichSprite(*self.display_rect.bottomleft, image=back_btn_image, align="left", vertical_align="bottom") back_btn.rect.move_ip(5, -5) outline = make_outline_sprites(back_btn.rect, self.outline_image) back_btn.change_enter_fnc(self.middle_sprites.add, outline) back_btn.change_exit_fnc(self.middle_sprites.remove, outline) back_btn.change_press_fnc(self._goto_title) self.front_sprites.add(back_btn)
def _set_background(self): rect = self.display.get_rect() bg_surface = pygame.transform.scale(self.components["background"], (rect.w, rect.h)) bg_sprite = RichSprite(0, 0, align="left", vertical_align="top", image=bg_surface) self.background_sprites.add(bg_sprite)
def _set_random_btn(self): """(デバッグ)ランダム勝敗ボタンの設置 """ rect = self.display.get_rect() surface = self.font.render("random result", True, (255, 255, 255), (0, 0, 0)) random_result_btn = RichSprite(rect.w // 2, rect.h // 3, image=surface, press_fnc=self._random_result) self.middle_sprites.add(random_result_btn)
def __init__(self, display_rect, characters, outline, gameplayer1, gameplayer2): super().__init__() self.characters = characters self.outline_image = outline self.gameplayer1 = gameplayer1 self.gameplayer2 = gameplayer2 self.margin_lr = 30 self.margin_top = 30 self.space = 20 self.rect = pygame.rect.Rect(self.margin_lr, self.margin_top, display_rect.width - self.margin_lr * 2, max(100, display_rect.height // 2)) width = (self.rect.width - self.space * (len(self.characters) - 1)) // len(self.characters) height = self.rect.height self.character_rects = [ pygame.rect.Rect(self.rect.left + i * (width + self.space), self.rect.top, width, height) for i in range(len(self.characters)) ] self.character_to_rect = {} for character, rect in zip(self.characters, self.character_rects): face_image = surface_fit_to_rect(rect=rect, surface=character.face_image) sprite = RichSprite(rect.centerx, rect.centery, image=face_image) to_hoverable(sprite, self.outline_image, self.background_sprites) sprite.change_press_fnc(self._press_character, (character, rect)) self.middle_sprites.add(sprite) self.badges = { gameplayer1: BadgeSpriteGroup(25, (200, 5, 5), "1"), gameplayer2: BadgeSpriteGroup(25, (5, 200, 5), "2") } self.front_sprites.add(self.badges.values()) self.gameplayers = [ GamePlayerSetter(gameplayer1, self._set_character), GamePlayerSetter(gameplayer2, self._set_character) ] self.add(self.gameplayers)
def _set_option_btn(self): option_surface = self.font.render("option", True, (0, 0, 0)) rect = self.display.get_rect() x = rect.w // 2 y = rect.h * 3 // 4 rect = adjust_rect(option_surface.get_rect().copy(), x, y) outline_sprites = make_outline_splites(rect, self.components["outline"], border_width=1) option_btn_sprite = RichSprite( x, y, image=option_surface, enter_fnc=self._visible_sprites, enter_fnc_args=(self.front_sprites, outline_sprites), exit_fnc=self._invisible_sprites, exit_fnc_args=(self.front_sprites, outline_sprites), press_fnc=self._go_to_option_screen, ) self.middle_sprites.add(option_btn_sprite)
def _set_start_btn(self): # start_btn_surfaces = self.components["start"] start_btn_surface = self.font.render("start", True, (0, 0, 0)) rect = self.display.get_rect() x = rect.w // 2 y = rect.h * 2 // 3 # start_btn_sprite = RichSprite(x=x, y=y, images=start_btn_surfaces, interval=5, press_fnc=self._go_to_character_select_screen) start_btn_sprite = RichSprite( x=x, y=y, image=start_btn_surface, press_fnc=self._go_to_character_select_screen) self.middle_sprites.add(start_btn_sprite) outline_sprites = make_outline_splites(start_btn_sprite.rect, self.components["outline"], border_width=1) start_btn_sprite.change_enter_fnc( self._visible_sprites, (self.front_sprites, outline_sprites)) start_btn_sprite.change_exit_fnc(self._invisible_sprites, (self.front_sprites, outline_sprites))
class CharacterSelectScreen(BaseScreen): def __init__(self, game_config, gameplayer1, gameplayer2): super().__init__() self.game_config = game_config self.players = list(self.game_config.players.values()) self.characters = list(self.game_config.characters.values()) self.gameplayer1 = gameplayer1 self.gameplayer2 = gameplayer2 self.margin_lr = 30 self.display_rect = self.display.get_rect() self.character_select_rect = None self.player_select_rect = None self.outline_image = self.game_config.components["outline"] self.outline_image = pygame.transform.scale2x(self.outline_image) self.font_size = 40 self.font = pygame.font.SysFont(None, self.font_size) self.character_select_area = CharacterSelectArea( self.display_rect, self.characters, self.outline_image, self.gameplayer1, self.gameplayer2) def _goto_stage_select(self): for i, gameplayer in enumerate([self.gameplayer1, self.gameplayer2]): gameplayer.player = self.player_select_btn[i].get_value() self.next_screen = Screen.STAGE_SELECT self.run = False def _goto_title(self): self.next_screen = Screen.START self.run = False def _set_next_btn(self): next_btn_image = self.font.render("Next", True, (0, 0, 0)) self.next_btn = RichSprite(*self.display_rect.bottomright, image=next_btn_image, align="right", vertical_align="bottom") self.next_btn.rect.move_ip(-5, -5) outline = make_outline_sprites(self.next_btn.rect, self.outline_image) self.next_btn.change_enter_fnc(self.middle_sprites.add, outline) self.next_btn.change_exit_fnc(self.middle_sprites.remove, outline) self.next_btn.change_press_fnc(self._goto_stage_select) self.front_sprites.add(self.next_btn) def _set_back_btn(self): back_btn_image = self.font.render("Back", True, (0, 0, 0)) back_btn = RichSprite(*self.display_rect.bottomleft, image=back_btn_image, align="left", vertical_align="bottom") back_btn.rect.move_ip(5, -5) outline = make_outline_sprites(back_btn.rect, self.outline_image) back_btn.change_enter_fnc(self.middle_sprites.add, outline) back_btn.change_exit_fnc(self.middle_sprites.remove, outline) back_btn.change_press_fnc(self._goto_title) self.front_sprites.add(back_btn) def _set_characters_area(self): self.middle_sprites.add(self.character_select_area) def _set_player_select_area(self): self.player_select_rect = pygame.rect.Rect( self.margin_lr, self.character_select_area.rect.bottomleft[1] + (self.display_rect.height - self.character_select_area.rect.bottomleft[1]) // 2, self.character_select_area.rect.width, 30) self.players_rects = layout_rects(self.player_select_rect, 2, 1, margin_horizontal=10) self.players_name = [player.name for player in self.players] self.colors = [(200, 200, 200), (200, 200, 200)] self.player_select_btn = [ ValuesGroup(base_rect=self.players_rects[i], values=self.players, labels=self.players_name, color=(0, 0, 0), bg_color=self.colors[i], defalut_i=i) for i in range(len(self.players_rects)) ] self.front_sprites.add(self.player_select_btn) def _set_bgm(self): self.bgm: pygame.mixer.Sound = self.game_config.sounds["menu"] self.bgm.set_volume(0.1) self.bgm.play() def _adapt_display(self): pygame.display.set_caption("Character Select") bg_image = self.game_config.components["background"] bg_image = pygame.transform.scale(bg_image, self.display_rect.size) bg_sprite = SimpleSprite(rect=self.display_rect, image=bg_image) self.background_sprites.add(bg_sprite) self._set_characters_area() self._set_player_select_area() self._set_next_btn() self._set_back_btn() def update(self): super().update() if self.front_sprites.has( self.next_btn) and self.player_select_btn[0].get_value( ) == self.player_select_btn[1].get_value(): self.front_sprites.remove(self.next_btn) elif not self.front_sprites.has( self.next_btn) and self.player_select_btn[0].get_value( ) != self.player_select_btn[1].get_value(): self.front_sprites.add(self.next_btn) def main(self): self._adapt_display() super().main()
class SimpleButton(LayeredGroup): def __init__(self, width: int = 300, height: int = 100, text: str = "", outline = None, func: Callable = None, func_args: Any = None): super().__init__() self.text = text self.font_size = height // 2 self.font = pygame.font.Font("./fonts/Mplus2-Medium.ttf", self.font_size) self.func = func self.func_args = func_args self.__text_height_scale = 1.0 self.width = width self.height = height self.frame_sprite = pygame.sprite.Sprite() self.text_sprite = pygame.sprite.Sprite() self.outline = outline self.baserect = pygame.rect.Rect(0, 0, self.width, self.height) self.rect = pygame.rect.Rect(0, 0, self.width, self.height) self.init() def _fit_font(self): while self.font.size(self.text)[0] > self.width: self.font_size -= 1 self.font = pygame.font.Font("./fonts/Mplus2-Medium.ttf", self.font_size) def _set_frame(self, clear = True, image = None): if image == None: btn_image = pygame.Surface((self.width, self.height)) btn_image.fill((200, 200, 200)) if clear: btn_image.set_colorkey(btn_image.get_at((0, 0))) self.frame_sprite = RichSprite(0, 0, image = btn_image, align = "left", vertical_align="top") else: btn_image = pygame.transform.smoothscale(image, (self.width, self.height)) self.frame_sprite = RichSprite(0, 0, image = btn_image, align = "left", vertical_align="top") self.frame_sprite.change_press_fnc(self.func, self.func_args) def _set_text(self): self.text_sprite = TextSprite(0, 0, text=self.text, font=self.font) self.text_sprite.rect.center = self.baserect.center def init(self): self._fit_font() self._set_text() self._set_frame(clear=False) self.outline = pygame.transform.scale2x(self.outline) self.outline = pygame.transform.scale2x(self.outline) self.outlines = to_hoverable(self.frame_sprite, self.outline, self.middle_sprites) self.background_sprites.add(self.frame_sprite) self.middle_sprites.add(self.text_sprite) def update(self): if self.baserect.topleft != self.rect.topleft: dx = self.rect.left - self.baserect.left dy = self.rect.top - self.baserect.top self.baserect.topleft = self.rect.topleft for sprites in [self.middle_sprites, self.background_sprites]: for sprite in sprites: sprite.rect.move_ip(dx, dy) if not self.middle_sprites.has(self.outlines): for sprite in self.outlines: sprite.rect.move_ip(dx, dy) super().update()