Exemple #1
0
 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()
Exemple #2
0
 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)
Exemple #7
0
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()
Exemple #8
0
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)
Exemple #9
0
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)