如何让我的代码等待点击?

Posted

技术标签:

【中文标题】如何让我的代码等待点击?【英文标题】:How do I make my code wait for a click? 【发布时间】:2017-11-20 18:19:39 【问题描述】:

我正在尝试为 pvp 战舰游戏编写代码,但我有点卡住了。

我会先给你看代码,然后解释它们是如何工作的。

这是第一个代码。此函数用于在网格上定位每艘船:

def ship_builder(name):
# client ship value = 6, server ship value = 7
    v_or_h = randrange(2)
    if v_or_h == 0:
        vertical = True
    else:
        vertical = False

    if name == 'destroyer':
        print('Click a cell to build a destroyer.')
        if vertical == True:
            print('Vertical')
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    break
                if event.type == pygame.MOUSEBUTTONDOWN:
                    pos = pygame.mouse.get_pos()
                    col = (pos[0] // (cell_side + margin)) + 1
                    row = (pos[1] // (cell_side + margin)) + 1
                    grid[row][col] = 7
                    for i in range(3):
                        row += 1
                        grid[row][col] = 7

        elif vertical == False:
            print('Horizontal')
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    break
                if event.type == pygame.MOUSEBUTTONDOWN:
                    pos = pygame.mouse.get_pos()
                    col = (pos[0] // (cell_side + margin)) + 1
                    row = (pos[1] // (cell_side + margin)) + 1
                    grid[row][col] = 7
                    for i in range(3):
                        col += 1
                        grid[row][col] = 7

    elif name == 'frigate':
        print('Click a cell to build a frigate')
        if vertical == True:
            print('Vertical')
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    break
                if event.type == pygame.MOUSEBUTTONDOWN:
                    pos = pygame.mouse.get_pos()
                    col = (pos[0] // (cell_side + margin)) + 1
                    row = (pos[1] // (cell_side + margin)) + 1
                    grid[row][col] = 7
                    for i in range(2):
                        row += 1
                        grid[row][col] = 7
        elif vertical == False:
            print('Horizontal')
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    break
                if event.type == pygame.MOUSEBUTTONDOWN:
                    pos = pygame.mouse.get_pos()
                    col = (pos[0] // (cell_side + margin)) + 1
                    row = (pos[1] // (cell_side + margin)) + 1
                    grid[row][col] = 7
                    for i in range(2):
                        col += 1
                        grid[row][col] = 7

第二个是上面函数的for循环:

for ship in ['destroyer','frigate']:
    ship_builder(ship)
    color_change()

    #color_change() is a function that colors the responding cells for the ships.

这是他们应该如何工作的。首先,ship_builder 被称为船名(例如,“战舰”)。代码做的第一件事是检查船是垂直放置还是水平放置。根据它的值,用户可以点击一个单元格来确定位置。这是我遇到问题的地方;代码只是跳过该部分并继续进行而不做任何事情。

我的问题是:为什么会跳过鼠标点击部分? pygame.event.get() 不应该让 Python “等待”一个动作吗?

我不确定我是否解释得很详细。如果我需要提供更多信息,请给我留言。我真的需要帮助!

谢谢!

【问题讨论】:

【参考方案1】:

简短的回答: 不,pygame.event.get() -> EventList 不应该“等待”一个动作。请改用pygame.event.wait() -> EventType

更长的答案: Pygame 正在使用一个事件队列,它存储已发生的事件。让我们看看pygame.event.get() 文档。

pygame.event.get()  
  get events from the queue 
  get() -> Eventlist  
  get(type) -> Eventlist
  get(typelist) -> Eventlist

这将获取所有消息并将它们从队列中删除。如果给定一个类型或类型序列,则只会从队列中删除那些消息。如果您只是从队列中获取特定事件,请注意队列最终可能会填满您不感兴​​趣的事件。

所以基本上,pygame.event.get() 返回自我们上次调用它以来发生的所有事件。如果我们的事件还没有发生,它就不会在返回的EventList中。

但是还有另一个名为 pygame.event.wait() 的函数按照要求的方式运行(尽管它只返回一个事件)。

pygame.event.wait()
  wait for a single event from the queue
  wait() -> EventType instance

从队列中返回单个事件。如果队列为空,此函数将等待直到创建队列。一旦事件被返回,它就会从队列中删除。

因此可以等待类似的鼠标按下事件

event_happened = False
while not event_happened:
    event = pygame.event.wait()
    if event.type == pygame.MOUSEBUTTONDOWN:
        do_something()
        event_happened = True

但是,我们需要在这里小心,因为如文档中所述,事件已从队列中删除,这意味着所有不属于 pygame.MOUSEBUTTONDOWN 类型的事件都将丢失.如果需要,我们将不得不手动处理它们或将它们传递/保护它们。

 

这是更长的答案,但我有一个补充/警告。像这样在代码中的不同点获取事件会很快导致混乱(例如,由于如上所述的丢失事件等)。这种情况下的决定可能与程序中缺少主游戏循环有关(我无法确定,因为我不知道周围的代码,但当前的实现似乎暗示了类似的东西)。

通常,事件是在一个连续的主游戏循环中访问的,看起来像这样

while True:
    for event in pygame.event.get():
        if event.type == pygame.MOUSEBUTTONDOWN:
            build_ship_on_event(event)

        elif event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

build_ship_on_event(event) 函数可以尝试做类似的事情

def build_ship_on_event(event):
    if event_is_mouse_click(event):
        ship_builder(selected_ship_type, event.pos)

并在给定位置为先前选择的类型建造船(当然检查之前是否建造过船等等)。

【讨论】:

没想到回答这么详细!非常感谢!

以上是关于如何让我的代码等待点击?的主要内容,如果未能解决你的问题,请参考以下文章

让我的php等待我的python脚本结束[重复]

如何让我的自定义不和谐机器人发送消息

如何使用异步发布并使用 HttpClient 等待

如何在继续之前等待所有 multiprocessing.Processes 完成?

如何成功等待函数结束?

如何让我的程序等待 Firebase 响应 IOS