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 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 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)
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)
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)
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 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)