2

四角形を描画する場所を処理する簡単なアニメーションがあり、サーフェスをクリックすると、四角形が左にスライドして 2 秒間待ってから、右にスライドして再描画しますが、ウィンドウを縮小または移動すると、待っている瞬間にウィンドウがフリーズしてみてください。

コードは次のとおりです。

import sys, pygame
from pygame.locals import *

pygame.init()

FPS       = 30
BGCOLOR   = (255, 255, 255)
RECTCOLOR = (10, 0, 199)
DS        = pygame.display.set_mode( (200,200) )
CLOCK     = pygame.time.Clock()
pygame.display.set_caption('Demo')

def main():
    DS.fill(BGCOLOR)
    pygame.draw.rect(DS, RECTCOLOR, (50, 50, 100, 100))
    pygame.display.update()

    while 1:
        ev = pygame.event.wait()
        if ev.type == QUIT:
            pygame.quit()
            sys.exit()
        elif ev.type == MOUSEBUTTONUP:
            animation()


def animation():
    pygame.event.set_blocked(MOUSEBUTTONUP)
    for x in range(10, 101, 10):
        pygame.draw.rect(DS, BGCOLOR, (150 - x,50,x,100))
        pygame.display.update()
        CLOCK.tick(FPS)
    pygame.time.wait(2000) # 2 seconds
    for x in range(10, 101, 10):
        pygame.draw.rect(DS, RECTCOLOR, (50,50,x,100))
        pygame.display.update()
        CLOCK.tick(FPS)
    pygame.event.set_allowed(MOUSEBUTTONUP)

if __name__ == '__main__':
    main()

なぜこのような振る舞いをするのでしょうか?おそらく、システムは一時停止の瞬間と 2 番目の for ループのティックとの間で同期していません。

PS: 私は Windows 7 を使用しており、母国語ではない英語で申し訳ありません

4

3 に答える 3

1
pygame.time.wait(1000) # 2 seconds

これにより、コードがここで 2 秒間一時停止します。したがって、2 秒後までイベントは取得されません。

アニメーションまたはタイマーにはget_ticks()を使用する必要があります。

于 2013-09-09T19:42:35.427 に答える
1

2つのこと:

次のようなループを実行すると:

for x in range(10, 101, 10):
        pygame.draw.rect(DS, BGCOLOR, (150 - x,50,x,100))
        pygame.display.update()

アニメーションを描画しますが、pygame にはオペレーティング システムから取得したメッセージを処理する機会がありません。これを回避するには、ループ内でpygame.event.pump()orを呼び出す必要があります。pygame.event.get()

ドキュメントから:

pygame.event.pump()

ゲームのフレームごとに、イベント キューに対して何らかの呼び出しを行う必要があります。これにより、プログラムがオペレーティング システムの残りの部分と内部的にやり取りできるようになります。ゲームで他のイベント関数を使用していない場合は、pygame.event.pump() を呼び出して、pygame が内部アクションを処理できるようにする必要があります。

プログラムが他の pygame.event 関数を通じてキュー上のイベントを一貫して処理している場合、この関数は必要ありません。

イベント キューには、内部的に処理しなければならない重要なものがあります。メイン ウィンドウを再描画するか、システムに応答する必要がある場合があります。イベント キューの呼び出しに長時間失敗すると、システムはプログラムがロックされたと判断する場合があります。

また、ウィンドウを動かしている間、ゲームがフリーズします。これは SDL の既知の制限です (pygame は SDL のシン ラッパーに過ぎないことを思い出してください)。Windows メッセージ ループが原因です。ウィンドウを移動またはサイズ変更すると、Windows はモーダル ループを使用し、ゲームが実行されるスレッドをブロックします。 .

于 2013-09-09T12:18:51.830 に答える
1

ループを 1 つだけ使用し、変数またはユーザー イベントを使用してゲームの状態を追跡することをお勧めします。

例:

game_state = 0

def main():
    global game_state
    rectangle_ticks = 0

    while 1:
        events = pygame.event.get()   # Get all pending events

        for ev in events:
            # Process events
            if ev.type == QUIT:
                pygame.quit()
                sys.exit()

            elif ev.type == MOUSEBUTTONUP:
                game_state = 1
                pygame.time.set_timer(pygame.time.set_timer(pygame.USEREVENT + 1, 1000)

            elif ev.type == pygame.USEREVENT + 1:
                pygame.time.set_timer(pygame.time.set_timer(pygame.USEREVENT + 1, 0)
                game_state = 2

        # Clear screen
        DS.fill(BGCOLOR)

        # Draw game state
        pygame.draw.rect(DS, RECTCOLOR, (50, 50, 100, 100))
        animation()

        # Update screen
        pygame.display.flip()

        CLOCK.tick(FPS)

def animation():
    if game_state == 1:
        for x in range(10, 101, 10):
            pygame.draw.rect(DS, BGCOLOR, (150 - x,50,x,100))

    if game_state == 2:
        for x in range(10, 101, 10):
            pygame.draw.rect(DS, RECTCOLOR, (50,50,x,100))

ティックごとに画面全体を描画するのは奇妙に見えるかもしれませんが、描画を続けたくない古いオブジェクトを取り除くために pygame で作業する通常の方法です。

于 2013-09-09T13:41:42.120 に答える