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ループが実行されている間) にマウス イベントがキャプチャされないため、プレイヤーが途中で別のタイルをクリックしても何も起こらないことです。プレイヤーがパスを変更できるようにしてほしい。

mainLoopループ内で使用してみforましたが、部分的にしか効果が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 秒ごとに (何らかのタイマーを使用して 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 に答える