首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >单线程在Pygame循环中的窗口冻结

单线程在Pygame循环中的窗口冻结
EN

Stack Overflow用户
提问于 2021-02-17 20:43:22
回答 2查看 149关注 0票数 1

我正在写一个简短的程序来在一轮中显示卡片。我怀疑是代码的长度阻止了P3 (最后一位玩家提交的)最后的“OK”提交文件的正确执行:此时,程序有时会评估胜利者并清除该回合,但大多数时间反而会冻结。我已经尝试过clock.tick(低fps)、pygame.event.pump()和pygame.event.clear()。任何线索都将不胜感激。

代码语言:javascript
复制
# Round loop begins. Finish until all hands are empty.
            while not self.game.get_is_last_round():

                player = self.game.get_player(self.game.get_player_turn())
                hand = player.order_hand(player.get_hand(),
                                         self.game.get_round_level(),
                                         self.game.get_round_trump_suit())
                ok_clicked_2 = False

                pygame.event.pump()
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        self.deal_running = False
                        self.is_running = False
                        pygame.display.quit()
                        pygame.quit()
                        sys.exit()
                    if event.type == pygame.MOUSEBUTTONDOWN:
                        play = player.get_play()
                        click = pygame.mouse.get_pressed(num_buttons=3)
                        pos = pygame.mouse.get_pos()

                        # Used DeMorgan's law to resolve error
                        ok_clicked_2 = (OK1_X < pos[0] < OK1_X + B_W) and (OK1_Y < pos[1] < OK1_Y + B_H) and click[0]

                        b1, card = self.check_hand(pos, player)
                        b2, play_card = self.check_play(pos, player)
                        if b1:
                            hand.remove(card)
                            play.append(card)
                            player.set_play(
                                player.order_hand(play, self.game.get_round_level(),
                                                  self.game.get_round_trump_suit()))
                            player.set_hand(
                                player.order_hand(hand, self.game.get_round_level(),
                                                  self.game.get_round_trump_suit()))

                        if b2:
                            play.remove(play_card)
                            hand.append(play_card)
                            player.set_play(
                                player.order_hand(play, self.game.get_round_level(),
                                                  self.game.get_round_trump_suit()))
                            player.set_hand(player.order_hand(hand, self.game.get_round_level(),
                                                              self.game.get_round_trump_suit()))
                clock.tick(100)
                surface.blit(background, (0, 0))

                if len(self.game.get_player(0).get_hand()) == 25:
                    self.game.set_is_first_round(True)
                else:
                    self.game.set_is_first_round(False)

                if len(self.game.get_player(0).get_hand()) == 0:
                    self.game.set_is_last_round(True)
                else:
                    self.game.set_is_last_round(False)

                if self.game.get_play_in_turn() != NUM_PLAYERS:

                    pygame.event.pump()
                    clock.tick(100)

                    if len(hand) <= 1:
                        width = 0
                        x = (BG_WIDTH - CARD_WIDTH) // 2
                    elif len(hand) >= 8:
                        width = (BG_WIDTH - SIDE_W - CARD_WIDTH) // (len(hand) - 1)
                        x = BG_WIDTH // 2 - (CARD_WIDTH + (width * (len(hand) - 1))) // 2
                    else:
                        width = CARD_WIDTH
                        x = (BG_WIDTH - (CARD_WIDTH * len(hand))) // 2

                    surface.blit(background, (0, 0))

                    self.blit_backs()
                    self.blit_round()

                    self.show_ok()

                    self.show_hand(x, ROW3h, width, hand)
                    self.show_hand(CARD_POSITIONS[0][0], CARD_POSITIONS[0][1], SLIM_WIDTH, play)

                    if ok_clicked_2:
                        for card in play:
                            hand.append(card)

                        player.set_hand(player.order_hand(hand, self.game.get_round_level(),
                                                          self.game.get_round_trump_suit()))

                        # If player is first to start a round, he/she has a different validity check.
                        # (Sets the pattern for the cycle)

                        if player.get_begins_cycle():
                            valid = self.game.check_validity(True)  # is_first
                        else:
                            valid = self.game.check_validity(False)  # Is not first to play in the round

                        if not valid:  # Clear holding if invalid
                            if (play == []) or (player.get_play() == []):
                                print("\nYou must make a play.\n")
                            else:
                                print("Invalid play. Try again.")

                                if not player.get_begins_cycle():
                                    valid_plays = player.get_valid_plays(self.game.get_pattern(),
                                                                         self.game.get_round_trump_suit())
                                    print("Valid plays: \n")

                                    for temp_play_idx in range(len(valid_plays)):
                                        temp_play = valid_plays[temp_play_idx]
                                        print("[", end='')
                                        for temp_card_idx in range(len(temp_play)):
                                            valid_plays[temp_play_idx][temp_card_idx].show_card("", '')
                                            if temp_card_idx != len(temp_play) - 1:
                                                print(", ", end='')
                                        print("]")

                            # Clear the current player's selection and restore hand to its original content
                            cycle_order = self.game.get_cycle_order()
                            cycle = self.game.get_cycle()
                            for player_order in range(len(cycle_order)):
                                if player == cycle_order[player_order]:
                                    cycle_order.remove(player)
                                    cycle.pop()
                            self.game.set_cycle_order(cycle_order)
                            self.game.set_cycle(cycle)

                        else:  # Valid play on submit
                            # Special case for HIGH_SUIT play, play lowest card if another player has greater
                            play = self.game.check_high_suit(play)

                            # If friend card played, establish and print teammates
                            # TODO: auto-designate friends if the last round
                            #  has been reached (friends buried in treasure case)
                            # TODO: determine whether friend is "dead"
                            self.game.check_for_friends()

                            cycle = self.game.get_cycle()
                            cycle.append(play)
                            self.game.set_cycle(cycle)

                            cycle_order = self.game.get_cycle_order()
                            cycle_order.append(player)
                            self.game.set_cycle_order(cycle_order)

                            # self.clear_positions()

                            for card in play:
                                hand.remove(card)

                            player.set_hand(
                                player.order_hand(hand, self.game.get_round_level(),
                                                  self.game.get_round_trump_suit()))

                            self.game.next_player_turn()
                            self.game.set_play_in_turn(self.game.get_play_in_turn() + 1)
                            print(self.game.get_play_in_turn())

                        play = []

                else:
                    self.game.set_play_in_turn(0)
                    # Distribute any points in the round to round winner
                    self.update_cycle_points()
                    for p in self.game.get_players():
                        for card in p.get_play():
                            discard = self.game.get_discard()
                            discard.append(card)
                        p.set_play([])

                pygame.event.clear()
                clock.tick(100)
                pygame.display.update()
