def start(self, screen): width = screen.get_width() height = screen.get_height() if not self.already_loaded: self.header = Label(pygame.rect.Rect(width / 2 - 200, 10, 400, 30), "Delete an account", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) self.confirm_text = Label(pygame.rect.Rect(width / 2 - 200, height / 2 - 50, 400, 30), "", options={ Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0 }) self.yes_btn = Button(pygame.rect.Rect(width / 2 - 200, height / 2 + 50, 50, 40), "Yes", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.BORDER_WIDTH: 0, }) self.no_btn = Button(pygame.rect.Rect(width / 2 + 150, height / 2 + 50, 50, 40), "No", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.BORDER_WIDTH: 0, }) self.already_loaded = True self.confirm_text.text = f"Are you sure you want to delete account {Account.account_to_delete.name}?" self.confirm_text.recreate()
def start(self, screen): if self.already_loaded: return # Spawn a new thread to load all resources Thread(target=self.load_assets).start() width = screen.get_width() height = screen.get_height() # Meanwhile create a label to show that the game is loading text_rect = pygame.rect.Rect(width / 2 - 100, height / 2 - 25, 200, 50) self.loading_text = Label(text_rect, "Loading...", { Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) # Also create an image to display a rotate animation image_rect = pygame.rect.Rect(width / 2 - 50, height / 2 + 50, 75, 75) self.loading_circle = Image(image_rect, None, { Options.BACKGROUND: (82, 173, 200) }) self.already_loaded = True
def start(self, screen): if not self.already_loaded: self.width, self.height = screen.get_width(), screen.get_height() self.turn_text = Label( pygame.Rect(10, 10, 100, 30), "", { Options.BACKGROUND: (0, 51, 102), Options.FOREGROUND: (255, 255, 255), Options.BORDER_WIDTH: 0, }) self.victory_text = Label( pygame.Rect(self.width / 2 - 100, self.height / 2 - 30, 200, 60), "", { Options.FONT: pygame.font.SysFont("Comic Sans MS", 25), Options.BACKGROUND: (0, 51, 102), Options.FOREGROUND: (255, 255, 255), Options.BORDER_WIDTH: 0, }) self.reset_game_data() self.already_loaded = True if GameScene.game_over: self.reset_game_data()
class DeleteAccountScene(Scene): header = None confirm_text = None yes_btn = None no_btn = None # Create the various gui elements def start(self, screen): width = screen.get_width() height = screen.get_height() if not self.already_loaded: self.header = Label(pygame.rect.Rect(width / 2 - 200, 10, 400, 30), "Delete an account", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) self.confirm_text = Label(pygame.rect.Rect(width / 2 - 200, height / 2 - 50, 400, 30), "", options={ Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0 }) self.yes_btn = Button(pygame.rect.Rect(width / 2 - 200, height / 2 + 50, 50, 40), "Yes", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.BORDER_WIDTH: 0, }) self.no_btn = Button(pygame.rect.Rect(width / 2 + 150, height / 2 + 50, 50, 40), "No", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.BORDER_WIDTH: 0, }) self.already_loaded = True self.confirm_text.text = f"Are you sure you want to delete account {Account.account_to_delete.name}?" self.confirm_text.recreate() def update(self, event): for elt in (self.yes_btn, self.no_btn): elt.update(event) if self.yes_btn.clicked: Account.delete_account(Account.account_to_delete) Account.account_to_delete = None Scene.push_scene(1) if self.no_btn.clicked: Scene.push_scene(1) # Clear the screen and draw the gui def draw(self, screen): screen.fill((82, 173, 200)) for elt in (self.header, self.confirm_text, self.yes_btn, self.no_btn): elt.draw(screen)
def start(self, screen): width = screen.get_width() height = screen.get_height() if not self.already_loaded: StatsScene.create_metrics() self.header = Label(pygame.rect.Rect(width / 2 - 200, 10, 400, 30), "Statistics", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) self.first_offset = pygame.rect.Rect(width / 2 - 125, 75, 250, 30) label_options = { Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0 } for metric in StatsScene.all_metrics.keys(): text = f"{metric}: {StatsScene.all_metrics[metric](Account.current_account)}" stat_lbl = Label(pygame.rect.Rect(0, 0, 0, 0), text, label_options) self.statistics.append(stat_lbl) btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) } self.back_btn = Button(pygame.rect.Rect(10, 10, 60, 40), "Back", btn_options) self.up_btn = Button( pygame.rect.Rect(width * 5 / 6, height * 2 / 6, 60, 40), "Up", btn_options) self.down_btn = Button( pygame.rect.Rect(width * 5 / 6, height * 4 / 6 - 40, 60, 40), "Down", btn_options) self.already_loaded = True self.stat_index = 0 self.reposition_stats()
def start(self, screen): if not self.already_loaded: self.back_btn = Button( pygame.rect.Rect(10, 10, 60, 40), "Back", { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) }) about_text = "This game was made by Ritobroto Mukherjee and\n" \ "Shivam Gupta (who has done absolutely nothing yet)\n" \ "as practice for collaboration." y_offset = 0 for line in about_text.splitlines(): self.about_labels.append( Label( pygame.rect.Rect(10, 200 + y_offset * 30, screen.get_width() - 10, 30), line, { Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0 })) y_offset += 1 self.already_loaded = True
def start(self, screen): width = screen.get_width() height = screen.get_height() if self.already_loaded: self.name_box.set_text("") else: self.header = Label(pygame.rect.Rect(width / 2 - 200, 10, 400, 30), "Add new account", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) self.name_box = Textbox(pygame.rect.Rect(width/2 - 200, height/2 - 50, 400, 30), "", options={ Options.BORDER_WIDTH: 0, }) self.create_btn = Button(pygame.rect.Rect(width / 2 - 100, height / 2 + 50, 200, 30), "Create", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.BORDER_WIDTH: 0, }) self.back_btn = Button(pygame.rect.Rect(10, 10, 60, 40), "Back", { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) }) self.already_loaded = True
def start(self, screen): width = screen.get_width() height = screen.get_height() if not self.already_loaded: self.confirm_text = Label( pygame.rect.Rect(width / 2 - 200, height / 2 - 50, 400, 30), "Are you sure you want to forfeit the match?", { Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0 }) self.yes_btn = Button(pygame.rect.Rect(width / 2 - 100, height / 2 + 50, 50, 40), "Yes", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.BORDER_WIDTH: 0, }) self.no_btn = Button(pygame.rect.Rect(width / 2 + 50, height / 2 + 50, 50, 40), "No", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.BORDER_WIDTH: 0, }) self.underlay_screen = screen.copy() self.already_loaded = True
def __init__(self, parent='osd', text=None, search=None, handler=None, left=None, top=None, width=600, height=200, bg_color=None, fg_color=None, icon=None, border=None, bd_color=None, bd_width=None, vertical_expansion=1): if not text: text = _('Program Search') PopupBox.__init__(self, text, handler, left, top, width, height, icon, vertical_expansion, parent=parent) (self.server_available, msg) = record_client.connectionTest() if not self.server_available: errormsg = Label(_('Recording server is unavailable.') + \ ( ': %s\n\n' % msg ) + \ _('Feel free to implement this function inside the main guide.'), self, Align.CENTER) return self.internal_h_align = Align.CENTER self.lbg = LetterBoxGroup(text=search) self.add_child(self.lbg) items_height = Button('foo').height self.num_shown_items = 8 self.results = ListBox(width=(self.width - 2 * self.h_margin), height=self.num_shown_items * items_height, show_v_scrollbar=0) self.results.y_scroll_interval = self.results.items_height = items_height max_results = 10 self.results.set_h_align(Align.CENTER) self.add_child(self.results) if search: self.searchProg(search) self.center_on_screen = TRUE
def recreate_victory_texts(self, w, h): coins = GameOverScene.result.coins text = f"You won the match! Received {coins} coins." if GameOverScene.result.state == GameResult.VictoryState.WIN else \ "You lost the match!" if GameOverScene.result.state == GameResult.VictoryState.LOSE else \ f"The match was a tie! Received {coins} coins." self.win_state_text = Label( pygame.rect.Rect(w / 2 - 300, 175, 600, 30), text, { Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0, })
def start(self, screen): if not self.already_loaded: width = screen.get_width() height = screen.get_height() self.header = Label(pygame.Rect(width / 2 - 75, height * 1 / 5 + 10, 150, 50), "Game Paused", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) self.back_btn = Button( pygame.Rect(width * 1 / 5 + 10, height * 1 / 5 + 10, 60, 40), "Back", { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) }) self.forfeit_btn = Button( pygame.Rect(width / 2 - 75, height / 2, 150, 40), "Forfeit", { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 25) }) settings_gear_image = Resources.get("gear") settings_gear_rect = pygame.rect.Rect(width * 4 / 5 - 100, height * 4 / 5 - 100, 75, 75) self.settings_btn = Image( settings_gear_rect, settings_gear_image, { Options.BACKGROUND: (20, 61, 89), Options.HOVERED_BACKGROUND: (10, 30, 45) }) self.already_loaded = True if self.last_scene_id != Scene.scene_stack[-2]: self.last_scene_id = Scene.scene_stack[-2] self.underlay_screen = screen.copy() dark_cover = pygame.Surface( self.underlay_screen.get_size()).convert_alpha( self.underlay_screen) dark_cover.fill((0, 0, 0, 0.6 * 255)) self.underlay_screen.blit(dark_cover, (0, 0))
def start(self, screen): if not self.already_loaded: self.back_btn = Button( pygame.rect.Rect(10, 10, 60, 40), "Back", { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) }) text_options = { Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0 } about_text = [ "This game was made by Ritobroto Mukherjee and", "Shivam Gupta (who has done absolutely nothing)", "as practice for collaboration on a group project." ] y_offset = 0 for line in about_text: lbl = Label( pygame.Rect(10, 300 + y_offset * 30, screen.get_width() - 10, 30), line, text_options) self.about_labels.append(lbl) y_offset += 1 version_text = "PenFight v1.0" self.version_label = Label( pygame.Rect(screen.get_width() / 2 - 25, screen.get_height() - 50, 50, 30), version_text, text_options) self.already_loaded = True
def start(self, screen): if not self.already_loaded: width = screen.get_width() height = screen.get_height() self.header = Label(pygame.rect.Rect(width / 2 - 50, 10, 150, 50), "Settings", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) self.back_btn = Button( pygame.rect.Rect(10, 10, 60, 40), "Back", { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) }) label_options = { Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0 } self.volume_value = Account.current_account.settings.get( Settings.VOLUME) self.volume_label = Label( pygame.rect.Rect(width * 2 / 5, height * 2 / 5, 100, 30), "Volume", label_options) self.volume_box = Textbox( pygame.rect.Rect(width * 3 / 5, height * 2 / 5, 100, 30), str(self.volume_value)) self.already_loaded = True
def start(self, screen): width, height = screen.get_width(), screen.get_height() if not self.already_loaded: self.title = Label(pygame.rect.Rect(width / 2 - 200, 10, 400, 30), "Game Over", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 20), } btn_rect = pygame.rect.Rect(width / 2 - 125, height * 3 / 5 - 50, 250, 30) self.replay_btn = Button(btn_rect, "Play again", btn_options) self.main_menu_btn = Button(btn_rect.copy().move(0, 75), "Go to main menu", btn_options) self.already_loaded = True self.recreate_victory_texts(width, height) Account.current_account.reward_money(GameOverScene.result.coins) if GameOverScene.result.state == GameResult.VictoryState.WIN: Account.current_account.add_win() elif GameOverScene.result.state == GameResult.VictoryState.LOSE: Account.current_account.add_loss()
class MainMenuScene(Scene): title = None play_btn = None stats_btn = None about_btn = None settings_btn = None back_btn = None close_btn = None # Create the various gui elements def start(self, screen): if self.already_loaded: return width = screen.get_width() height = screen.get_height() self.title = Label(pygame.rect.Rect(width / 2 - 200, height / 7, 400, 60), "Python Penfight!", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 4, Options.FONT: pygame.font.SysFont("Comic Sans MS", 40, bold=True, italic=False) }) btn_rect = pygame.rect.Rect(width / 2 - 125, height / 2 - 50, 250, 30) btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 25), } self.play_btn = Button(btn_rect, "Play", btn_options) self.stats_btn = Button(btn_rect.copy().move(0, 75), "Stats", btn_options) self.about_btn = Button(btn_rect.copy().move(0, 150), "About", btn_options) settings_gear_image = Resources.get("gear") settings_gear_rect = pygame.rect.Rect(width - 100, height - 100, 75, 75) self.settings_btn = Image( settings_gear_rect, settings_gear_image, { Options.BACKGROUND: (20, 61, 89), Options.HOVERED_BACKGROUND: (10, 30, 45) }) close_image = Resources.get("close") close_rect = pygame.rect.Rect(width - 75, 25, 50, 50) self.close_btn = Image( close_rect, close_image, { Options.BACKGROUND: (200, 0, 0), Options.HOVERED_BACKGROUND: (100, 0, 0) }) self.back_btn = Button( pygame.rect.Rect(10, 10, 60, 40), "Back", { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) }) self.already_loaded = True # Check the buttons and switch to corresponding scenes when clicked def update(self, event): for btn in (self.play_btn, self.stats_btn, self.about_btn, self.back_btn, self.close_btn, self.settings_btn): btn.update(event) # Goto single player pen select scene if self.play_btn.clicked: Scene.push_scene(5) # Goto the stats scene elif self.stats_btn.clicked: Scene.push_scene(11) # Goto the about scene elif self.about_btn.clicked: Scene.push_scene(12) # Go to the settings pane elif self.settings_btn.clicked: Scene.push_scene(13) # Close the app elif self.close_btn.clicked: pygame.event.post(pygame.event.Event(pygame.QUIT)) # Go back to account select scene elif self.back_btn.clicked: Account.save_to_file(Account.current_account) Scene.pop_scene() # Clear the screen and draw the gui def draw(self, screen): screen.fill((82, 173, 200)) self.title.draw(screen) for btn in (self.play_btn, self.stats_btn, self.about_btn, self.back_btn, self.close_btn, self.settings_btn): btn.draw(screen)
def start(self, screen): if self.already_loaded: return width = screen.get_width() height = screen.get_height() self.title = Label(pygame.rect.Rect(width / 2 - 200, height / 7, 400, 60), "Python Penfight!", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 4, Options.FONT: pygame.font.SysFont("Comic Sans MS", 40, bold=True, italic=False) }) btn_rect = pygame.rect.Rect(width / 2 - 125, height / 2 - 50, 250, 30) btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 25), } self.play_btn = Button(btn_rect, "Play", btn_options) self.stats_btn = Button(btn_rect.copy().move(0, 75), "Stats", btn_options) self.about_btn = Button(btn_rect.copy().move(0, 150), "About", btn_options) settings_gear_image = Resources.get("gear") settings_gear_rect = pygame.rect.Rect(width - 100, height - 100, 75, 75) self.settings_btn = Image( settings_gear_rect, settings_gear_image, { Options.BACKGROUND: (20, 61, 89), Options.HOVERED_BACKGROUND: (10, 30, 45) }) close_image = Resources.get("close") close_rect = pygame.rect.Rect(width - 75, 25, 50, 50) self.close_btn = Image( close_rect, close_image, { Options.BACKGROUND: (200, 0, 0), Options.HOVERED_BACKGROUND: (100, 0, 0) }) self.back_btn = Button( pygame.rect.Rect(10, 10, 60, 40), "Back", { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) }) self.already_loaded = True
class SelectAccountScene(Scene): header = None no_account_text = None close_btn = None account_btns = [] visible_acc_btns = [] delete_btns = {} up_btn, down_btn = None, None create_btn = None btn_index = 0 first_offset = None # Create the various gui elements def start(self, screen): width = screen.get_width() height = screen.get_height() if self.already_loaded: btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), } del_btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (200, 20, 40), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (150, 5, 20), } original_names = [btn.text for btn in self.account_btns] account_names = Account.get_account_names() for name in original_names: if name not in account_names: btn_to_delete = self.account_btns[[ idx for idx, btn in enumerate(self.account_btns) if btn.text == name ][0]] self.account_btns.remove(btn_to_delete) self.delete_btns.pop(btn_to_delete) for name in account_names: if name not in original_names: btn = Button(pygame.rect.Rect(0, 0, 0, 0), name, btn_options) self.account_btns.append(btn) del_btn = Button(pygame.rect.Rect(0, 0, 30, 30), "X", del_btn_options) self.delete_btns[btn] = del_btn self.account_btns.sort(key=(lambda btn: btn.text)) else: self.header = Label(pygame.rect.Rect(width / 2 - 200, 10, 400, 30), "Select account to load", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) close_image = Resources.get("close") close_rect = pygame.rect.Rect(width - 75, 25, 50, 50) self.close_btn = Image( close_rect, close_image, { Options.BACKGROUND: (200, 0, 0), Options.HOVERED_BACKGROUND: (100, 0, 0) }) self.no_account_text = Label( pygame.rect.Rect(width / 2 - 350, height / 2, 550, 30), "No account created. Click the New button to make one.", options={ Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0, }) self.first_offset = pygame.rect.Rect(width / 2 - 125, 75, 250, 30) btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), } del_btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (200, 20, 40), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (150, 5, 20), } account_names = Account.get_account_names() for name in account_names: btn = Button(pygame.rect.Rect(0, 0, 0, 0), name, btn_options) self.account_btns.append(btn) del_btn = Button(pygame.rect.Rect(0, 0, 30, 30), "X", del_btn_options) self.delete_btns[btn] = del_btn btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) } self.up_btn = Button( pygame.rect.Rect(width * 5 / 6, height * 2 / 6, 60, 40), "Up", btn_options) self.create_btn = Button( pygame.rect.Rect(width * 5 / 6, height * 3 / 6 - 20, 60, 40), "New", btn_options) self.down_btn = Button( pygame.rect.Rect(width * 5 / 6, height * 4 / 6 - 40, 60, 40), "Down", btn_options) self.already_loaded = True Account.current_account = None self.btn_index = 0 self.reposition_buttons() # Check the buttons and switch to corresponding scenes when clicked def update(self, event): for btn in self.visible_acc_btns: btn.update(event) if btn.clicked: Account.current_account = Account.load_from_file(btn.text) Scene.push_scene(4) self.delete_btns[btn].update(event) if self.delete_btns[btn].clicked: Account.account_to_delete = Account.load_from_file(btn.text) Scene.push_scene(3) for btn in (self.create_btn, self.up_btn, self.down_btn, self.close_btn): btn.update(event) if self.create_btn.clicked: Scene.push_scene(2) elif self.close_btn.clicked: pygame.event.post(pygame.event.Event(pygame.QUIT)) elif self.up_btn.clicked: self.btn_index -= 1 self.reposition_buttons() elif self.down_btn.clicked: self.btn_index += 1 self.reposition_buttons() def reposition_buttons(self): self.visible_acc_btns.clear() offset = 0 for btn in self.account_btns[self.btn_index:self.btn_index + 10]: btn.rect = self.first_offset.copy().move(0, offset) btn.recreate() self.visible_acc_btns.append(btn) offset += 50 self.delete_btns[btn].rect.top = btn.rect.top self.delete_btns[btn].rect.left = btn.rect.right + 10 self.delete_btns[btn].recreate() self.up_btn.set_enabled(self.btn_index > 0) self.down_btn.set_enabled(self.btn_index < len(self.account_btns) - 1) @staticmethod def near_mouse(point, max_dist): mouse_pos = pygame.mouse.get_pos() distance = ((point[0] - mouse_pos[0])**2) + ( (point[1] - mouse_pos[1])**2) return distance < (max_dist**2) # Clear the screen and draw the gui def draw(self, screen): screen.fill((82, 173, 200)) for elt in (self.header, self.close_btn): elt.draw(screen) if len(self.account_btns) == 0: self.no_account_text.draw(screen) else: for btn in self.visible_acc_btns: btn.draw(screen) if self.near_mouse(self.delete_btns[btn].rect.center, 25): self.delete_btns[btn].draw(screen) width, height = screen.get_width(), screen.get_height() scroll_rect = pygame.Rect(width * 5 / 6 + 100, height * 1 / 6, 10, height * 4 / 6) pygame.draw.rect(screen, (100, 100, 100), scroll_rect) height_diff = (height * 4 / 6) / len(self.account_btns) scroll_rect.top = height * 1 / 6 + height_diff * self.btn_index scroll_rect.height = height_diff pygame.draw.rect(screen, (50, 50, 50), scroll_rect) for btn in (self.create_btn, self.up_btn, self.down_btn): btn.draw(screen)
def start(self, screen): width = screen.get_width() height = screen.get_height() if self.already_loaded: btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), } del_btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (200, 20, 40), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (150, 5, 20), } original_names = [btn.text for btn in self.account_btns] account_names = Account.get_account_names() for name in original_names: if name not in account_names: btn_to_delete = self.account_btns[[ idx for idx, btn in enumerate(self.account_btns) if btn.text == name ][0]] self.account_btns.remove(btn_to_delete) self.delete_btns.pop(btn_to_delete) for name in account_names: if name not in original_names: btn = Button(pygame.rect.Rect(0, 0, 0, 0), name, btn_options) self.account_btns.append(btn) del_btn = Button(pygame.rect.Rect(0, 0, 30, 30), "X", del_btn_options) self.delete_btns[btn] = del_btn self.account_btns.sort(key=(lambda btn: btn.text)) else: self.header = Label(pygame.rect.Rect(width / 2 - 200, 10, 400, 30), "Select account to load", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) close_image = Resources.get("close") close_rect = pygame.rect.Rect(width - 75, 25, 50, 50) self.close_btn = Image( close_rect, close_image, { Options.BACKGROUND: (200, 0, 0), Options.HOVERED_BACKGROUND: (100, 0, 0) }) self.no_account_text = Label( pygame.rect.Rect(width / 2 - 350, height / 2, 550, 30), "No account created. Click the New button to make one.", options={ Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0, }) self.first_offset = pygame.rect.Rect(width / 2 - 125, 75, 250, 30) btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), } del_btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (200, 20, 40), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (150, 5, 20), } account_names = Account.get_account_names() for name in account_names: btn = Button(pygame.rect.Rect(0, 0, 0, 0), name, btn_options) self.account_btns.append(btn) del_btn = Button(pygame.rect.Rect(0, 0, 30, 30), "X", del_btn_options) self.delete_btns[btn] = del_btn btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) } self.up_btn = Button( pygame.rect.Rect(width * 5 / 6, height * 2 / 6, 60, 40), "Up", btn_options) self.create_btn = Button( pygame.rect.Rect(width * 5 / 6, height * 3 / 6 - 20, 60, 40), "New", btn_options) self.down_btn = Button( pygame.rect.Rect(width * 5 / 6, height * 4 / 6 - 40, 60, 40), "Down", btn_options) self.already_loaded = True Account.current_account = None self.btn_index = 0 self.reposition_buttons()
def __init__(self, parent=None, subject=None, left=None, top=None, width=500, height=350, context=None): self.oldname = None if context: self.context = context else: context = 'guide' if isinstance(subject, TvProgram): (result, favs) = record_client.getFavorites() if result: num_favorites = len(favs) self.priority = num_favorites + 1 else: self.priority = 1 self.fav = Favorite(subject.title, subject, TRUE, TRUE, TRUE, self.priority, TRUE, FALSE) else: self.fav = subject self.oldname = self.fav.name PopupBox.__init__(self, text=_('Edit Favorite'), x=left, y=top, width=width, height=height) self.v_spacing = 15 self.h_margin = 20 self.v_margin = 20 self.internal_h_align = Align.LEFT if not self.left: self.left = self.osd.width / 2 - self.width / 2 if not self.top: self.top = self.osd.height / 2 - self.height / 2 guide = epg_xmltv.get_guide() name = Label(_('Name') + ':', self, Align.LEFT) self.name_input = LetterBoxGroup(text=self.fav.name) self.name_input.h_align = Align.NONE self.add_child(self.name_input) title = Label(_('Title') + ': %s' % self.fav.title, self, Align.LEFT) chan = Label(_('Channel') + ':', self, Align.LEFT) self.chan_box = OptionBox('ANY') self.chan_box.h_align = Align.NONE self.chan_box.add_item(text=_('ANY'), value='ANY') i = 1 chan_index = 0 for ch in guide.chan_list: #if ch.id == self.fav.channel_id: if ch.displayname == self.fav.channel: chan_index = i i += 1 self.chan_box.add_item(text=ch.displayname, value=ch.displayname) self.chan_box.toggle_selected_index(chan_index) # This is a hack for setting the OptionBox's label to the current # value. It should be done by OptionBox when drawing, but it doesn't # work :( self.chan_box.change_item(None) self.add_child(self.chan_box) dow = Label(_('Day of Week') + ':', self, Align.LEFT) self.dow_box = OptionBox('ANY DAY') self.dow_box.h_align = Align.NONE self.dow_box.add_item(text=_('ANY DAY'), value='ANY') i = 1 dow_index = 0 for dow in (_('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri'), _('Sat'), _('Sun')): val = "%d" % (i - 1) self.dow_box.add_item(text=_(dow), value=val) if val == self.fav.dow: dow_index = i i += 1 self.dow_box.toggle_selected_index(dow_index) # This is a hack for setting the OptionBox's label to the current # value. It should be done by OptionBox when drawing, but it doesn't # work :( self.dow_box.change_item(None) self.add_child(self.dow_box) tod = Label(_('Time of Day') + ':', self, Align.LEFT) self.tod_box = OptionBox('ANY') self.tod_box.h_align = Align.NONE self.tod_box.add_item(text=_('ANY TIME'), value='ANY') i = 0 tod_index = 0 for h in range(0, 24): for m in (00, 30): val = i * 30 # Little hack: we calculate the hours from Jan 1st, 1970 GMT, # and then use strftime to get the string representation text = strftime(config.TV_TIMEFORMAT, gmtime(h * 3600 + 60 * m)) self.tod_box.add_item(text=text, value=val) if val == self.fav.mod: tod_index = i + 1 i += 1 self.tod_box.toggle_selected_index(tod_index) # This is a hack for setting the OptionBox's label to the current # value. It should be done by OptionBox when drawing, but it doesn't # work :( self.tod_box.change_item(None) self.add_child(self.tod_box) self.save = Button(_('Save')) self.add_child(self.save) if self.oldname: self.remove = Button(_('Remove')) self.add_child(self.remove) else: self.remove = None self.cancel = Button(_('CANCEL')) self.add_child(self.cancel)
def __init__(self, C, router_address: tuple, log: dict, bounds: tuple): self.router_address = router_address self.model = RouterModel(router_address, log) self.past_free_index = 0 # exibir sinais no instante X # Prepara as coordenadas # self.bounds = bounds x1, y1, x2, y2 = bounds local_w = x2 - x1 local_h = y2 - y1 caixa_w = x2 - x1 - 76 caixa_h = y2 - y1 - 76 #instancia os vetores self.portas = list() self.portas.insert(stds.IN_ACK, []) self.portas.insert(stds.IN_NACK, []) self.portas.insert(stds.OUT_REQ, []) self.portas.insert(stds.IN_REQ, []) self.portas.insert(stds.OUT_NACK, []) self.portas.insert(stds.OUT_ACK, []) self.sinais = dict() self.sinais.update({ 'fsm1': Label(C, (x1 + 50, y1 + 38 + caixa_h * .2), "", pre_text="in {}", font_size=7, bold=True, pos='nw') }) self.sinais.update({ 'fsm2': Label(C, (x1 + 50, y2 - 38 - caixa_h * .4), "", pre_text="out {}", font_size=7, bold=True, pos='nw') }) self.sinais['fsm1'].draw() self.sinais['fsm2'].draw() c1 = x1 + 38 c2 = x1 + 38 + caixa_w / 8 c3 = x1 + 38 + caixa_w / 2.3 c4 = x1 + 38 + caixa_w / 1.4 l1 = y1 + 38 + caixa_h * .3 Label( C, (c1, l1), "L", ).draw(state="normal") Label(C, (c2, l1), "Src").draw(state="normal") Label(C, (c3, l1), "Tgt").draw(state="normal") Label(C, (c4, l1), "PayL").draw(state="normal") l2 = y1 + 38 + caixa_h * .4 self.sinais.update({'writed': Label(C, (c1, l2), "")}) self.sinais.update({'in_source': Label(C, (c2, l2), "")}) self.sinais.update({'in_target': Label(C, (c3, l2), "")}) self.sinais.update({'in_payload': Label(C, (c4, l2), "")}) l2_5 = y1 + 38 + caixa_h * .5 self.sinais.update({ 'in_service': Label(C, (x1 + local_w / 2, l2_5), "", pos='n', font_size=7) }) # self.sinais.update( {'in_service.' : Label(C,(c1,l2_5),"")} ) l3 = y2 - 38 - caixa_h * .3 Label( C, (c1, l3), "L", ).draw(state="normal") Label(C, (c2, l3), "Src").draw(state="normal") Label(C, (c3, l3), "Tgt").draw(state="normal") Label(C, (c4, l3), "PayL").draw(state="normal") l4 = y2 - 38 - caixa_h * .2 self.sinais.update({'sel': Label(C, (c1, l4), "")}) self.sinais.update({'out_source': Label(C, (c2, l4), "")}) self.sinais.update({'out_target': Label(C, (c3, l4), "")}) self.sinais.update({'out_payload': Label(C, (c4, l4), "")}) l4_5 = y2 - 38 - caixa_h * .1 self.sinais.update({ 'out_service': Label(C, (x1 + local_w / 2, l4_5), "", pos='n', font_size=7) }) # self.sinais.update( {'out_service.' : Label(C,(c1,l4_5),"")} ) self.label_id = Label(C, (x2 - 32, y1 + 38), *router_address, font_size=10, pre_text="{} x {}", pos='e') self.label_id.draw() self.label_id.update(*router_address) # self.sinais.update( {'sel' : Label(C,(x2-32,y1+50),"",pre_text="sel: {}",font_size=8,bold=False,pos='e')} ) self.sinais.update({ 'sel_port': Label(C, (x2 - 32, y1 + 47), "", pre_text="sel_port: {}", font_size=8, bold=False, pos='e') }) self.sinais.update({ 'free_index': Label(C, (x2 - 32, y1 + 57), "", pre_text="free index:{}", font_size=8, bold=False, pos='e') }) self.sinais['sel'].draw() self.sinais['sel_port'].draw() # self.sinais.update( {'sel' : Label(C,(x2-32,y1+50),"",pre_text="sel: {}",font_size=8,bold=False,pos='e')} ) self.sinais.update({ 'sec_zone_ID': Label(C, (x2 - 70, y1 + 38), "", "", pre_text="sz:{},{}", font_size=5, bold=False, pos='e') }) self.sinais['sec_zone_ID'].draw() self.wrapper = list() self.wrapper.insert( stds.EAST, Box(C, (x2 - 33, y1 + 3 * local_h / 7.4), (5, local_h / 4))) self.wrapper.insert( stds.WEST, Box(C, (x1 + 28, y1 + 3 * local_h / 7.4), (5, local_w / 4))) self.wrapper.insert( stds.NORTH, Box(C, (x1 + 3 * local_w / 7.4, y1 + 28), (local_w / 4, 5))) self.wrapper.insert( stds.SOUTH, Box(C, (x1 + 3 * local_w / 7.4, y2 - 33), (local_w / 4, 5))) # self.wrapper.insert(stds.LOCAL,Box(C,(x1+28,y1+28),(10,10))) for i in range(0, 4): self.wrapper[i].draw() self.opmode = Box(C, (x1 + 38, y2 - 38 - caixa_h * .4), (10, 10)) self.opmode.draw() # test.update("green") # self.sinais.update # Prepara a localização das portas # OBSERVAÇÃO: Precisa ser feito na ordem certa: # EAST, WEST, NORTH, SOUTH, LOCAL # Desta forma os indices da lista batem na ordem certa # Portas EAST, define posições IN_EAST_ACK = (x2 - 26, y1 + int(local_h * 0.2)) IN_EAST_NACK = (x2 - 26, y1 + int(local_h * 0.25)) OUT_EAST_REQ = (x2 - 26, y1 + int(local_h * 0.4)) IN_EAST_REQ = (x2 - 26, y1 + int(local_h * 0.6)) OUT_EAST_NACK = (x2 - 26, y1 + int(local_h * 0.75)) OUT_EAST_ACK = (x2 - 26, y1 + int(local_h * 0.8)) self.portas[stds.IN_ACK].insert(stds.EAST, ArrowInput(C, IN_EAST_ACK, stds.EAST)) self.portas[stds.IN_NACK].insert( stds.EAST, ArrowInput(C, IN_EAST_NACK, stds.EAST)) self.portas[stds.OUT_REQ].insert( stds.EAST, ArrowOutput(C, OUT_EAST_REQ, stds.EAST)) self.portas[stds.IN_REQ].insert(stds.EAST, ArrowInput(C, IN_EAST_REQ, stds.EAST)) self.portas[stds.OUT_NACK].insert( stds.EAST, ArrowOutput(C, OUT_EAST_NACK, stds.EAST)) self.portas[stds.OUT_ACK].insert( stds.EAST, ArrowOutput(C, OUT_EAST_ACK, stds.EAST)) # Portas WEST OUT_WEST_ACK = (x1, y1 + int(local_h * 0.2)) OUT_WEST_NACK = (x1, y1 + int(local_h * 0.25)) IN_WEST_REQ = (x1, y1 + int(local_h * 0.4)) OUT_WEST_REQ = (x1, y1 + int(local_h * 0.6)) IN_WEST_NACK = (x1, y1 + int(local_h * 0.75)) IN_WEST_ACK = (x1, y1 + int(local_h * 0.8)) self.portas[stds.IN_ACK].insert(stds.WEST, ArrowInput(C, IN_WEST_ACK, stds.WEST)) self.portas[stds.IN_NACK].insert( stds.WEST, ArrowInput(C, IN_WEST_NACK, stds.WEST)) self.portas[stds.OUT_REQ].insert( stds.WEST, ArrowOutput(C, OUT_WEST_REQ, stds.WEST)) self.portas[stds.IN_REQ].insert(stds.WEST, ArrowInput(C, IN_WEST_REQ, stds.WEST)) self.portas[stds.OUT_NACK].insert( stds.WEST, ArrowOutput(C, OUT_WEST_NACK, stds.WEST)) self.portas[stds.OUT_ACK].insert( stds.WEST, ArrowOutput(C, OUT_WEST_ACK, stds.WEST)) # Portas NORTH OUT_NORTH_ACK = (x1 + int(local_w * 0.2), y1) OUT_NORTH_NACK = (x1 + int(local_w * 0.25), y1) IN_NORTH_REQ = (x1 + int(local_w * 0.4), y1) OUT_NORTH_REQ = (x1 + int(local_w * 0.6), y1) IN_NORTH_NACK = (x1 + int(local_w * 0.75), y1) IN_NORTH_ACK = (x1 + int(local_w * 0.8), y1) self.portas[stds.IN_ACK].insert( stds.NORTH, ArrowInput(C, IN_NORTH_ACK, stds.NORTH)) self.portas[stds.IN_NACK].insert( stds.NORTH, ArrowInput(C, IN_NORTH_NACK, stds.NORTH)) self.portas[stds.OUT_REQ].insert( stds.NORTH, ArrowOutput(C, OUT_NORTH_REQ, stds.NORTH)) self.portas[stds.IN_REQ].insert( stds.NORTH, ArrowInput(C, IN_NORTH_REQ, stds.NORTH)) self.portas[stds.OUT_NACK].insert( stds.NORTH, ArrowOutput(C, OUT_NORTH_NACK, stds.NORTH)) self.portas[stds.OUT_ACK].insert( stds.NORTH, ArrowOutput(C, OUT_NORTH_ACK, stds.NORTH)) # # Portas SOUTH IN_SOUTH_ACK = (x1 + int(local_w * 0.2), y2 - 26) IN_SOUTH_NACK = (x1 + int(local_w * 0.25), y2 - 26) OUT_SOUTH_REQ = (x1 + int(local_w * 0.4), y2 - 26) IN_SOUTH_REQ = (x1 + int(local_w * 0.6), y2 - 26) OUT_SOUTH_NACK = (x1 + int(local_w * 0.75), y2 - 26) OUT_SOUTH_ACK = (x1 + int(local_w * 0.8), y2 - 26) self.portas[stds.IN_ACK].insert( stds.SOUTH, ArrowInput(C, IN_SOUTH_ACK, stds.SOUTH)) self.portas[stds.IN_NACK].insert( stds.SOUTH, ArrowInput(C, IN_SOUTH_NACK, stds.SOUTH)) self.portas[stds.OUT_REQ].insert( stds.SOUTH, ArrowOutput(C, OUT_SOUTH_REQ, stds.SOUTH)) self.portas[stds.IN_REQ].insert( stds.SOUTH, ArrowInput(C, IN_SOUTH_REQ, stds.SOUTH)) self.portas[stds.OUT_NACK].insert( stds.SOUTH, ArrowOutput(C, OUT_SOUTH_NACK, stds.SOUTH)) self.portas[stds.OUT_ACK].insert( stds.SOUTH, ArrowOutput(C, OUT_SOUTH_ACK, stds.SOUTH)) # # Portas LOCAL IN_LOCAL_ACK = (x1 + int(local_w * 0.16), y1 + int(local_h * 0.22)) OUT_LOCAL_REQ = (x1 + int(local_w * 0.20), y1 + int(local_h * 0.2)) IN_LOCAL_NACK = (x1 + int(local_w * 0.24), y1 + int(local_h * 0.18)) OUT_LOCAL_ACK = (x1 + int(local_w * 0.32), y1 + int(local_h * 0.22)) IN_LOCAL_REQ = (x1 + int(local_w * 0.36), y1 + int(local_h * 0.2)) OUT_LOCAL_NACK = (x1 + int(local_w * 0.40), y1 + int(local_h * 0.18)) self.portas[stds.IN_ACK].insert( stds.LOCAL, ArrowInput(C, IN_LOCAL_ACK, stds.LOCAL)) self.portas[stds.IN_NACK].insert( stds.LOCAL, ArrowInput(C, IN_LOCAL_NACK, stds.LOCAL)) self.portas[stds.OUT_REQ].insert( stds.LOCAL, ArrowOutput(C, OUT_LOCAL_REQ, stds.LOCAL)) self.portas[stds.IN_REQ].insert( stds.LOCAL, ArrowInput(C, IN_LOCAL_REQ, stds.LOCAL)) self.portas[stds.OUT_NACK].insert( stds.LOCAL, ArrowOutput(C, OUT_LOCAL_NACK, stds.LOCAL)) self.portas[stds.OUT_ACK].insert( stds.LOCAL, ArrowOutput(C, OUT_LOCAL_ACK, stds.LOCAL)) for i in self.sinais.values(): i.draw() self.caixa = Box(C, (x1, y1), (local_w, local_h), color="red", alpha=True, state="hidde") self.caixa.draw()
class EnemySelectScene(Scene): header = None back_btn = None select_btn = None name_text = None random_diff_btn = None easy_btn = None normal_btn = None hard_btn = None difficulty = -1 random_pen_data = None pen_images = [] visible_pen_images = [] left_btn, right_btn = None, None center_pos = None pen_index = 0 def start(self, screen): if not self.already_loaded: PenData.load_all_pens() width = screen.get_width() height = screen.get_height() self.back_btn = Button( pygame.Rect(10, 10, 60, 40), "Back", { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) }) self.header = Label( pygame.Rect(width / 2 - 200, 10, 400, 30), "Choose your opponent!", { Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) self.name_text = Label( pygame.Rect(width / 2 - 45, height - 125, 90, 50), "", { Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0, Options.FONT: pygame.font.SysFont("Comic Sans MS", 18) }) btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 25) } self.left_btn = Button(pygame.Rect(10, height / 2 - 20, 20, 30), "<", btn_options) self.right_btn = Button( pygame.Rect(width - 30, height / 2 - 20, 20, 30), ">", btn_options) self.select_btn = Button( pygame.Rect(width / 2 - 45, height - 75, 90, 50), "Select", btn_options) btn_options[Options.TOGGLED_BACKGROUND] = (5, 20, 30) self.random_diff_btn = ToggleButton( pygame.Rect(width * 1 / 5 - 50, 100, 100, 30), "Random", btn_options) self.easy_btn = ToggleButton( pygame.Rect(width * 2 / 5 - 50, 100, 100, 30), "Easy", btn_options) self.normal_btn = ToggleButton( pygame.Rect(width * 3 / 5 - 50, 100, 100, 30), "Normal", btn_options) self.hard_btn = ToggleButton( pygame.Rect(width * 4 / 5 - 50, 100, 100, 30), "Hard", btn_options) toggle_group = [ self.random_diff_btn, self.easy_btn, self.normal_btn, self.hard_btn ] for elt in toggle_group: elt.set_group(toggle_group) self.easy_btn.toggle() self.center_pos = pygame.Rect(width / 2 - 50, height / 2 - 50, 100, 100) self.random_pen_data = PenData.dict_to_pen({ "name": "Random", "image_file": "random_pen" }) for pen in [self.random_pen_data] + PenData.all_pens: self.pen_images.append( Image(self.center_pos, Resources.get(pen.image_file), {Options.BACKGROUND: (82, 173, 200)})) self.already_loaded = True self.reposition_images() self.update_enemy_data() def update(self, event): for elt in (self.back_btn, self.left_btn, self.right_btn, self.select_btn, self.random_diff_btn, self.easy_btn, self.normal_btn, self.hard_btn): elt.update(event) if self.select_btn.clicked: PenData.current_enemy_pen = \ random.choice(PenData.all_pens) if self.pen_index == 0 else \ PenData.all_pens[self.pen_index - 1] PenData.current_enemy_difficulty = \ AIDifficulty.EASY if self.easy_btn.toggled else \ AIDifficulty.NORMAL if self.normal_btn.toggled else \ AIDifficulty.HARD if self.hard_btn.toggled else \ random.choice(list(AIDifficulty)) Scene.push_scene(7) if self.back_btn.clicked: Scene.pop_scene() if self.left_btn.clicked or self.right_btn.clicked: if self.left_btn.clicked: self.pen_index -= 1 self.reposition_images() elif self.right_btn.clicked: self.pen_index += 1 self.reposition_images() self.update_enemy_data() def reposition_images(self): self.visible_pen_images.clear() if self.pen_index > 0: img = self.pen_images[self.pen_index - 1] self.visible_pen_images.append(img) img.rect = self.center_pos.copy().move(-300, 40) self.visible_pen_images.append(self.pen_images[self.pen_index]) self.pen_images[self.pen_index].rect = self.center_pos if self.pen_index < len(self.pen_images) - 1: img = self.pen_images[self.pen_index + 1] self.visible_pen_images.append(img) img.rect = self.center_pos.copy().move(300, 40) self.left_btn.set_enabled(self.pen_index > 0) self.right_btn.set_enabled(self.pen_index < len(self.pen_images) - 1) def update_enemy_data(self): self.name_text.text = self.random_pen_data.name if self.pen_index == 0 else \ PenData.all_pens[self.pen_index - 1].name self.name_text.recreate() def draw(self, screen): screen.fill((82, 173, 200)) for elt in (self.header, self.back_btn, self.left_btn, self.right_btn, self.name_text, self.select_btn, self.easy_btn, self.normal_btn, self.hard_btn, self.random_diff_btn): elt.draw(screen) for img in self.visible_pen_images: img.draw(screen)
def start(self, screen): if not self.already_loaded: PenData.load_all_pens(Resources.get("all_pens")) width = screen.get_width() height = screen.get_height() self.back_btn = Button( pygame.Rect(10, 10, 60, 40), "Back", { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) }) label_options = { Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, } self.header = Label(pygame.Rect(width / 2 - 200, 10, 400, 30), "Select your weapon!", label_options) self.coins_text = Label( pygame.Rect(width - 110, height - 55, 100, 40), "0", label_options) label_options = { Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0, Options.FONT: pygame.font.SysFont("Comic Sans MS", 18) } self.density_text = Label(pygame.Rect(width / 5, 110, 100, 20), "Density: ", label_options) self.restitution_text = Label(pygame.Rect(width / 5, 130, 100, 20), "Restitution: ", label_options) self.name_text = Label( pygame.Rect(width / 2 - 45, height - 125, 90, 50), "", label_options) self.description_lines = [ Label(pygame.Rect(width * 2 / 3, 100 + i * 25, 100, 20), "", label_options) for i in range(0, 3) ] self.coins_image = Image( pygame.Rect(width - 175, height - 60, 50, 50), Resources.get("coin"), {Options.BACKGROUND: (82, 173, 200)}) btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 25) } self.left_btn = Button(pygame.Rect(10, height / 2 - 20, 20, 30), "<", btn_options) self.right_btn = Button( pygame.Rect(width - 30, height / 2 - 20, 20, 30), ">", btn_options) self.select_btn = Button( pygame.Rect(width / 2 - 45, height - 75, 90, 50), "Select", btn_options) self.purchase_btn = Button( pygame.Rect(width / 2 - 125, height - 75, 250, 40), "", btn_options) self.center_pos = pygame.Rect(width / 2 - 50, height / 2 - 50, 100, 100) for pen in PenData.all_pens: self.pen_images.append( Image(self.center_pos, Resources.get(pen.image_file), {Options.BACKGROUND: (82, 173, 200)})) self.already_loaded = True self.reposition_images() self.update_shop_data() self.reset_coin_text()
class GameScene(Scene): GAME_OVER_EVENT = pygame.USEREVENT + 1 game_over = False ENEMY_MOVE_DELAY = 100 world = None table = None players = None current_player_index = -1 victory_state = -1 move_made = True turn_count = 0 ai_counter = 0 turn_text = None victory_text = None drag_start_pos = None mouse_dragging = False drag_end_pos = None player_sprites = [] width, height = 0, 0 def start(self, screen): if not self.already_loaded: self.width, self.height = screen.get_width(), screen.get_height() self.turn_text = Label( pygame.Rect(10, 10, 100, 30), "", { Options.BACKGROUND: (0, 51, 102), Options.FOREGROUND: (255, 255, 255), Options.BORDER_WIDTH: 0, }) self.victory_text = Label( pygame.Rect(self.width / 2 - 100, self.height / 2 - 30, 200, 60), "", { Options.FONT: pygame.font.SysFont("Comic Sans MS", 25), Options.BACKGROUND: (0, 51, 102), Options.FOREGROUND: (255, 255, 255), Options.BORDER_WIDTH: 0, }) self.reset_game_data() self.already_loaded = True if GameScene.game_over: self.reset_game_data() def reset_game_data(self): GameScene.game_over = False self.world = World((0, 0)) world_center = screen_to_world((self.width / 2, self.height / 2)) table_size = screen_to_world((1200, 600)) self.table = Table(world_center, table_size, self.world) self.players = [ Pen(PenData.current_pen, (world_center[0] - 35, world_center[1]), self.table.body, self.world), Pen(PenData.current_enemy_pen, (world_center[0] + 35, world_center[1]), self.table.body, self.world) ] self.ai_counter = GameScene.ENEMY_MOVE_DELAY self.turn_count = 0 self.move_made = True self.current_player_index = 1 self.victory_state = -1 self.player_sprites = { p: PenSprite(Resources.get(p.data.image_file)) for p in self.players } self.next_turn() def update(self, event): if event.type == pygame.KEYDOWN and event.key == pygame.K_p: Scene.push_scene(8) elif self.current_player_index == 0 and not self.move_made: if event.type == pygame.MOUSEBUTTONDOWN and not self.mouse_dragging: self.drag_start_pos = self.drag_end_pos = pygame.mouse.get_pos( ) self.mouse_dragging = True elif event.type == pygame.MOUSEMOTION and self.mouse_dragging: self.drag_end_pos = pygame.mouse.get_pos() elif event.type == pygame.MOUSEBUTTONUP and self.mouse_dragging: self.drag_end_pos = pygame.mouse.get_pos() drag_start = Vec2( screen_to_world((self.drag_start_pos[0], self.height - self.drag_start_pos[1]))) drag_end = Vec2( screen_to_world((self.drag_end_pos[0], self.height - self.drag_end_pos[1]))) hit_point = GameScene.cast_ray(self.players[0].fixture, drag_start, drag_end) if hit_point is not None: randomness = random.random() * 5 - 2.5 force = (hit_point - drag_start) * (20 + randomness) self.players[0].apply_force(hit_point, force) self.move_made = True self.mouse_dragging = False elif event.type == GameScene.GAME_OVER_EVENT: pygame.time.set_timer(GameScene.GAME_OVER_EVENT, 0) GameScene.game_over = True GameOverScene.result = GameResult(self.victory_state) Scene.push_scene(10) def draw(self, screen): screen.fill((0, 51, 102)) table_rect = pygame.Rect((0, 0), world_to_screen(self.table.dimensions)) table_rect.center = world_to_screen(self.table.center) pygame.draw.rect(screen, (204, 102, 0), table_rect) if self.victory_state == -1: self.turn_text.draw(screen) self.draw_player(screen, self.players[0]) self.draw_player(screen, self.players[1]) elif self.victory_state != GameResult.VictoryState.TIE: self.draw_player(screen, self.players[self.victory_state.value]) self.check_bounds() if self.mouse_dragging: drag_start = Vec2( screen_to_world((self.drag_start_pos[0], self.height - self.drag_start_pos[1]))) drag_end = Vec2( screen_to_world((self.drag_end_pos[0], self.height - self.drag_end_pos[1]))) hit_point = GameScene.cast_ray(self.players[0].fixture, drag_start, drag_end) if hit_point is not None: end = world_to_screen(hit_point) end = (end[0], self.height - end[1]) GameScene.draw_arrow(screen, (0, 255, 0), self.drag_start_pos, end) else: GameScene.draw_arrow(screen, (255, 0, 0), self.drag_start_pos, self.drag_end_pos) if self.victory_state != -1: self.victory_text.draw(screen) if self.victory_state == -1 and not self.move_made and self.current_player_index == 1: if self.ai_counter == 0: self.ai_counter = GameScene.ENEMY_MOVE_DELAY target, hit_point = PenData.current_enemy_strategy( self.players[1], self.players[0], self.table) randomness = random.random() * 10 - 5 force = (target - hit_point) * (20 + randomness) self.players[1].apply_force(hit_point, force) self.move_made = True else: self.ai_counter -= 1 self.world.Step(1.0 / 30.0, 20, 20) self.world.ClearForces() def next_turn(self): self.move_made = False self.current_player_index = 1 - self.current_player_index self.turn_text.text = f"Player's Turn" if self.current_player_index == 0 else f"Computer's Turn" self.turn_text.recreate(False) def check_bounds(self): if self.victory_state == -1: player_outside = not self.table.contains_point( self.players[0].body.position) comp_outside = not self.table.contains_point( self.players[1].body.position) if player_outside and comp_outside: self.set_winner(GameResult.VictoryState.TIE) elif (GameScene.velocity_near_zero(self.players[0]) or player_outside) and \ (GameScene.velocity_near_zero(self.players[1]) or comp_outside): if player_outside: self.set_winner(GameResult.VictoryState.LOSE) elif comp_outside: self.set_winner(GameResult.VictoryState.WIN) elif self.move_made: self.next_turn() def set_winner(self, result): self.victory_state = result if result == GameResult.VictoryState.TIE: self.victory_text.text = f"It's a tie!" elif result == GameResult.VictoryState.LOSE: self.victory_text.text = f"Computer wins!" elif result == GameResult.VictoryState.WIN: self.victory_text.text = f"Player wins!" self.victory_text.recreate() pygame.time.set_timer(GameScene.GAME_OVER_EVENT, 2000) def draw_player(self, screen, player): position = player.body.position position = world_to_screen(position) position = (position[0], self.height - position[1]) rotation = player.body.angle rotation = math.degrees(rotation) sprite = self.player_sprites[player] sprite.set_transform(position, rotation) sprite.draw(screen) @staticmethod def cast_ray(fixture, start, end): input = RayCastInput(p1=start, p2=end, maxFraction=1.1) output = RayCastOutput() if fixture.RayCast(output, input, 0): hit_point = start + (end - start) * output.fraction return hit_point return None @staticmethod def draw_arrow(surface, color, start, end, line_size=3, arrow_size=7): pygame.draw.line(surface, color, start, end, line_size) rotation = math.atan2(start[1] - end[1], end[0] - start[0]) + math.pi / 2 pygame.draw.polygon( surface, color, [(end[0] + arrow_size * math.sin(rotation), end[1] + arrow_size * math.cos(rotation)), (end[0] + arrow_size * math.sin(rotation - 2.0944), end[1] + arrow_size * math.cos(rotation - 2.0944)), (end[0] + arrow_size * math.sin(rotation + 2.0944), end[1] + arrow_size * math.cos(rotation + 2.0944))]) @staticmethod def velocity_near_zero(player, linear_threshold=0.2, angular_threshold=0.5): return player.body.linearVelocity.lengthSquared <= linear_threshold ** 2 \ and player.body.angularVelocity <= angular_threshold
class LoadingScene(Scene): loaded = False loading_text = None circle_image = None loading_circle = None circle_angle = 0 def start(self, screen): if self.already_loaded: return # Spawn a new thread to load all resources Thread(target=self.load_assets).start() width = screen.get_width() height = screen.get_height() # Meanwhile create a label to show that the game is loading text_rect = pygame.rect.Rect(width / 2 - 100, height / 2 - 25, 200, 50) self.loading_text = Label(text_rect, "Loading...", { Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) # Also create an image to display a rotate animation image_rect = pygame.rect.Rect(width / 2 - 50, height / 2 + 50, 75, 75) self.loading_circle = Image(image_rect, None, { Options.BACKGROUND: (82, 173, 200) }) self.already_loaded = True def load_assets(self): # Load the circle loading animation Resources.add("loading", pygame.image.load("assets/loading.png")) self.circle_image = Resources.get("loading") # Load the settings gear icon Resources.add("gear", pygame.image.load("assets/gear.png")) # Load the close icon Resources.add("close", pygame.image.load("assets/close.png")) # Load the coin image Resources.add("coin", pygame.image.load("assets/coin.png")) # Load the random pen image Resources.add("random_pen", pygame.image.load("assets/random_pen.png")) # Load the pen data and images Resources.add("all_pens", Resources.load_text("assets/pens.json")) Resources.add("pencil", pygame.image.load("assets/pencil.png")) Resources.add("ball_pen", pygame.image.load("assets/ball_pen.png")) Resources.add("blue_gel_pen", pygame.image.load("assets/blue_gel_pen.png")) Resources.add("black_gel_pen", pygame.image.load("assets/black_gel_pen.png")) Resources.add("mech_pencil", pygame.image.load("assets/mech_pencil.png")) Resources.add("marker", pygame.image.load("assets/marker.png")) self.loaded = True def update(self, event): # If the circle loading image has been loaded then use it for the animation if (self.loading_circle.image is None) and (self.circle_image is not None): self.loading_circle.image = self.circle_image def draw(self, screen): screen.fill((82, 173, 200)) # Wait if the loading has not finished if not self.loaded: self.loading_text.draw(screen) # Rotate the image to show a loading animation self.loading_circle.draw(screen) if self.loading_circle.image is not None: self.loading_circle.image = pygame.transform.rotate(self.circle_image, self.circle_angle) self.circle_angle = -(pygame.time.get_ticks() % 360) # If loading has finished, then go to account loading else: Scene.push_scene(1)
class GameOverScene(Scene): result = None title = None win_state_text = None replay_btn = None main_menu_btn = None def start(self, screen): width, height = screen.get_width(), screen.get_height() if not self.already_loaded: self.title = Label(pygame.rect.Rect(width / 2 - 200, 10, 400, 30), "Game Over", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 20), } btn_rect = pygame.rect.Rect(width / 2 - 125, height * 3 / 5 - 50, 250, 30) self.replay_btn = Button(btn_rect, "Play again", btn_options) self.main_menu_btn = Button(btn_rect.copy().move(0, 75), "Go to main menu", btn_options) self.already_loaded = True self.recreate_victory_texts(width, height) Account.current_account.reward_money(GameOverScene.result.coins) if GameOverScene.result.state == GameResult.VictoryState.WIN: Account.current_account.add_win() elif GameOverScene.result.state == GameResult.VictoryState.LOSE: Account.current_account.add_loss() def recreate_victory_texts(self, w, h): coins = GameOverScene.result.coins text = f"You won the match! Received {coins} coins." if GameOverScene.result.state == GameResult.VictoryState.WIN else \ "You lost the match!" if GameOverScene.result.state == GameResult.VictoryState.LOSE else \ f"The match was a tie! Received {coins} coins." self.win_state_text = Label( pygame.rect.Rect(w / 2 - 300, 175, 600, 30), text, { Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0, }) def update(self, event): for btn in (self.replay_btn, self.main_menu_btn): btn.update(event) if self.replay_btn.clicked: Scene.fire_event = False for i in range(0, 2): Scene.pop_scene() Scene.fire_event = True Scene.pop_scene() elif self.main_menu_btn.clicked: Scene.fire_event = False for i in range(0, 3): Scene.pop_scene() Scene.fire_event = True Scene.pop_scene() # Clear the screen and draw the gui def draw(self, screen): screen.fill((82, 173, 200)) self.title.draw(screen) for elt in (self.replay_btn, self.main_menu_btn, self.win_state_text): elt.draw(screen)
def print_text(self, text): label = Label(self.unit, text, int(self.unit * 10), (255, 255, 255)) label.rect.centerx = self.screen.get_rect().centerx label.rect.y = self.unit * 5 label.draw(self.screen) label.set_fontsize(self.unit * 11) label.set_fontcolor((140, 20, 10)) label.rect.centerx = self.screen.get_rect().centerx label.update() label.draw(self.screen) del label pygame.display.update()
def print_text(self,text): label = Label(self.unit,text,int(self.unit*10),(255,255,255)) label.rect.centerx = self.screen.get_rect().centerx label.rect.y = self.unit*5 label.draw(self.screen) label.set_fontsize(self.unit*11) label.set_fontcolor((140,20,10)) label.rect.centerx = self.screen.get_rect().centerx label.update() label.draw(self.screen) del label pygame.display.update()
class PenSelectScene(Scene): header = None back_btn = None select_btn = None purchase_btn = None name_text = None density_text = None restitution_text = None description_lines = [] coins_image = None coins_text = None pen_images = [] visible_pen_images = [] left_btn, right_btn = None, None center_pos = None pen_index = 0 def start(self, screen): if not self.already_loaded: PenData.load_all_pens(Resources.get("all_pens")) width = screen.get_width() height = screen.get_height() self.back_btn = Button( pygame.Rect(10, 10, 60, 40), "Back", { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) }) label_options = { Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, } self.header = Label(pygame.Rect(width / 2 - 200, 10, 400, 30), "Select your weapon!", label_options) self.coins_text = Label( pygame.Rect(width - 110, height - 55, 100, 40), "0", label_options) label_options = { Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0, Options.FONT: pygame.font.SysFont("Comic Sans MS", 18) } self.density_text = Label(pygame.Rect(width / 5, 110, 100, 20), "Density: ", label_options) self.restitution_text = Label(pygame.Rect(width / 5, 130, 100, 20), "Restitution: ", label_options) self.name_text = Label( pygame.Rect(width / 2 - 45, height - 125, 90, 50), "", label_options) self.description_lines = [ Label(pygame.Rect(width * 2 / 3, 100 + i * 25, 100, 20), "", label_options) for i in range(0, 3) ] self.coins_image = Image( pygame.Rect(width - 175, height - 60, 50, 50), Resources.get("coin"), {Options.BACKGROUND: (82, 173, 200)}) btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 25) } self.left_btn = Button(pygame.Rect(10, height / 2 - 20, 20, 30), "<", btn_options) self.right_btn = Button( pygame.Rect(width - 30, height / 2 - 20, 20, 30), ">", btn_options) self.select_btn = Button( pygame.Rect(width / 2 - 45, height - 75, 90, 50), "Select", btn_options) self.purchase_btn = Button( pygame.Rect(width / 2 - 125, height - 75, 250, 40), "", btn_options) self.center_pos = pygame.Rect(width / 2 - 50, height / 2 - 50, 100, 100) for pen in PenData.all_pens: self.pen_images.append( Image(self.center_pos, Resources.get(pen.image_file), {Options.BACKGROUND: (82, 173, 200)})) self.already_loaded = True self.reposition_images() self.update_shop_data() self.reset_coin_text() def update(self, event): for elt in (self.back_btn, self.left_btn, self.right_btn): elt.update(event) cur_pen = PenData.all_pens[self.pen_index] if cur_pen.name in Account.current_account.pens: self.select_btn.update(event) if self.select_btn.clicked: PenData.current_pen = cur_pen Scene.push_scene(6) else: self.purchase_btn.set_enabled( Account.current_account.money >= cur_pen.cost) self.purchase_btn.update(event) if self.purchase_btn.clicked: Account.current_account.purchase_pen(cur_pen) self.reset_coin_text() if self.back_btn.clicked: Scene.pop_scene() if self.left_btn.clicked or self.right_btn.clicked: if self.left_btn.clicked: self.pen_index -= 1 self.reposition_images() elif self.right_btn.clicked: self.pen_index += 1 self.reposition_images() self.update_shop_data() def reposition_images(self): self.visible_pen_images.clear() if self.pen_index > 0: img = self.pen_images[self.pen_index - 1] self.visible_pen_images.append(img) img.rect = self.center_pos.copy().move(-300, 40) self.visible_pen_images.append(self.pen_images[self.pen_index]) self.pen_images[self.pen_index].rect = self.center_pos if self.pen_index < len(self.pen_images) - 1: img = self.pen_images[self.pen_index + 1] self.visible_pen_images.append(img) img.rect = self.center_pos.copy().move(300, 40) self.left_btn.set_enabled(self.pen_index > 0) self.right_btn.set_enabled(self.pen_index < len(self.pen_images) - 1) def reset_coin_text(self): self.coins_text.text = str(Account.current_account.money) self.coins_text.recreate() def update_shop_data(self): cur_pen = PenData.all_pens[self.pen_index] self.name_text.text = cur_pen.name self.name_text.recreate() self.density_text.text = f"Density: {cur_pen.density}" self.density_text.recreate() self.restitution_text.text = f"Restitution: {cur_pen.restitution}" self.restitution_text.recreate() line_index = 0 for line in cur_pen.description: self.description_lines[line_index].text = line self.description_lines[line_index].recreate() line_index += 1 if cur_pen.name not in Account.current_account.pens: self.purchase_btn.text = f"Purchase for {cur_pen.cost}" self.purchase_btn.recreate() def draw(self, screen): screen.fill((82, 173, 200)) for elt in (self.header, self.back_btn, self.left_btn, self.right_btn, self.name_text, self.coins_image, self.coins_text, self.density_text, self.restitution_text): elt.draw(screen) for line in self.description_lines: line.draw(screen) if PenData.all_pens[ self.pen_index].name in Account.current_account.pens: self.select_btn.draw(screen) else: self.purchase_btn.draw(screen) for img in self.visible_pen_images: img.draw(screen)
class RouterControl(): def __init__(self, C, router_address: tuple, log: dict, bounds: tuple): self.router_address = router_address self.model = RouterModel(router_address, log) self.past_free_index = 0 # exibir sinais no instante X # Prepara as coordenadas # self.bounds = bounds x1, y1, x2, y2 = bounds local_w = x2 - x1 local_h = y2 - y1 caixa_w = x2 - x1 - 76 caixa_h = y2 - y1 - 76 #instancia os vetores self.portas = list() self.portas.insert(stds.IN_ACK, []) self.portas.insert(stds.IN_NACK, []) self.portas.insert(stds.OUT_REQ, []) self.portas.insert(stds.IN_REQ, []) self.portas.insert(stds.OUT_NACK, []) self.portas.insert(stds.OUT_ACK, []) self.sinais = dict() self.sinais.update({ 'fsm1': Label(C, (x1 + 50, y1 + 38 + caixa_h * .2), "", pre_text="in {}", font_size=7, bold=True, pos='nw') }) self.sinais.update({ 'fsm2': Label(C, (x1 + 50, y2 - 38 - caixa_h * .4), "", pre_text="out {}", font_size=7, bold=True, pos='nw') }) self.sinais['fsm1'].draw() self.sinais['fsm2'].draw() c1 = x1 + 38 c2 = x1 + 38 + caixa_w / 8 c3 = x1 + 38 + caixa_w / 2.3 c4 = x1 + 38 + caixa_w / 1.4 l1 = y1 + 38 + caixa_h * .3 Label( C, (c1, l1), "L", ).draw(state="normal") Label(C, (c2, l1), "Src").draw(state="normal") Label(C, (c3, l1), "Tgt").draw(state="normal") Label(C, (c4, l1), "PayL").draw(state="normal") l2 = y1 + 38 + caixa_h * .4 self.sinais.update({'writed': Label(C, (c1, l2), "")}) self.sinais.update({'in_source': Label(C, (c2, l2), "")}) self.sinais.update({'in_target': Label(C, (c3, l2), "")}) self.sinais.update({'in_payload': Label(C, (c4, l2), "")}) l2_5 = y1 + 38 + caixa_h * .5 self.sinais.update({ 'in_service': Label(C, (x1 + local_w / 2, l2_5), "", pos='n', font_size=7) }) # self.sinais.update( {'in_service.' : Label(C,(c1,l2_5),"")} ) l3 = y2 - 38 - caixa_h * .3 Label( C, (c1, l3), "L", ).draw(state="normal") Label(C, (c2, l3), "Src").draw(state="normal") Label(C, (c3, l3), "Tgt").draw(state="normal") Label(C, (c4, l3), "PayL").draw(state="normal") l4 = y2 - 38 - caixa_h * .2 self.sinais.update({'sel': Label(C, (c1, l4), "")}) self.sinais.update({'out_source': Label(C, (c2, l4), "")}) self.sinais.update({'out_target': Label(C, (c3, l4), "")}) self.sinais.update({'out_payload': Label(C, (c4, l4), "")}) l4_5 = y2 - 38 - caixa_h * .1 self.sinais.update({ 'out_service': Label(C, (x1 + local_w / 2, l4_5), "", pos='n', font_size=7) }) # self.sinais.update( {'out_service.' : Label(C,(c1,l4_5),"")} ) self.label_id = Label(C, (x2 - 32, y1 + 38), *router_address, font_size=10, pre_text="{} x {}", pos='e') self.label_id.draw() self.label_id.update(*router_address) # self.sinais.update( {'sel' : Label(C,(x2-32,y1+50),"",pre_text="sel: {}",font_size=8,bold=False,pos='e')} ) self.sinais.update({ 'sel_port': Label(C, (x2 - 32, y1 + 47), "", pre_text="sel_port: {}", font_size=8, bold=False, pos='e') }) self.sinais.update({ 'free_index': Label(C, (x2 - 32, y1 + 57), "", pre_text="free index:{}", font_size=8, bold=False, pos='e') }) self.sinais['sel'].draw() self.sinais['sel_port'].draw() # self.sinais.update( {'sel' : Label(C,(x2-32,y1+50),"",pre_text="sel: {}",font_size=8,bold=False,pos='e')} ) self.sinais.update({ 'sec_zone_ID': Label(C, (x2 - 70, y1 + 38), "", "", pre_text="sz:{},{}", font_size=5, bold=False, pos='e') }) self.sinais['sec_zone_ID'].draw() self.wrapper = list() self.wrapper.insert( stds.EAST, Box(C, (x2 - 33, y1 + 3 * local_h / 7.4), (5, local_h / 4))) self.wrapper.insert( stds.WEST, Box(C, (x1 + 28, y1 + 3 * local_h / 7.4), (5, local_w / 4))) self.wrapper.insert( stds.NORTH, Box(C, (x1 + 3 * local_w / 7.4, y1 + 28), (local_w / 4, 5))) self.wrapper.insert( stds.SOUTH, Box(C, (x1 + 3 * local_w / 7.4, y2 - 33), (local_w / 4, 5))) # self.wrapper.insert(stds.LOCAL,Box(C,(x1+28,y1+28),(10,10))) for i in range(0, 4): self.wrapper[i].draw() self.opmode = Box(C, (x1 + 38, y2 - 38 - caixa_h * .4), (10, 10)) self.opmode.draw() # test.update("green") # self.sinais.update # Prepara a localização das portas # OBSERVAÇÃO: Precisa ser feito na ordem certa: # EAST, WEST, NORTH, SOUTH, LOCAL # Desta forma os indices da lista batem na ordem certa # Portas EAST, define posições IN_EAST_ACK = (x2 - 26, y1 + int(local_h * 0.2)) IN_EAST_NACK = (x2 - 26, y1 + int(local_h * 0.25)) OUT_EAST_REQ = (x2 - 26, y1 + int(local_h * 0.4)) IN_EAST_REQ = (x2 - 26, y1 + int(local_h * 0.6)) OUT_EAST_NACK = (x2 - 26, y1 + int(local_h * 0.75)) OUT_EAST_ACK = (x2 - 26, y1 + int(local_h * 0.8)) self.portas[stds.IN_ACK].insert(stds.EAST, ArrowInput(C, IN_EAST_ACK, stds.EAST)) self.portas[stds.IN_NACK].insert( stds.EAST, ArrowInput(C, IN_EAST_NACK, stds.EAST)) self.portas[stds.OUT_REQ].insert( stds.EAST, ArrowOutput(C, OUT_EAST_REQ, stds.EAST)) self.portas[stds.IN_REQ].insert(stds.EAST, ArrowInput(C, IN_EAST_REQ, stds.EAST)) self.portas[stds.OUT_NACK].insert( stds.EAST, ArrowOutput(C, OUT_EAST_NACK, stds.EAST)) self.portas[stds.OUT_ACK].insert( stds.EAST, ArrowOutput(C, OUT_EAST_ACK, stds.EAST)) # Portas WEST OUT_WEST_ACK = (x1, y1 + int(local_h * 0.2)) OUT_WEST_NACK = (x1, y1 + int(local_h * 0.25)) IN_WEST_REQ = (x1, y1 + int(local_h * 0.4)) OUT_WEST_REQ = (x1, y1 + int(local_h * 0.6)) IN_WEST_NACK = (x1, y1 + int(local_h * 0.75)) IN_WEST_ACK = (x1, y1 + int(local_h * 0.8)) self.portas[stds.IN_ACK].insert(stds.WEST, ArrowInput(C, IN_WEST_ACK, stds.WEST)) self.portas[stds.IN_NACK].insert( stds.WEST, ArrowInput(C, IN_WEST_NACK, stds.WEST)) self.portas[stds.OUT_REQ].insert( stds.WEST, ArrowOutput(C, OUT_WEST_REQ, stds.WEST)) self.portas[stds.IN_REQ].insert(stds.WEST, ArrowInput(C, IN_WEST_REQ, stds.WEST)) self.portas[stds.OUT_NACK].insert( stds.WEST, ArrowOutput(C, OUT_WEST_NACK, stds.WEST)) self.portas[stds.OUT_ACK].insert( stds.WEST, ArrowOutput(C, OUT_WEST_ACK, stds.WEST)) # Portas NORTH OUT_NORTH_ACK = (x1 + int(local_w * 0.2), y1) OUT_NORTH_NACK = (x1 + int(local_w * 0.25), y1) IN_NORTH_REQ = (x1 + int(local_w * 0.4), y1) OUT_NORTH_REQ = (x1 + int(local_w * 0.6), y1) IN_NORTH_NACK = (x1 + int(local_w * 0.75), y1) IN_NORTH_ACK = (x1 + int(local_w * 0.8), y1) self.portas[stds.IN_ACK].insert( stds.NORTH, ArrowInput(C, IN_NORTH_ACK, stds.NORTH)) self.portas[stds.IN_NACK].insert( stds.NORTH, ArrowInput(C, IN_NORTH_NACK, stds.NORTH)) self.portas[stds.OUT_REQ].insert( stds.NORTH, ArrowOutput(C, OUT_NORTH_REQ, stds.NORTH)) self.portas[stds.IN_REQ].insert( stds.NORTH, ArrowInput(C, IN_NORTH_REQ, stds.NORTH)) self.portas[stds.OUT_NACK].insert( stds.NORTH, ArrowOutput(C, OUT_NORTH_NACK, stds.NORTH)) self.portas[stds.OUT_ACK].insert( stds.NORTH, ArrowOutput(C, OUT_NORTH_ACK, stds.NORTH)) # # Portas SOUTH IN_SOUTH_ACK = (x1 + int(local_w * 0.2), y2 - 26) IN_SOUTH_NACK = (x1 + int(local_w * 0.25), y2 - 26) OUT_SOUTH_REQ = (x1 + int(local_w * 0.4), y2 - 26) IN_SOUTH_REQ = (x1 + int(local_w * 0.6), y2 - 26) OUT_SOUTH_NACK = (x1 + int(local_w * 0.75), y2 - 26) OUT_SOUTH_ACK = (x1 + int(local_w * 0.8), y2 - 26) self.portas[stds.IN_ACK].insert( stds.SOUTH, ArrowInput(C, IN_SOUTH_ACK, stds.SOUTH)) self.portas[stds.IN_NACK].insert( stds.SOUTH, ArrowInput(C, IN_SOUTH_NACK, stds.SOUTH)) self.portas[stds.OUT_REQ].insert( stds.SOUTH, ArrowOutput(C, OUT_SOUTH_REQ, stds.SOUTH)) self.portas[stds.IN_REQ].insert( stds.SOUTH, ArrowInput(C, IN_SOUTH_REQ, stds.SOUTH)) self.portas[stds.OUT_NACK].insert( stds.SOUTH, ArrowOutput(C, OUT_SOUTH_NACK, stds.SOUTH)) self.portas[stds.OUT_ACK].insert( stds.SOUTH, ArrowOutput(C, OUT_SOUTH_ACK, stds.SOUTH)) # # Portas LOCAL IN_LOCAL_ACK = (x1 + int(local_w * 0.16), y1 + int(local_h * 0.22)) OUT_LOCAL_REQ = (x1 + int(local_w * 0.20), y1 + int(local_h * 0.2)) IN_LOCAL_NACK = (x1 + int(local_w * 0.24), y1 + int(local_h * 0.18)) OUT_LOCAL_ACK = (x1 + int(local_w * 0.32), y1 + int(local_h * 0.22)) IN_LOCAL_REQ = (x1 + int(local_w * 0.36), y1 + int(local_h * 0.2)) OUT_LOCAL_NACK = (x1 + int(local_w * 0.40), y1 + int(local_h * 0.18)) self.portas[stds.IN_ACK].insert( stds.LOCAL, ArrowInput(C, IN_LOCAL_ACK, stds.LOCAL)) self.portas[stds.IN_NACK].insert( stds.LOCAL, ArrowInput(C, IN_LOCAL_NACK, stds.LOCAL)) self.portas[stds.OUT_REQ].insert( stds.LOCAL, ArrowOutput(C, OUT_LOCAL_REQ, stds.LOCAL)) self.portas[stds.IN_REQ].insert( stds.LOCAL, ArrowInput(C, IN_LOCAL_REQ, stds.LOCAL)) self.portas[stds.OUT_NACK].insert( stds.LOCAL, ArrowOutput(C, OUT_LOCAL_NACK, stds.LOCAL)) self.portas[stds.OUT_ACK].insert( stds.LOCAL, ArrowOutput(C, OUT_LOCAL_ACK, stds.LOCAL)) for i in self.sinais.values(): i.draw() self.caixa = Box(C, (x1, y1), (local_w, local_h), color="red", alpha=True, state="hidde") self.caixa.draw() def set_time(self, time): self.model.set_time(time) signals = self.model.get_all_values() # print("\nrouter {}x{}".format(*self.router_address)) for signal_name, signal_number in zip( ['in_ack', 'in_nack', 'out_req', 'in_req', 'out_nack', 'out_ack'], range(6)): vec = [int(x) for x in signals[signal_name][1]] for val, port in zip(vec, range(4, -1, -1)): # local south north west east if signal_name in ['in_nack', 'out_nack']: self.portas[signal_number][port].update(val * -1) else: self.portas[signal_number][port].update(val) # print(signal_name+f' {vec} string: {signals[signal_name]}') for k, v in signals.items(): if k in self.sinais: # print(f"{k} - {v[1]}") if ("service" in k): # self.sinais[k].update(v[1]) # self.sinais[k+'.'].update(services[v[1]]) self.sinais[k].update(services[v[1]]) elif ("fsm1" == k): self.sinais[k].update(str(v[1]) + ' ' + fsm1[v[1]]) elif ("fsm2" == k): self.sinais[k].update(str(v[1]) + ' ' + fsm2[v[1]]) elif ("sec_zone_ID" == k): self.sinais[k].update(*v[1]) # tupla elif ("in_payload" == k): self.sinais[k].update(hex(int(v[1], 2))) # tupla elif ("out_payload" == k): self.sinais[k].update(hex(int(v[1], 2))) # tupla else: self.sinais[k].update(str(v[1])) elif k == "in_fail": for new_v, i in zip(list(v[1])[1:], range(3, -1, -1)): # exceto porta local self.wrapper[i].update(wrapper_color[new_v]) elif k == "out_opmode": self.opmode.update(opmode_color[v[1][0]]) elif k == "sec_zone": if v[1] == 0: # sem zona segura self.caixa.update(state='hidde', color="red") elif v[1] == 1: # zona segura definida self.caixa.update(state='hidde', color='green') elif v[1] == 2: # zona segura ativa self.caixa.update(state='normal', color='red') ################################################################################################### # # # def set_max_tick(self, max_tick): self.max_tick = max_tick def filter_next_value(self, signals, value, originaltick): for signal in signals: hsignal = self.model.historico_sinal[signal] for tick in [k for k in hsignal.keys() if k > originaltick]: if hsignal[tick] == value: return tick return originaltick def filter_prior_value(self, signals, value, originaltick): for signal in signals: hsignal = self.model.historico_sinal[signal] for tick in [ k for k in reversed(hsignal.keys()) if k < originaltick ]: if hsignal[tick] == value: return tick return originaltick def get_next_event(self, time): return self.model.get_next_event(time) def get_prior_event(self, time): return self.model.get_prior_event(time) def get_prior_signals_event(self, signals, time): return self.model.get_prior_signals_event(signals, time) def get_next_signals_event(self, signals, time): return self.model.get_next_signals_event(signals, time) def get_all_signals(self): return self.model.get_all_values()
class StatsScene(Scene): header = None back_btn = None statistics = [] visible_stats = [] up_btn, down_btn = None, None stat_index = 0 first_offset = None all_metrics = {} @staticmethod def create_metrics(): StatsScene.all_metrics = { "Total Wins": (lambda acc: acc.stats[Account.TOTAL_WINS]), "Total Losses": (lambda acc: acc.stats[Account.TOTAL_LOSSES]), "Total Money": (lambda acc: acc.stats[Account.TOTAL_MONEY]), "Unlocked Pens": (lambda acc: acc.stats[Account.UNLOCKED_PENS]), } def start(self, screen): width = screen.get_width() height = screen.get_height() if not self.already_loaded: StatsScene.create_metrics() self.header = Label(pygame.rect.Rect(width / 2 - 200, 10, 400, 30), "Statistics", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) self.first_offset = pygame.rect.Rect(width / 2 - 125, 75, 250, 30) label_options = { Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0 } for metric in StatsScene.all_metrics.keys(): text = f"{metric}: {StatsScene.all_metrics[metric](Account.current_account)}" stat_lbl = Label(pygame.rect.Rect(0, 0, 0, 0), text, label_options) self.statistics.append(stat_lbl) btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) } self.back_btn = Button(pygame.rect.Rect(10, 10, 60, 40), "Back", btn_options) self.up_btn = Button( pygame.rect.Rect(width * 5 / 6, height * 2 / 6, 60, 40), "Up", btn_options) self.down_btn = Button( pygame.rect.Rect(width * 5 / 6, height * 4 / 6 - 40, 60, 40), "Down", btn_options) self.already_loaded = True self.stat_index = 0 self.reposition_stats() def update(self, event): for btn in (self.back_btn, self.up_btn, self.down_btn): btn.update(event) if self.back_btn.clicked: Scene.pop_scene() if self.up_btn.clicked: self.stat_index -= 1 self.reposition_stats() elif self.down_btn.clicked: self.stat_index += 1 self.reposition_stats() def reposition_stats(self): self.visible_stats.clear() offset = 0 for stat in self.statistics[self.stat_index:self.stat_index + 10]: stat.rect = self.first_offset.copy().move(0, offset) stat.recreate() self.visible_stats.append(stat) offset += 50 self.up_btn.set_enabled(self.stat_index > 0) self.down_btn.set_enabled(self.stat_index < len(self.statistics) - 1) def draw(self, screen): screen.fill((82, 173, 200)) self.header.draw(screen) for stat in self.visible_stats: stat.draw(screen) width, height = screen.get_width(), screen.get_height() scroll_rect = pygame.rect.Rect(width * 5 / 6 + 100, height * 1 / 6, 10, height * 4 / 6) pygame.draw.rect(screen, (100, 100, 100), scroll_rect) height_diff = (height * 4 / 6) / len(self.statistics) scroll_rect.top = height * 1 / 6 + height_diff * self.stat_index scroll_rect.height = height_diff pygame.draw.rect(screen, (50, 50, 50), scroll_rect) for btn in (self.back_btn, self.up_btn, self.down_btn): btn.draw(screen)
def start(self, screen): if not self.already_loaded: PenData.load_all_pens() width = screen.get_width() height = screen.get_height() self.back_btn = Button( pygame.Rect(10, 10, 60, 40), "Back", { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) }) self.header = Label( pygame.Rect(width / 2 - 200, 10, 400, 30), "Choose your opponent!", { Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) self.name_text = Label( pygame.Rect(width / 2 - 45, height - 125, 90, 50), "", { Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0, Options.FONT: pygame.font.SysFont("Comic Sans MS", 18) }) btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 25) } self.left_btn = Button(pygame.Rect(10, height / 2 - 20, 20, 30), "<", btn_options) self.right_btn = Button( pygame.Rect(width - 30, height / 2 - 20, 20, 30), ">", btn_options) self.select_btn = Button( pygame.Rect(width / 2 - 45, height - 75, 90, 50), "Select", btn_options) btn_options[Options.TOGGLED_BACKGROUND] = (5, 20, 30) self.random_diff_btn = ToggleButton( pygame.Rect(width * 1 / 5 - 50, 100, 100, 30), "Random", btn_options) self.easy_btn = ToggleButton( pygame.Rect(width * 2 / 5 - 50, 100, 100, 30), "Easy", btn_options) self.normal_btn = ToggleButton( pygame.Rect(width * 3 / 5 - 50, 100, 100, 30), "Normal", btn_options) self.hard_btn = ToggleButton( pygame.Rect(width * 4 / 5 - 50, 100, 100, 30), "Hard", btn_options) toggle_group = [ self.random_diff_btn, self.easy_btn, self.normal_btn, self.hard_btn ] for elt in toggle_group: elt.set_group(toggle_group) self.easy_btn.toggle() self.center_pos = pygame.Rect(width / 2 - 50, height / 2 - 50, 100, 100) self.random_pen_data = PenData.dict_to_pen({ "name": "Random", "image_file": "random_pen" }) for pen in [self.random_pen_data] + PenData.all_pens: self.pen_images.append( Image(self.center_pos, Resources.get(pen.image_file), {Options.BACKGROUND: (82, 173, 200)})) self.already_loaded = True self.reposition_images() self.update_enemy_data()