def __init__(self, master, car_id: int, **kwargs): self.__height = 150 Image.__init__(self, RESOURCES.IMG["garage_cars"][car_id], height=self.__height) Clickable.__init__(self, master, **kwargs, highlight_thickness=0) self.__id = car_id self.__all_max_speed = list() self.__all_acceleration = list() self.__all_maniablities = list() self.__all_braking = list() for infos in CAR_INFOS.values(): self.__all_max_speed.append(infos["max_speed"]) self.__all_acceleration.append(infos["acceleration"]) self.__all_maniablities.append(infos["maniability"]) self.__all_braking.append(infos["braking"]) self.take_focus(True) self.disable_key_joy() self.disable_mouse() self.master.bind_event(pygame.KEYDOWN, self.on_click_down) self.master.bind_event(pygame.KEYUP, self.on_click_up) self.master.bind_event(pygame.JOYHATMOTION, self.on_click_down) self.master.bind_event(pygame.JOYHATMOTION, self.on_click_up)
def set_box_hit(self, box: Box, hit: bool) -> None: box.state = Button.DISABLED hit = bool(hit) img = {False: "hatch", True: "cross"}[hit] image = Image(RESOURCES.IMG[img], size=box.size) image.center = box.center self.box_hit_img.add(image)
def __init__(self, name: str, boxes: Sequence[tuple[int, int]], orient: str): Image.__init__(self, RESOURCES.IMG[name]) self.name = name self.__orient = Ship.VERTICAL self.ship_size = len(boxes) self.boxes_pos = [tuple(box_pos) for box_pos in boxes] self.set_height(self.ship_size * BOX_SIZE[0]) self.orient = orient self.__boxes_covered = list()
def __init__(self, master, assembly_file: str, *args, **kwargs): TextButton.__init__(self, master, *args, **kwargs, command=self.select) self.file = assembly_file self.master = master self.comment = get_champion_comment(assembly_file) self.selected = False self.select_img = Image(IMG["valide"]) self.select_img.hide() master.add(self.select_img)
def __init__(self, player_id: int): Window.__init__(self, bg_color=(0, 200, 255), bg_music=RESOURCES.MUSIC["setup"]) self.gameplay = Gameplay(player_id) self.count_down = CountDown(self, 60, "Time left: {seconds}", font=(None, 70), color=WHITE) self.start_count_down = lambda: self.count_down.start( at_end=self.timeout) if self.client_socket.connected() else None params_for_all_buttons = { "bg": GREEN, "hover_bg": GREEN_LIGHT, "active_bg": GREEN_DARK, "highlight_color": YELLOW } self.button_back = ImageButton(self, RESOURCES.IMG["arrow_blue"], **params_for_all_buttons, rotate=180, size=50, callback=self.stop) self.navy_grid = DrawableListVertical(offset=0, bg_color=(0, 157, 255)) for i in range(NB_LINES_BOXES): box_line = DrawableListHorizontal(offset=0) for j in range(NB_COLUMNS_BOXES): box_line.add(BoxSetup(self, size=BOX_SIZE, pos=(i, j))) self.navy_grid.add(box_line) self.ships_list = DrawableListVertical(offset=70, justify="left") for ship_name, ship_infos in SHIPS.items(): ship_line = DrawableListHorizontal(offset=ship_infos["offset"]) for _ in range(ship_infos["nb"]): ship_line.add(ShipSetup(self, ship_name, ship_infos["size"])) self.ships_list.add(ship_line) option_size = 50 self.button_restart = Button.withImageOnly( self, Image(RESOURCES.IMG["reload_blue"], size=option_size), callback=self.reinit_all_ships, **params_for_all_buttons) self.button_random = Button.withImageOnly(self, Image( RESOURCES.IMG["random"], size=option_size), callback=self.shuffle, **params_for_all_buttons) self.button_play = Button(self, "Play", font=(None, 40), callback=self.play, **params_for_all_buttons)
def __init__(self, master: Window): Window.__init__(self, bg_color=BACKGROUND_COLOR) self.bind_key(pygame.K_ESCAPE, lambda event: self.stop()) self.master = master self.logo = Image(RESOURCES.IMG["logo"]) arrow = pygame.transform.flip(RESOURCES.IMG["arrow"], True, False) self.button_back = ImageButton(self, img=arrow, width=100, callback=self.stop, active_offset=(0, 5), highlight_color=YELLOW) self.grid = FourInARowGrid(self, self.width / 2, self.height * 0.75) self.__player_turn = 0 self.player_who_start_first = 0 self.player = 0 self.__turn = str() self.__turn_dict = dict() self.__score_player = self.__score_enemy = 0 self.__highlight_line_window_callback = None self.enemy = str() self.ai = FourInARowAI() self.text_score = Text() self.text_player_turn = Text() self.left_options = ButtonListVertical(offset=50) self.left_options.add( Button(self, "Restart", theme="option", callback=self.restart), Button(self, "Quit game", theme="option", callback=self.quit_game)) self.text_winner = Text() self.text_drawn_match = Text("Drawn match.") self.token_players = Grid(self) for row in range(2): self.token_players.place(CircleShape(20, PLAYER_TOKEN_COLOR[row + 1], outline=2, outline_color=WHITE), row, column=1, padx=5, pady=5, justify="left") self.enemy_quit_dialog = EnemyQuitGame(self)
def __init__(self): MainWindow.__init__(self, title=f"Navy - v{__version__}", size=(1280, 720), resources=RESOURCES, config=WINDOW_CONFIG_FILE) self.bg = Image(RESOURCES.IMG["menu_bg"], size=self.size) self.logo = Image(RESOURCES.IMG["logo"]) Button.set_default_theme("default") Button.set_theme("default", { "bg": GREEN, "hover_bg": GREEN_LIGHT, "active_bg": GREEN_DARK, "highlight_color": YELLOW, "outline": 3, }) Button.set_theme("title", { "font": (None, 100), }) Button.set_theme("option", { "font": ("calibri", 30), }) Scale.set_default_theme("default") Scale.set_theme("default", { "color": TRANSPARENT, "scale_color": GREEN, "highlight_color": YELLOW, "outline": 3 }) params_for_dialogs = { "outline": 5, "hide_all_without": [self.bg, self.logo] } self.start_game = NavySetup() self.multiplayer_server = PlayerServer(self, **params_for_dialogs) self.multiplayer_client = PlayerClient(self, **params_for_dialogs) self.dialog_credits = Credits(self, **params_for_dialogs) self.menu_buttons = ButtonListVertical(offset=30) self.menu_buttons.add( Button(self, "Play against AI", theme="title", callback=lambda: self.start_game.start(1)), Button(self, "Play as P1", theme="title", callback=self.multiplayer_server.mainloop), Button(self, "Play as P2", theme="title", callback=self.multiplayer_client.mainloop), Button(self, "Quit", theme="title", callback=self.stop) ) self.button_credits = Button(self, "Credits", font=("calibri", 50), callback=self.dialog_credits.mainloop)
def __init__(self, master, ship_name: str, ship_size: int): Image.__init__(self, RESOURCES.IMG[ship_name]) self.name = ship_name self.__orient = ShipSetup.VERTICAL self.master = master self.ship_size = ship_size self.orient = ShipSetup.HORIZONTAL self.set_width(self.ship_size * BOX_SIZE[0]) self.clicked = False self.on_move = False self.mouse_offset = (0, 0) self.default_center = (0, 0) self.center_before_click = (0, 0) self.__boxes_covered = list() self.master.bind_event(pygame.MOUSEBUTTONDOWN, self.select_event) self.master.bind_event(pygame.MOUSEBUTTONUP, self.unselect_event) self.master.bind_event(pygame.MOUSEMOTION, self.move_event)
def __init__(self): Window.__init__(self, bg_color=(0, 200, 255)) self.gameplay = Gameplay() self.enemy_quit_window = EnemyQuitGame(self) self.transition = GameSetupTransition() self.count_down = CountDown(self, 60, "Time left: {seconds}", font=(None, 70), color=WHITE) self.start_count_down = lambda: self.count_down.start( at_end=self.timeout) if self.client_socket.connected() else None self.button_back = ImageButton(self, RESOURCES.IMG["arrow_blue"], rotate=180, size=50, callback=self.stop) self.navy_grid = Grid(self, bg_color=(0, 157, 255)) self.__boxes_dict = {(i, j): BoxSetup(self, size=BOX_SIZE, pos=(i, j)) for i in range(NB_LINES_BOXES) for j in range(NB_COLUMNS_BOXES)} self.__boxes_list = list(self.__boxes_dict.values()) self.navy_grid.place_multiple(self.__boxes_dict) self.ships_list = DrawableListVertical(offset=70, justify="left") for ship_name, ship_infos in SHIPS.items(): ship_line = DrawableListHorizontal(offset=ship_infos["offset"]) for _ in range(ship_infos["nb"]): ship_line.add(ShipSetup(self, ship_name, ship_infos["size"])) self.ships_list.add(ship_line) option_size = 50 self.button_restart = Button(self, img=Image(RESOURCES.IMG["reload_blue"], size=option_size), callback=self.reinit_all_ships) self.button_random = Button(self, img=Image(RESOURCES.IMG["random"], size=option_size), callback=self.shuffle) self.button_play = Button(self, "Play", font=(None, 40), callback=self.play)
def __init__(self): Window.__init__(self, size=(1280, 720), flags=pygame.DOUBLEBUF, bg_music=RESOURCES.MUSIC["menu"]) self.set_icon(RESOURCES.IMG["icon"]) self.set_title(f"Navy - v{__version__}") self.set_fps(60) self.disable_key_joy_focus_for_all_window() self.bg = Image(RESOURCES.IMG["menu_bg"], self.size) self.logo = Image(RESOURCES.IMG["logo"]) params_for_all_buttons = { "font": (None, 100), "bg": GREEN, "hover_bg": GREEN_LIGHT, "active_bg": GREEN_DARK, "outline": 3, "highlight_color": YELLOW, } params_for_dialogs = { "outline": 5, "hide_all_without": [self.bg, self.logo] } self.start_game = NavySetup(1) self.multiplayer_server = PlayerServer(self, **params_for_dialogs) self.multiplayer_client = PlayerClient(self, **params_for_dialogs) self.dialog_credits = Credits(self, **params_for_dialogs) self.dialog_options = Options(self, **params_for_dialogs) self.menu_buttons = ButtonListVertical(offset=30) self.menu_buttons.add( Button(self, "Play against AI", **params_for_all_buttons, callback=self.start_game.mainloop), Button(self, "Play as P1", **params_for_all_buttons, callback=self.multiplayer_server.mainloop), Button(self, "Play as P2", **params_for_all_buttons, callback=self.multiplayer_client.mainloop), Button(self, "Quit", **params_for_all_buttons, callback=self.stop) ) self.button_credits = Button(self, "Credits", callback=self.dialog_credits.mainloop, **params_for_all_buttons) self.button_settings = Button.withImageOnly(self, Image(RESOURCES.IMG["settings"], size=self.button_credits.height - 20), callback=self.dialog_options.mainloop, **params_for_all_buttons)
def __init__(self, master): Window.__init__(self, bg_color=master.bg_color, bg_music=master.bg_music) params_for_button = { "highlight_color": YELLOW, "hover_sound": RESOURCES.SFX["select"], "on_click_sound": RESOURCES.SFX["back"] } self.master = master self.button_back = ImageButton(self, img=RESOURCES.IMG["blue_arrow"], **params_for_button, callback=self.stop) self.objects.add(master.text_highscore, master.text_money) self.text_title = Text("ENVIRONMENT", (RESOURCES.FONT["algerian"], 90), GREEN_DARK, shadow=True, shadow_x=2, shadow_y=2) self.environment = ButtonListHorizontal(offset=15) self.texts = DrawableList() for name, color in ENVIRONMENT.items(): b = Button(self, img=Image(RESOURCES.IMG[name], max_width=180, max_height=180), compound="center", outline=3, callback=lambda env=name: self.play(env), bg=color, hover_bg=change_saturation(color, -20), active_bg=change_brightness(color, -20), hover_sound=RESOURCES.SFX["select"], on_click_sound=RESOURCES.SFX["validate"], highlight_color=YELLOW) b.set_size(200) self.texts.add( Text(name.upper(), (RESOURCES.FONT["algerian"], 50), GREEN_DARK, shadow=True, shadow_x=2, shadow_y=2)) self.environment.add(b) self.bind_key(pygame.K_ESCAPE, lambda event: self.stop(sound=RESOURCES.SFX["back"])) self.bind_joystick( 0, "B", lambda event: self.stop(sound=RESOURCES.SFX["back"]))
class ChampionViewer(TextButton): def __init__(self, master, assembly_file: str, *args, **kwargs): TextButton.__init__(self, master, *args, **kwargs, command=self.select) self.file = assembly_file self.master = master self.comment = get_champion_comment(assembly_file) self.selected = False self.select_img = Image(IMG["valide"]) self.select_img.hide() master.add(self.select_img) def hide_all(self): self.hide() self.select_img.hide() def update(self, *args, **kwargs): self.select_img.move(left=self.right + 10, centery=self.centery) def select(self): self.selected = not self.selected if self.selected: if len(self.master.selected) >= MAX_NB_PLAYERS: self.selected = False return self.select_img.show() self.master.selected.append(self) else: self.select_img.hide() try: self.master.selected.remove(self) except ValueError: pass def update_file(self, new_file: str, new_name: str): self.file = new_file self.set_text(new_name) self.comment = get_champion_comment(new_file)
class FourInARowGameplay(Window): def __init__(self, master: Window): Window.__init__(self, bg_color=BACKGROUND_COLOR) self.bind_key(pygame.K_ESCAPE, lambda event: self.stop()) self.master = master self.logo = Image(RESOURCES.IMG["logo"]) arrow = pygame.transform.flip(RESOURCES.IMG["arrow"], True, False) self.button_back = ImageButton(self, img=arrow, width=100, callback=self.stop, active_offset=(0, 5), highlight_color=YELLOW) self.grid = FourInARowGrid(self, self.width / 2, self.height * 0.75) self.__player_turn = 0 self.player_who_start_first = 0 self.player = 0 self.__turn = str() self.__turn_dict = dict() self.__score_player = self.__score_enemy = 0 self.__highlight_line_window_callback = None self.enemy = str() self.ai = FourInARowAI() self.text_score = Text() self.text_player_turn = Text() self.left_options = ButtonListVertical(offset=50) self.left_options.add( Button(self, "Restart", theme="option", callback=self.restart), Button(self, "Quit game", theme="option", callback=self.quit_game)) self.text_winner = Text() self.text_drawn_match = Text("Drawn match.") self.token_players = Grid(self) for row in range(2): self.token_players.place(CircleShape(20, PLAYER_TOKEN_COLOR[row + 1], outline=2, outline_color=WHITE), row, column=1, padx=5, pady=5, justify="left") self.enemy_quit_dialog = EnemyQuitGame(self) def start(self, enemy: str, player=1, player_name=None, enemy_name=None, ai_level=None) -> None: self.player = player self.enemy = enemy if enemy == LAN_PLAYER: player_name = str(player_name) self.client_socket.send("name", player_name) result = self.client_socket.wait_for("name") if result == self.client_socket.QUIT_MESSAGE: return enemy_name = str(self.client_socket.get(result)) self.__turn_dict = { 1: { 1: player_name, 2: enemy_name }[player], 2: { 1: enemy_name, 2: player_name }[player] } else: player_name = str(player_name) if player_name is not None else "P1" enemy_name = str(enemy_name) if enemy_name is not None else "P2" self.__turn_dict = { 1: "You" if self.enemy == AI else player_name, 2: "AI" if self.enemy == AI else enemy_name } if self.enemy == AI: self.ai.level = ai_level for row, name in enumerate(self.__turn_dict.values()): self.token_players.place(Text(name + ":"), row, column=0, padx=5, pady=5, justify="right") self.mainloop() def on_start_loop(self) -> None: self.grid[0].focus_set() self.score_player = self.score_enemy = 0 self.player_who_start_first = 0 self.text_winner.hide() self.restart(init=True) def on_quit(self) -> None: self.stop_connection() def quit_game(self) -> None: self.stop() self.master.stop() def restart(self, init=False) -> None: if not init: self.client_socket.send("restart") self.grid.reset() self.remove_window_callback(self.__highlight_line_window_callback) if self.player_who_start_first == 0: if self.enemy == AI: self.player_turn = 1 elif self.enemy == LOCAL_PLAYER or (self.enemy == LAN_PLAYER and self.player == 1): self.player_turn = random.randint(1, 2) if self.enemy == LAN_PLAYER: self.client_socket.send("player_turn", int(self.player_turn)) elif self.enemy == LAN_PLAYER and self.player == 2: result = self.client_socket.wait_for("player_turn") if result == self.client_socket.QUIT_MESSAGE: self.stop() return self.player_turn = self.client_socket.get(result) elif self.text_winner.is_shown(): self.player_turn = (self.player_who_start_first % 2) + 1 else: self.player_turn = self.player_who_start_first self.player_who_start_first = self.player_turn self.text_winner.hide() self.text_drawn_match.hide() def place_objects(self) -> None: self.logo.move(centerx=self.centerx, top=10) self.grid.midbottom = self.midbottom self.text_score.move(left=10, top=self.grid.top) self.text_player_turn.move(left=self.text_score.left, top=self.text_score.bottom + 50) self.left_options.move(centerx=(self.left + self.grid.left) // 2, top=self.text_player_turn.bottom + 50) self.text_winner.center = ((self.grid.right + self.right) // 2, self.grid.centery) self.token_players.move(centerx=self.text_winner.centerx, top=self.grid.top) self.text_drawn_match.center = self.text_winner.center def set_grid(self) -> None: self.grid.set_obj_on_side(on_top=self.button_back, on_left=self.left_options[0]) self.button_back.set_obj_on_side(on_bottom=self.left_options[0], on_right=self.grid[0]) self.left_options.set_obj_on_side(on_top=self.button_back, on_right=self.grid[0]) @property def player_turn(self) -> int: return self.__player_turn @player_turn.setter def player_turn(self, player: int) -> None: self.__player_turn = player self.__turn = turn = self.__turn_dict[player] self.text_player_turn.message = f"Player turn:\n{turn}" self.place_objects() if self.enemy != LOCAL_PLAYER: for column in filter(lambda column: not column.full(), self.grid.columns): column.set_enabled(self.player_turn == self.player) if self.enemy == AI and self.player_turn == 2: self.after(500, self.play, self.ai.play(self.grid.map)) @property def score_player(self) -> int: return self.__score_player @score_player.setter def score_player(self, value: int) -> None: self.__score_player = value self.__update_text_score() @property def score_enemy(self) -> int: return self.__score_enemy @score_enemy.setter def score_enemy(self, value: int) -> None: self.__score_enemy = value self.__update_text_score() def __update_text_score(self) -> None: self.text_score.message = "Score:\n{you}: {score_1}\n{enemy}: {score_2}".format( you=self.__turn_dict[1], enemy=self.__turn_dict[2], score_1=self.score_player, score_2=self.score_enemy) self.place_objects() def update(self) -> None: if self.enemy == LAN_PLAYER: if self.client_socket.recv("column"): self.play(self.client_socket.get("column")) if self.client_socket.recv("restart"): self.restart() if self.client_socket.recv(self.client_socket.QUIT_MESSAGE): self.enemy_quit_dialog.text.message = "{}\nhas left the game".format( self.__turn_dict[(self.player % 2) + 1]) self.enemy_quit_dialog.mainloop() def play(self, column: int) -> None: self.block_only_event([ pygame.KEYDOWN, pygame.KEYUP, pygame.JOYBUTTONDOWN, pygame.JOYBUTTONUP, pygame.MOUSEBUTTONDOWN, pygame.MOUSEBUTTONUP ]) if self.enemy == LAN_PLAYER and self.player_turn == self.player: self.client_socket.send("column", column) self.grid.play(self.player_turn, column) line = self.check_victory() if line: for c in self.grid.columns: c.disable() self.left_options[0].focus_set() self.update_winner() self.highlight_line(line) elif self.grid.full(): self.left_options[0].focus_set() self.text_drawn_match.show() else: self.player_turn = (self.player_turn % 2) + 1 if self.enemy == LOCAL_PLAYER: self.draw_and_refresh() pygame.time.wait(500) self.clear_all_events() self.allow_all_events() def check_victory(self) -> list[tuple[int, int]]: grid = self.grid.map grid_pos_getter = [ lambda row, col, index: (row, col + index), # Check row (->) lambda row, col, index: (row, col - index), # Check row (<-) lambda row, col, index: (row + index, col), # Check column lambda row, col, index: (row + index, col - index), # Check diagonal (/) lambda row, col, index: (row + index, col + index), # Check diagonal (\) ] all_box_pos = list() box_pos = list() for row, column in filter(lambda pos: grid[pos] != 0, grid): for grid_pos in grid_pos_getter: index = 0 box_pos.clear() while grid.get(grid_pos(row, column, index), -1) == grid[row, column]: box_pos.append(grid_pos(row, column, index)) index += 1 if len(box_pos) >= 4: all_box_pos.extend( filter(lambda pos: pos not in all_box_pos, box_pos)) return all_box_pos def highlight_line(self, line: list[tuple[int, int]], highlight=True): for row, col in line: box = self.grid.columns[col].boxes[row] if highlight: box.circle.color = GREEN else: box.value = box.value self.__highlight_line_window_callback = self.after( 500, self.highlight_line, line=line, highlight=not highlight) def update_winner(self): if self.player_turn == 1: self.score_player += 1 else: self.score_enemy += 1 winner = self.__turn self.text_winner.message = f"Winner:\n{winner}" self.text_winner.show()
class Gameplay(Window): def __init__(self, car_id: int, env: str): Window.__init__(self, bg_color=ENVIRONMENT[env], bg_music=RESOURCES.MUSIC["gameplay"]) self.bind_key(pygame.K_ESCAPE, lambda event: self.pause()) self.bind_joystick(0, "START", lambda event: self.pause()) font = RESOURCES.FONT["cooperblack"] # Demaraction lines self.road = DrawableListVertical(bg_color=GRAY, offset=70) self.white_bands = list() white_bands_width = 50 #px white_lines_height = 10 #px for i in range(5): if i % 2 == 0: self.road.add( RectangleShape(self.width, white_lines_height, WHITE)) else: white_bands = DrawableListHorizontal(offset=20) while white_bands.width < self.width: white_bands.add( RectangleShape(white_bands_width, white_lines_height, WHITE)) self.road.add(white_bands) self.white_bands.append(white_bands) # Environment self.env_top = DrawableListHorizontal(offset=400) self.env_bottom = DrawableListHorizontal(offset=400) while self.env_top.width < self.width: self.env_top.add(Image(RESOURCES.IMG[env], height=110)) while self.env_bottom.width < self.width: self.env_bottom.add(Image(RESOURCES.IMG[env], height=110)) #Infos params_for_infos = { "font": (font, 45), "color": YELLOW, "shadow": True, "shadow_x": 3, "shadow_y": 3 } self.infos_score = Info("Score", round_n=0, **params_for_infos) self.infos_speed = Info("Speed", extension="km/h", **params_for_infos, justify="right") self.infos_distance = Info("Distance", round_n=2, extension="km", **params_for_infos, justify="right") self.infos_time_100 = Info("High speed", **params_for_infos) self.infos_time_opposite = Info("Opposite side", **params_for_infos) self.clock_time_100 = Clock() self.clock_time_opposite = Clock() self.total_time_100 = self.total_time_opposite = 0 self.car = PlayerCar(car_id) self.speed = 0 self.traffic = TrafficCarList(nb_ways=4, max_nb_car=6) self.clock_traffic = Clock() self.img_crash = Image(RESOURCES.IMG["crash"], size=150) self.count_down = CountDown(self, 3, font=(font, 90), color=YELLOW, shadow=True, shadow_x=5, shadow_y=5) self.last_car_way = 0 # Background self.background = DrawableList(draw=False) self.background.add(self.env_top, self.env_bottom, *self.white_bands, self.traffic) # Default values self.update_clock = Clock() self.update_time = 15 #ms self.pixel_per_sec = 6 # For 1km/h self.pixel_per_ms = self.pixel_per_sec * self.update_time / 1000 self.paused = False self.go_to_garage = self.restart = False self.crashed_car = None self.disable_key_joy_focus() self.init_game() def pause(self): if not self.count_down.is_shown(): self.paused = True self.car.stop_animation() for car in self.traffic: car.stop_animation() pause = Pause(self) pause.mainloop() if self.loop and not self.count_down.is_shown(): self.count_down.start(at_end=self.return_to_game) self.objects.set_priority(self.count_down, self.objects.end) def return_to_game(self): self.paused = False self.car.restart_animation() for car in self.traffic: car.restart_animation() self.clock_traffic.tick() self.clock_time_100.tick() self.clock_time_opposite.tick() self.update_clock.tick() def init_game(self): self.go_to_garage = False self.paused = False self.crashed_car = None for info in (self.infos_speed, self.infos_score, self.infos_distance, self.infos_time_100, self.infos_time_opposite): info.value = 0 if info in (self.infos_time_100, self.infos_time_opposite): info.hide() self.total_time_100 = self.total_time_opposite = 0 self.count_down.start() self.img_crash.hide() def place_objects(self): self.count_down.center = self.road.center = self.center self.infos_score.move(topleft=(10, 10)) self.infos_speed.move(right=self.right - 10, top=10) self.infos_distance.move(right=self.right - 10, bottom=self.road.top - 10) self.infos_time_100.move(left=10, bottom=self.road.top - 10) self.infos_time_opposite.move(left=10, top=self.road.bottom + 10) self.car.move(centery=self.road.centery, left=50) self.env_top.move(centerx=self.centerx, centery=(self.top + self.road[0].top) / 2) self.env_bottom.move(centerx=self.centerx, centery=(self.road[-1].bottom + self.bottom) / 2) def update(self): if self.paused: return self.update_player_car() if self.update_clock.elapsed_time(self.update_time): self.update_infos() self.update_background() self.update_traffic() self.rect_to_update = (self.road.rect, self.env_top.rect, self.env_bottom.rect, self.infos_score.rect, self.infos_speed.rect, self.infos_distance.rect, self.infos_time_100.rect, self.infos_time_opposite.rect) def update_player_car(self): if not self.count_down.is_shown(): joystick = self.joystick[0] controls = SAVE["controls"] car_handling = ( (controls["speed_up"], self.car.speed_up), (controls["brake"], self.car.brake), (controls["up"], self.car.moveUp), (controls["down"], self.car.moveDown), ) for control, car_function in car_handling: car_function(self.keyboard.is_pressed(control["key"])) car_function(joystick.get_value(control["joy"])) if SAVE["auto_acceleration"] is True: self.car.speed_up() self.car.update(self.pixel_per_ms) if self.car.top < self.road[0].bottom + 5: self.car.top = self.road[0].bottom + 5 elif self.car.bottom > self.road[-1].top - 5: self.car.bottom = self.road[-1].top - 5 if not self.car.is_crashed(): self.speed = self.car.speed for car in self.traffic: collision = pygame.sprite.collide_mask(self.car, car) if collision: self.car.crash(car) self.crashed_car = car self.play_sound(RESOURCES.SFX["crash"]) self.img_crash.show() self.img_crash.move(centerx=collision[0] + self.car.left, centery=collision[1] + self.car.top) self.objects.set_priority(self.img_crash, self.objects.end) elif self.car.right <= 0 and self.crashed_car.right <= 0: self.end_game() def car_in_opposite_side(self) -> bool: return bool(self.car.bottom < self.road.centery) def update_infos(self): min_speed = 30 score_to_add = (self.car.speed - min_speed) / 5 bonus = False if self.car.speed > 30 and self.car_in_opposite_side(): self.infos_time_opposite.show() self.infos_time_opposite.value = self.clock_time_opposite.get_elapsed_time( ) / 1000 score_to_add += 120 bonus = True else: self.total_time_opposite += self.infos_time_opposite.value self.infos_time_opposite.value = 0 self.clock_time_opposite.restart() self.infos_time_opposite.hide() if self.car.speed >= 100: self.infos_time_100.show() self.infos_time_100.value = self.clock_time_100.get_elapsed_time( ) / 1000 score_to_add += 150 bonus = True else: self.total_time_100 += self.infos_time_100.value self.infos_time_100.value = 0 self.clock_time_100.restart() self.infos_time_100.hide() if bonus: self.infos_score.color = GREEN_DARK self.infos_score.shadow_color = YELLOW else: self.infos_score.color = YELLOW self.infos_score.shadow_color = BLACK self.infos_score.value += score_to_add * self.update_time / 1000 self.infos_speed.value = self.car.speed self.infos_distance.value += self.car.speed * self.pixel_per_ms / ( 1000 * 3.6) def update_background(self): offset = self.speed * self.pixel_per_ms self.background.move_ip(-offset, 0) for white_bands_list in self.white_bands: if white_bands_list[0].right <= 0: white_bands_list.remove_from_index(0) if white_bands_list[-1].right < self.right: white_bands_list.add( RectangleShape(*white_bands_list[-1].size, WHITE)) for env in (self.env_top, self.env_bottom): img = env[0] if img.right <= 0: img.move(left=env[-1].right + env.offset) env.set_priority(img, env.end) if self.img_crash.is_shown(): self.img_crash.move_ip(-offset, 0) def update_traffic(self): for car in self.traffic.drawable: car.update(self.pixel_per_ms) if car.right < 0: self.traffic.remove(car) for way, car_list in enumerate(self.traffic.ways, 1): for i in range(1, len(car_list)): car_1 = car_list[i - 1] car_2 = car_list[i] if car_2.left - car_1.right < 20: if (way in [1, 2]) and (car_1.speed < car_2.speed): car_2.speed = car_1.speed elif (way in [3, 4]) and (car_1.speed > car_2.speed): car_1.speed = car_2.speed ratio = (2 - (round(self.infos_score.value) / 20000)) * 1000 if self.car.speed > 30 and self.clock_traffic.elapsed_time(ratio): if self.traffic.empty( ) or self.traffic.last.right < self.right - 20: self.traffic.add_cars(self, self.road, round(self.infos_score.value)) def end_game(self): for car in self.traffic: car.stop_animation() self.crashed_car = None score = round(self.infos_score.value) distance = round(self.infos_distance.value, 1) time_100 = round(self.total_time_100, 1) time_opposite = round(self.total_time_opposite, 1) window = EndGame(self, score, distance, time_100, time_opposite) window.mainloop() if self.restart: self.traffic.clear() self.car.move(left=50, centery=self.road.centery) self.car.restart() self.init_game()
def __init__(self): Window.__init__(self, bg_color=GRAY, bg_music=RESOURCES.MUSIC["garage"]) params_for_all_buttons = { "bg": GREEN, "hover_bg": GREEN_LIGHT, "active_bg": GREEN_DARK, "highlight_color": YELLOW, "hover_sound": RESOURCES.SFX["select"], } params_for_button_except_back = { "on_click_sound": RESOURCES.SFX["validate"], "disabled_sound": RESOURCES.SFX["block"], "disabled_bg": GRAY_LIGHT, } params_for_button_except_back.update(params_for_all_buttons) params_for_car_viewer = { k: params_for_button_except_back[k] for k in ["hover_sound", "on_click_sound"] } self.button_back = ImageButton(self, RESOURCES.IMG["blue_arrow"], **params_for_all_buttons, on_click_sound=RESOURCES.SFX["back"], callback=self.stop) self.car_viewer = CarViewer(self, SAVE["car"], **params_for_car_viewer) size_progress_bar = (300, 30) self.speed_bar = ProgressBar(*size_progress_bar, TRANSPARENT, GREEN) self.maniability_bar = ProgressBar(*size_progress_bar, TRANSPARENT, GREEN) self.braking_bar = ProgressBar(*size_progress_bar, TRANSPARENT, GREEN) self.left_arrow = ImageButton( self, img=RESOURCES.IMG["left_arrow"], active_img=RESOURCES.IMG["left_arrow_hover"], **params_for_button_except_back, callback=self.car_viewer.decrease_id) self.right_arrow = ImageButton( self, img=RESOURCES.IMG["right_arrow"], active_img=RESOURCES.IMG["right_arrow_hover"], **params_for_button_except_back, callback=self.car_viewer.increase_id) for arrow in [self.left_arrow, self.right_arrow]: arrow.take_focus(False) self.button_price = Button(self, font=(RESOURCES.FONT["algerian"], 40), img=Image(RESOURCES.IMG["piece"], size=40), compound="right", callback=self.buy_car, **params_for_button_except_back) self.button_play = Button(self, "Play", font=(RESOURCES.FONT["algerian"], 70), callback=self.play, **params_for_button_except_back) self.text_money = Text(format_number(SAVE["money"]), (RESOURCES.FONT["algerian"], 50), YELLOW, img=Image(RESOURCES.IMG["piece"], height=40), compound="right") self.text_highscore = Text( "Highscore: {}".format(format_number(SAVE["highscore"])), (RESOURCES.FONT["algerian"], 50), YELLOW) self.padlock = Image(RESOURCES.IMG["padlock"]) self.bind_key(pygame.K_ESCAPE, lambda event: self.stop(sound=RESOURCES.SFX["back"])) self.bind_joystick( 0, "B", lambda event: self.stop(sound=RESOURCES.SFX["back"]))
class Garage(Window): def __init__(self): Window.__init__(self, bg_color=GRAY, bg_music=RESOURCES.MUSIC["garage"]) params_for_all_buttons = { "bg": GREEN, "hover_bg": GREEN_LIGHT, "active_bg": GREEN_DARK, "highlight_color": YELLOW, "hover_sound": RESOURCES.SFX["select"], } params_for_button_except_back = { "on_click_sound": RESOURCES.SFX["validate"], "disabled_sound": RESOURCES.SFX["block"], "disabled_bg": GRAY_LIGHT, } params_for_button_except_back.update(params_for_all_buttons) params_for_car_viewer = { k: params_for_button_except_back[k] for k in ["hover_sound", "on_click_sound"] } self.button_back = ImageButton(self, RESOURCES.IMG["blue_arrow"], **params_for_all_buttons, on_click_sound=RESOURCES.SFX["back"], callback=self.stop) self.car_viewer = CarViewer(self, SAVE["car"], **params_for_car_viewer) size_progress_bar = (300, 30) self.speed_bar = ProgressBar(*size_progress_bar, TRANSPARENT, GREEN) self.maniability_bar = ProgressBar(*size_progress_bar, TRANSPARENT, GREEN) self.braking_bar = ProgressBar(*size_progress_bar, TRANSPARENT, GREEN) self.left_arrow = ImageButton( self, img=RESOURCES.IMG["left_arrow"], active_img=RESOURCES.IMG["left_arrow_hover"], **params_for_button_except_back, callback=self.car_viewer.decrease_id) self.right_arrow = ImageButton( self, img=RESOURCES.IMG["right_arrow"], active_img=RESOURCES.IMG["right_arrow_hover"], **params_for_button_except_back, callback=self.car_viewer.increase_id) for arrow in [self.left_arrow, self.right_arrow]: arrow.take_focus(False) self.button_price = Button(self, font=(RESOURCES.FONT["algerian"], 40), img=Image(RESOURCES.IMG["piece"], size=40), compound="right", callback=self.buy_car, **params_for_button_except_back) self.button_play = Button(self, "Play", font=(RESOURCES.FONT["algerian"], 70), callback=self.play, **params_for_button_except_back) self.text_money = Text(format_number(SAVE["money"]), (RESOURCES.FONT["algerian"], 50), YELLOW, img=Image(RESOURCES.IMG["piece"], height=40), compound="right") self.text_highscore = Text( "Highscore: {}".format(format_number(SAVE["highscore"])), (RESOURCES.FONT["algerian"], 50), YELLOW) self.padlock = Image(RESOURCES.IMG["padlock"]) self.bind_key(pygame.K_ESCAPE, lambda event: self.stop(sound=RESOURCES.SFX["back"])) self.bind_joystick( 0, "B", lambda event: self.stop(sound=RESOURCES.SFX["back"])) def update(self): self.left_arrow.set_visibility(self.car_viewer.id > 1) self.right_arrow.set_visibility( self.car_viewer.id < len(self.car_viewer)) if not SAVE["owned_cars"][self.car_viewer.id]: self.padlock.show() price = self.car_viewer["price"] if isinstance(price, int): self.button_price.show() self.button_price.text = format_number(price) self.button_price.state = Button.NORMAL if SAVE[ "money"] >= price else Button.DISABLED else: self.button_price.hide() self.button_play.state = Button.DISABLED else: self.padlock.hide() self.button_price.hide() self.button_play.state = Button.NORMAL SAVE["car"] = self.car_viewer.id max_s = self.car_viewer.max_speed min_a = self.car_viewer.min_acceleration max_m = self.car_viewer.max_maniability min_b = self.car_viewer.min_braking s = self.car_viewer["max_speed"] a = self.car_viewer["acceleration"] m = self.car_viewer["maniability"] b = self.car_viewer["braking"] self.speed_bar.percent = (s + min_a) / (max_s + a) self.maniability_bar.percent = m / max_m self.braking_bar.percent = min_b / b def place_objects(self): self.button_back.topleft = (5, 5) self.car_viewer.move(center=self.center) self.padlock.center = self.car_viewer.center self.braking_bar.move(bottom=self.car_viewer.top - 40, centerx=self.car_viewer.centerx + 100) self.maniability_bar.move(bottom=self.braking_bar.top - 10, centerx=self.car_viewer.centerx + 100) self.speed_bar.move(bottom=self.maniability_bar.top - 10, centerx=self.car_viewer.centerx + 100) self.speed_bar.show_label("Speed/Acc.", ProgressBar.S_LEFT, font=(RESOURCES.FONT["algerian"], 40)) self.maniability_bar.show_label("Maniability", ProgressBar.S_LEFT, font=(RESOURCES.FONT["algerian"], 40)) self.braking_bar.show_label("Braking", ProgressBar.S_LEFT, font=(RESOURCES.FONT["algerian"], 40)) self.left_arrow.move(left=self.left + 50, centery=self.centery) self.right_arrow.move(right=self.right - 50, centery=self.centery) self.button_price.move(centerx=self.centerx, top=self.car_viewer.bottom + 25) self.button_play.move(bottom=self.bottom - 50, right=self.right - 10) self.text_money.move(top=5, right=self.right - 10) self.text_highscore.move(bottom=self.bottom - 50, left=5) def set_grid(self): self.button_back.set_obj_on_side(on_bottom=self.car_viewer) self.car_viewer.set_obj_on_side(on_top=self.button_back, on_bottom=self.button_price) self.button_price.set_obj_on_side(on_top=self.car_viewer, on_bottom=self.button_play) self.button_play.set_obj_on_side(on_top=self.button_price) def buy_car(self): confirm_window = ConfirmPayement(self) confirm_window.mainloop() if confirm_window.buyed: SAVE["money"] -= self.car_viewer["price"] SAVE["owned_cars"][self.car_viewer.id] = True self.text_money.message = format_number(SAVE["money"]) if Clickable.MODE != Clickable.MODE_MOUSE: self.car_viewer.focus_set() def play(self): environment_chooser = EnvironmentChooser(self) environment_chooser.mainloop() self.text_money.message = format_number(SAVE["money"]) self.text_highscore.message = "Highscore: {}".format( format_number(SAVE["highscore"]))
def __init__(self, car_id: int, env: str): Window.__init__(self, bg_color=ENVIRONMENT[env], bg_music=RESOURCES.MUSIC["gameplay"]) self.bind_key(pygame.K_ESCAPE, lambda event: self.pause()) self.bind_joystick(0, "START", lambda event: self.pause()) font = RESOURCES.FONT["cooperblack"] # Demaraction lines self.road = DrawableListVertical(bg_color=GRAY, offset=70) self.white_bands = list() white_bands_width = 50 #px white_lines_height = 10 #px for i in range(5): if i % 2 == 0: self.road.add( RectangleShape(self.width, white_lines_height, WHITE)) else: white_bands = DrawableListHorizontal(offset=20) while white_bands.width < self.width: white_bands.add( RectangleShape(white_bands_width, white_lines_height, WHITE)) self.road.add(white_bands) self.white_bands.append(white_bands) # Environment self.env_top = DrawableListHorizontal(offset=400) self.env_bottom = DrawableListHorizontal(offset=400) while self.env_top.width < self.width: self.env_top.add(Image(RESOURCES.IMG[env], height=110)) while self.env_bottom.width < self.width: self.env_bottom.add(Image(RESOURCES.IMG[env], height=110)) #Infos params_for_infos = { "font": (font, 45), "color": YELLOW, "shadow": True, "shadow_x": 3, "shadow_y": 3 } self.infos_score = Info("Score", round_n=0, **params_for_infos) self.infos_speed = Info("Speed", extension="km/h", **params_for_infos, justify="right") self.infos_distance = Info("Distance", round_n=2, extension="km", **params_for_infos, justify="right") self.infos_time_100 = Info("High speed", **params_for_infos) self.infos_time_opposite = Info("Opposite side", **params_for_infos) self.clock_time_100 = Clock() self.clock_time_opposite = Clock() self.total_time_100 = self.total_time_opposite = 0 self.car = PlayerCar(car_id) self.speed = 0 self.traffic = TrafficCarList(nb_ways=4, max_nb_car=6) self.clock_traffic = Clock() self.img_crash = Image(RESOURCES.IMG["crash"], size=150) self.count_down = CountDown(self, 3, font=(font, 90), color=YELLOW, shadow=True, shadow_x=5, shadow_y=5) self.last_car_way = 0 # Background self.background = DrawableList(draw=False) self.background.add(self.env_top, self.env_bottom, *self.white_bands, self.traffic) # Default values self.update_clock = Clock() self.update_time = 15 #ms self.pixel_per_sec = 6 # For 1km/h self.pixel_per_ms = self.pixel_per_sec * self.update_time / 1000 self.paused = False self.go_to_garage = self.restart = False self.crashed_car = None self.disable_key_joy_focus() self.init_game()
def __init__(self, master, score: int, distance: float, time_100: float, time_opposite: float): Window.__init__(self, master=master, bg_music=master.bg_music) self.master = master self.bg = RectangleShape(*self.size, (0, 0, 0, 170)) self.text_score = Text(f"Your score\n{score}", (RESOURCES.FONT["algerian"], 90), YELLOW, justify="center") self.img_highscore = Image(RESOURCES.IMG["new_high_score"], width=150) if score > SAVE["highscore"]: SAVE["highscore"] = score else: self.img_highscore.hide() MAX_MONEY = pow(10, 9) - 1 money_distance = round(300.40 * distance) money_time_100 = round(12.5 * time_100) money_time_opposite = round(21.7 * time_opposite) money_gained = money_distance + money_time_100 + money_time_opposite total = SAVE["money"] + money_gained SAVE["money"] = MAX_MONEY if total > MAX_MONEY else total self.text_money = Text(format_number(SAVE["money"]), (RESOURCES.FONT["algerian"], 50), YELLOW, img=Image(RESOURCES.IMG["piece"], height=40), compound="right") font = ("calibri", 50) self.frame = RectangleShape(0.75 * self.width, 0.45 * self.height, BLACK, outline=1, outline_color=WHITE) self.text_distance = Text(f"Distance: {distance}", font, WHITE) self.img_green_arrow_distance = Image(RESOURCES.IMG["green_arrow"], height=40) self.text_money_distance = Text(money_distance, font, WHITE, img=Image(RESOURCES.IMG["piece"], height=40), compound="right") self.text_time_100 = Text(f"Time up to 100: {time_100}", font, WHITE) self.img_green_arrow_time_100 = Image(RESOURCES.IMG["green_arrow"], height=40) self.text_money_time_100 = Text(money_time_100, font, WHITE, img=Image(RESOURCES.IMG["piece"], height=40), compound="right") self.text_time_opposite = Text( f"Time in opposite side: {time_opposite}", font, WHITE) self.img_green_arrow_time_opposite = Image( RESOURCES.IMG["green_arrow"], height=40) self.text_money_time_opposite = Text(money_time_opposite, font, WHITE, img=Image(RESOURCES.IMG["piece"], height=40), compound="right") self.total_money = DrawableListHorizontal(offset=10) self.total_money.add( Text("TOTAL: ", font, WHITE), Text(money_gained, font, WHITE, img=Image(RESOURCES.IMG["piece"], height=40), compound="right")) params_for_all_buttons = { "font": (RESOURCES.FONT["algerian"], 50), "bg": GREEN, "hover_bg": GREEN_LIGHT, "active_bg": GREEN_DARK, "hover_sound": RESOURCES.SFX["select"], "on_click_sound": RESOURCES.SFX["validate"], "outline": 3, "highlight_color": YELLOW } self.menu_buttons = ButtonListHorizontal(offset=30) self.menu_buttons.add( Button(self, "Restart", **params_for_all_buttons, callback=self.restart_game), Button(self, "Garage", **params_for_all_buttons, callback=self.return_to_garage), Button(self, "Menu", **params_for_all_buttons, callback=self.return_to_menu))
class PyGameCase(MainWindow): RUNNING_STATE_SUFFIX = " - Running" def __init__(self): super().__init__(title=f"Py-Game-Case - v{__version__}", size=(1280, 720), flags=pygame.RESIZABLE, bg_color=(0, 0, 100), resources=RESOURCES) TitleButton.set_default_theme("default") TitleButton.set_theme("default", { "font": ("calibri", 30), "bg": TRANSPARENT, "fg": WHITE, "outline": 0, "hover_bg": set_color_alpha(WHITE, 100), "active_bg": set_color_alpha(WHITE, 50), "highlight_color": WHITE, "highlight_thickness": 3, "x_size": self.w * 0.25, "y_add_size": 30, "justify": ("left", "center"), "offset": (10, 0), "hover_offset": (0, -5), "active_offset": (0, 10) }) SettingsButton.set_default_theme("default") SettingsButton.set_theme("default", { "bg": WHITE, "hover_bg": YELLOW, "active_bg": change_brightness(YELLOW, -75), "outline": 7, "outline_color": WHITE, "highlight_thickness": 0 }) self.launcher_updater = Updater(__version__) self.image_game_preview = SpriteDict() self.bg = DrawableListHorizontal() left_color = BLACK right_color = set_color_alpha(BLACK, 60) self.bg.add( RectangleShape(self.w * 0.25, self.h, left_color), HorizontalGradientShape(self.w * 0.5, self.h, left_color, right_color), RectangleShape(self.w * 0.25, self.h, right_color), ) self.logo = Image(RESOURCES.IMG["logo"], width=self.bg[0].width) self.buttons_game_launch = ButtonListVertical(offset=30) self.buttons_game_dict = dict[str, TitleButton]() self.window_game_dict = dict[str, MainWindow]() for game_id, game_infos in GAMES.items(): button = TitleButton( self, lambda game_id=game_id: self.show_preview(game_id), text=game_infos["name"], callback=lambda game_id=game_id: self.launch_game(game_id) ) self.image_game_preview[game_id] = Sprite(RESOURCES.IMG[game_id], height=self.height) self.buttons_game_dict[game_id] = button self.buttons_game_launch.add_multiple(self.buttons_game_dict.values()) self.game_id = None self.game_launched_processes = GameProcessList() self.settings_section = SettingsWindow(self) self.updater_window = UpdaterWindow(self, self.launcher_updater) self.side_board = SideBoard(self) self.side_board.add_option("Settings", self.settings_section.mainloop) if psutil.WINDOWS: self.side_board.add_option("Update", lambda: self.updater_window.start(install=True)) self.button_settings = SettingsButton(self, size=40, callback=self.side_board.mainloop) self.button_settings.force_use_highlight_thickness(True) self.transition = GameLaunchTransition() def place_objects(self) -> None: self.bg.center = self.center self.logo.move(left=10, top=10) self.buttons_game_launch.move(left=10, top=self.logo.bottom + 50) self.image_game_preview.midright = self.midleft self.button_settings.move(right=self.right - 20, top=20) def set_grid(self) -> None: self.button_settings.set_obj_on_side(on_bottom=self.buttons_game_launch[0], on_left=self.buttons_game_launch[0]) self.buttons_game_launch.set_obj_on_side(on_top=self.button_settings, on_right=self.button_settings) def on_start_loop(self): self.image_game_preview.move(right=self.left, top=self.top) save_objects_center = list() for obj in [self.logo, *self.buttons_game_dict.values(), self.button_settings]: save_objects_center.append((obj, obj.get_move())) self.buttons_game_launch.right = self.left self.button_settings.left = self.right default_logo_width = self.logo.width self.logo.load(RESOURCES.IMG["logo"]) self.logo.midtop = self.midbottom if psutil.WINDOWS: if self.launcher_updater.has_a_downloaded_update() or (SETTINGS.auto_check_update and self.launcher_updater.has_a_new_release()): self.logo.animate_move(self, speed=20, top=0, centerx=self.centerx) self.updater_window.start() self.logo.animate_move(self, speed=20, midbottom=self.center) loading = ProgressBar( default_logo_width, 40, TRANSPARENT, GREEN, from_=0, to=len(GAMES), default=len(self.window_game_dict), outline_color=WHITE, border_radius=10 ) loading.center = self.logo.center loading.show_percent(ProgressBar.S_INSIDE, font=("calibri", 30), color=WHITE) self.objects.add(loading) self.objects.set_priority(loading, 0, relative_to=self.logo) loading.animate_move(self, speed=10, centerx=loading.centerx, top=self.logo.bottom + 20) try: for game_id, game_infos in filter(lambda item: item[0] not in self.window_game_dict, GAMES.items()): with ThemeNamespace(game_id): self.window_game_dict[game_id] = game_infos["window"]() loading.value = len(self.window_game_dict) self.draw_and_refresh(pump=True) except: sys.excepthook(*sys.exc_info()) self.stop(force=True) pygame.time.wait(100) loading.animate_move(self, speed=10, center=self.logo.center) self.objects.remove(loading) self.logo.animation.rotate(angle=360, offset=5, point="center").scale_width(width=default_logo_width, offset=7).start(self) for obj, move in save_objects_center: obj.animate_move(self, speed=20, **move) self.focus_mode(Button.MODE_KEY) pygame.event.clear() def on_quit(self) -> None: self.launcher_updater.close() def update(self) -> None: if self.game_launched_processes: for process in self.game_launched_processes.check_for_terminated_games(): self.buttons_game_dict[process.game_id].text = GAMES[process.game_id]["name"] self.buttons_game_dict[process.game_id].state = Button.NORMAL # if not self.game_launched_processes and not pygame.display.get_active(): # pass if all(not button.has_focus() and not button.hover for button in self.buttons_game_launch) and self.game_id is not None: self.image_game_preview.animate_move_in_background(self, speed=75, right=self.left) self.game_id = None def show_preview(self, game_id: str) -> None: if self.game_id == game_id: return self.game_id = game_id self.image_game_preview.animate_move_in_background(self, speed=75, right=self.left, after_animation=self.__show_preview) def __show_preview(self) -> None: self.image_game_preview.use_sprite(self.game_id) self.image_game_preview.animate_move_in_background(self, speed=75, right=self.right) def launch_game(self, game_id: str) -> None: if not SETTINGS.launch_in_same_window: self.game_launched_processes.launch(game_id) self.buttons_game_dict[game_id].text += PyGameCase.RUNNING_STATE_SUFFIX self.buttons_game_dict[game_id].state = Button.DISABLED self.iconify() else: self.game_id = game_id if self.image_game_preview.get_actual_sprite_name() != game_id: self.image_game_preview.animate_move(self, speed=75, right=self.left) self.image_game_preview.use_sprite(game_id) self.image_game_preview.animate_move(self, speed=75, right=self.right) window = self.window_game_dict[game_id] window.mainloop(transition=self.transition) def close(self) -> None: if self.game_launched_processes: self.iconify() else: self.stop(force=True)
def __init__(self): super().__init__(title=f"Py-Game-Case - v{__version__}", size=(1280, 720), flags=pygame.RESIZABLE, bg_color=(0, 0, 100), resources=RESOURCES) TitleButton.set_default_theme("default") TitleButton.set_theme("default", { "font": ("calibri", 30), "bg": TRANSPARENT, "fg": WHITE, "outline": 0, "hover_bg": set_color_alpha(WHITE, 100), "active_bg": set_color_alpha(WHITE, 50), "highlight_color": WHITE, "highlight_thickness": 3, "x_size": self.w * 0.25, "y_add_size": 30, "justify": ("left", "center"), "offset": (10, 0), "hover_offset": (0, -5), "active_offset": (0, 10) }) SettingsButton.set_default_theme("default") SettingsButton.set_theme("default", { "bg": WHITE, "hover_bg": YELLOW, "active_bg": change_brightness(YELLOW, -75), "outline": 7, "outline_color": WHITE, "highlight_thickness": 0 }) self.launcher_updater = Updater(__version__) self.image_game_preview = SpriteDict() self.bg = DrawableListHorizontal() left_color = BLACK right_color = set_color_alpha(BLACK, 60) self.bg.add( RectangleShape(self.w * 0.25, self.h, left_color), HorizontalGradientShape(self.w * 0.5, self.h, left_color, right_color), RectangleShape(self.w * 0.25, self.h, right_color), ) self.logo = Image(RESOURCES.IMG["logo"], width=self.bg[0].width) self.buttons_game_launch = ButtonListVertical(offset=30) self.buttons_game_dict = dict[str, TitleButton]() self.window_game_dict = dict[str, MainWindow]() for game_id, game_infos in GAMES.items(): button = TitleButton( self, lambda game_id=game_id: self.show_preview(game_id), text=game_infos["name"], callback=lambda game_id=game_id: self.launch_game(game_id) ) self.image_game_preview[game_id] = Sprite(RESOURCES.IMG[game_id], height=self.height) self.buttons_game_dict[game_id] = button self.buttons_game_launch.add_multiple(self.buttons_game_dict.values()) self.game_id = None self.game_launched_processes = GameProcessList() self.settings_section = SettingsWindow(self) self.updater_window = UpdaterWindow(self, self.launcher_updater) self.side_board = SideBoard(self) self.side_board.add_option("Settings", self.settings_section.mainloop) if psutil.WINDOWS: self.side_board.add_option("Update", lambda: self.updater_window.start(install=True)) self.button_settings = SettingsButton(self, size=40, callback=self.side_board.mainloop) self.button_settings.force_use_highlight_thickness(True) self.transition = GameLaunchTransition()
def __init__(self): MainWindow.__init__(self, title=f"4 in a row - v{__version__}", size=(1280, 720), bg_color=BACKGROUND_COLOR, resources=RESOURCES, config=WINDOW_CONFIG_FILE) self.logo = Image(RESOURCES.IMG["logo"]) Text.set_default_theme("default") Text.set_theme( "default", { "font": RESOURCES.font("heavy", 45), "color": YELLOW, "shadow": True, "shadow_x": 3, "shadow_y": 3 }) Text.set_theme("form", { "font": RESOURCES.font("heavy", 35), }) Button.set_default_theme("default") Button.set_theme( "default", { "fg": YELLOW, "disabled_fg": WHITE, "shadow": True, "shadow_x": 3, "shadow_y": 3, "bg": BLUE, "hover_bg": (0, 175, 255), "active_bg": BLUE, "outline": 0, "highlight_color": WHITE, "highlight_thickness": 1, "border_bottom_left_radius": 45, "border_top_right_radius": 45, "x_add_size": 150, "offset": (0, -5), "hover_offset": (-10, 0), "active_offset": (0, 10), }) Button.set_theme("title", { "font": RESOURCES.font("heavy", 70), "y_add_size": -50 }) Button.set_theme("option", { "font": RESOURCES.font("heavy", 40), "y_add_size": -20 }) Button.set_theme("section", { "bg": BLUE_DARK, "active_bg": BLUE_DARK, "disabled_bg": GRAY_LIGHT }) Entry.set_default_theme("default") Entry.set_theme( "default", { "width": 12, "font": RESOURCES.font("afterglow", 25), "highlight_color": BLACK, "highlight_thickness": 3 }) gameplay = FourInARowGameplay(self) ai_level_selector = AILevelSelectorSection(self, gameplay) local_playing = LocalPlayingSection(self, gameplay) lan_playing_server = LANPlayingP1(self, gameplay) lan_playing_client = LANPlayingP2(self, gameplay) self.buttons = ButtonListVertical(offset=80, justify="right") self.buttons.add( Button(self, "Play against AI", theme="title", callback=ai_level_selector.mainloop), Button(self, "Multiplayer", theme="title", callback=local_playing.mainloop), Button(self, "Play as P1 (LAN)", theme="title", callback=lan_playing_server.mainloop), Button(self, "Play as P2 (LAN)", theme="title", callback=lan_playing_client.mainloop), Button(self, "Quit", theme="title", callback=self.stop), )
def __init__(self, master: Window): Window.__init__(self, master=master, bg_music=master.bg_music) self.frame = RectangleShape(0.60 * self.width, 0.60 * self.height, GREEN, outline=3) self.title = Text("Options", font=(RESOURCES.FONT["algerian"], 70)) self.options_font = (RESOURCES.FONT["algerian"], 40) self.case_font = (RESOURCES.FONT["algerian"], 30) self.control_font = ("calibri", 20) params_for_all_scales = { "width": 0.45 * self.frame.w, "color": TRANSPARENT, "scale_color": GREEN_DARK, "from_": 0, "to": 100, "outline": 3, } params_for_all_buttons = { "highlight_color": YELLOW, "hover_sound": RESOURCES.SFX["select"], "disabled_sound": RESOURCES.SFX["block"] } params_for_option_buttons = { "on_click_sound": RESOURCES.SFX["validate"] } params_for_buttons = { "bg": GRAY_DARK, "fg": WHITE, "hover_bg": GRAY, "active_bg": BLACK } params_for_reset_button = { "bg": RED, "fg": WHITE, "hover_bg": RED_LIGHT, "active_bg": RED_DARK, } self.button_back = ImageButton(self, img=RESOURCES.IMG["blue_arrow"], on_click_sound=RESOURCES.SFX["back"], callback=self.stop, **params_for_all_buttons) self.button_change_page = Button(self, ">>", font=self.case_font, callback=self.change_page, **params_for_all_buttons, **params_for_option_buttons, **params_for_buttons) self.nb_pages = 2 self.page = 1 ## PAGE 1 ## valid_img = Image(RESOURCES.IMG["green_valid"]) self.text_music = Text("Music:", self.options_font) self.cb_music = CheckBox(self, 30, 30, TRANSPARENT, image=valid_img, value=self.get_music_state(), callback=self.set_music_state, **params_for_all_buttons, **params_for_option_buttons) self.scale_music = Scale( self, **params_for_all_scales, **params_for_all_buttons, height=self.cb_music.height, default=Window.music_volume() * 100, callback=lambda value, percent: Window.set_music_volume(percent)) self.text_sound = Text("SFX:", self.options_font) self.cb_sound = CheckBox(self, 30, 30, TRANSPARENT, image=valid_img, value=self.get_sound_state(), callback=self.set_sound_state, **params_for_all_buttons, **params_for_option_buttons) self.scale_sound = Scale( self, **params_for_all_scales, **params_for_all_buttons, height=self.cb_sound.height, default=Window.sound_volume() * 100, callback=lambda value, percent: Window.set_sound_volume(percent)) self.text_fps = Text("FPS:", self.options_font) self.cb_show_fps = CheckBox(self, 30, 30, TRANSPARENT, image=valid_img, value=Window.fps_is_shown(), callback=self.show_fps, **params_for_all_buttons, **params_for_option_buttons) self.button_reset = Button(self, "Reset Save", font=(RESOURCES.FONT["algerian"], 30), callback=SAVE.reset, state=Button.DISABLED, **params_for_all_buttons, **params_for_option_buttons, **params_for_reset_button) ## PAGE 2 ## self.text_acceleration = Text("Accélérer:", self.options_font) self.button_auto_acceleration = Button( self, font=self.case_font, callback=lambda: SAVE.update(auto_acceleration=not SAVE[ "auto_acceleration"]), **params_for_all_buttons, **params_for_option_buttons, **params_for_buttons) self.button_acceleration = Button( self, font=self.control_font, callback=lambda: self.choose_key("speed_up"), **params_for_all_buttons, **params_for_option_buttons, **params_for_buttons) self.text_brake = Text("Freiner:", self.options_font) self.button_brake = Button(self, font=self.control_font, callback=lambda: self.choose_key("brake"), **params_for_all_buttons, **params_for_option_buttons, **params_for_buttons) self.text_move_up = Text("Aller en haut:", self.options_font) self.button_move_up = Button(self, font=self.control_font, callback=lambda: self.choose_key("up"), **params_for_all_buttons, **params_for_option_buttons, **params_for_buttons) self.text_move_down = Text("Aller en bas:", self.options_font) self.button_move_down = Button( self, font=self.control_font, callback=lambda: self.choose_key("down"), **params_for_all_buttons, **params_for_option_buttons, **params_for_buttons) self.bind_key(pygame.K_ESCAPE, lambda event: self.stop(sound=RESOURCES.SFX["back"])) self.bind_joystick( 0, "B", lambda event: self.stop(sound=RESOURCES.SFX["back"]))