0

我正在使用 pygame 构建一个简单的游戏,并具有以下主循环,其中mouse()是捕获和处理鼠标事件和keyboard()键盘事件的函数:

def mainLoop():
    pygame.event.pump()
    keyboard(pygame.key.get_pressed())
    events = pygame.event.get()
    mouse(events)
    for event in events:
        if event.type == pygame.QUIT:
            pygame.quit()
            return False
    return True

当玩家点击瓷砖时,我会调用以下函数mouse()

def objReach(obj, pos):     
    try:
        path = obj.reach(pos, move=False)       # A* (path-finding algorithm)
        for step in path:
            sleep(1.0/obj.speed)
            objMove(obj, step)
    except Exception as e:
        sendMsg(str(e))

问题是,当对象走在路径上时(当for循环运行时)鼠标事件不会被捕获,所以如果玩家在中间点击另一个图块,什么也不会发生。我希望玩家能够改变路径。

我尝试mainLoopfor循环内使用,但它只是部分有效 - 它只捕获MOUSEBUTTONUP事件,而不是 UP 和 DOWN 事件,这是确定玩家是否只是单击或拖放所必需的。这是mouse()要澄清的功能:

def mouse(events):
    global clickPos
    global releasePos

    for event in events:
        if event.type == MOUSEBUTTONDOWN:
            clickPos = getPos(pygame.mouse.get_pos())
            # getPos() transforms screen coordinates in game coordinates
        elif event.type == MOUSEBUTTONUP:
            releasePos = getPos(pygame.mouse.get_pos())
            if event.button == MAIN_BUTTON:
                # Simple click
                if clickPos == releasePos:
                    if player.privilege > 1:
                        objMove(player, getPos(pygame.mouse.get_pos()))
                    else:
                        objReach(player, getPos(pygame.mouse.get_pos()))
                # Drag and drop
                else:
                    obj = player.place.matrix[clickPos[0]][clickPos[1]][-1]
                    objThrow(obj, clickPos, releasePos)
            elif event.button == SECONDARY_BUTTON:
                pass        # TODO: ...

我不熟悉多线程,我认为它不应该与 pygame 一起使用,但这是我唯一能想到的。有任何想法吗?

4

1 回答 1

2

objReach您可以尝试修改对象以使其具有类似于obj列表的内容,而不是使用多线程并直接导致对象在函数内移动并阻塞主循环。它基本上充当一个队列,其中包含要移动到的每个位置的坐标。

然后,您要做的是在单击鼠标时,使用您的寻路算法找到对象应该经过的路径并用它替换队列:

import time

def objReach(obj, pos):     
    try:
        obj.path = obj.reach(pos, move=False)       # A* (path-finding algorithm)
        obj.last_move = time.time()
        obj.move_after = 1   # move every 1 second.
    except Exception as e:
        sendMsg(str(e))

然后,在你的主循环中,每秒一次(使用某种计时器来跟踪 1 秒过去的时间),让你的对象弹出列表中的下一个坐标并移动到它。

它看起来像这样:

def mainLoop():
    pygame.event.pump()
    keyboard(pygame.key.get_pressed())
    events = pygame.event.get()
    mouse(events)
    for event in events:
        if event.type == pygame.QUIT:
            pygame.quit()
            return False

    if time.time() - obj.last_move > obj.move_after:
        obj.last_move = time.time()
        objMove(obj, obj.path.pop())

    return True

这样,使对象移动的代码被重新定位到主循环中,以便您仍然可以响应所有事件。

如果用户点击一个新的图块,那么路径会自动被覆盖,主循环会正确地做正确的事情。

如果你的代码结构正确,你甚至可以扩展游戏,让它可以同时处理多个在瓷砖上移动的物体,以不同的速度移动。

于 2013-08-28T23:25:01.077 回答