EN

回答 2

Stack Overflow用户

发布于 2021-02-17 22:21:17

我认为是时候进行代码清理了,然后你的问题就会消失(否则你会发现它)。

目前,主循环是事件处理、屏幕绘制和游戏引擎的一个很大的混合.试着把这些部分分开。

将一些循环中的处理移到函数中,比如if ok_clicked_2:之后的块。它可能有助于创建一个数据结构,在其中存储游戏状态,然后让事件更改该游戏状态。当需要将游戏绘制到屏幕上时,绘画代码可以查询状态,并采取相应的行动。

就实际的锁定而言,如果self.game.get_play_in_turn() == NUM_PLAYERS没有绘制到屏幕上。这是故意的吗?向代码中添加一些print(),这样您就可以知道执行流程(或者学习使用python调试器)。

我认为最大的进步是将所有的屏幕绘画移到主循环的一个部分,类似于:

代码语言:javascript
复制
# Render the screen
print( "Rendering Screen" )
surface.blit(background, (0, 0))
self.blit_backs()
self.blit_round()
# etc. for all other things, score, buttons, ...
clock.tick(60)
pygame.display.update()

您似乎正在处理这些事件,所以最好删除对pygame.event.pump()pygame.event.clear()的调用。你不需要这些。

票数 1
EN

Stack Overflow用户

发布于 2021-02-18 16:56:41

按照金斯利的建议,我按功能组织了代码:渲染屏幕、游戏引擎和事件处理。我会提供MRE的随机戴维斯建议,但这将包括5个综合文件,这将花费太长时间来削减。

事实证明,这个问题存在于一段单独调用的代码中:"update_cycle_points()“。在内部,有一个Within循环,它不包含事件处理程序。解决方案是将其更改为for循环,Pygame似乎可以在没有错误的情况下处理这个循环(不要冻结,因为它不需要那里的事件处理)。

我还删除了pygame.event.clear()和水泵()函数,没有任何问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66249662

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档