マウスを動かすと、スプライトプレーヤーの動きが速くなるのはなぜですか?


17

Pygame(Pythonライブラリ)で作られたシンプルなゲームを開発しようとしています。

spriteオブジェクトがあり、player矢印キーを使用して移動します。マウスを動かさないと、スプライトは普通に動きますが、マウスを動かすと、スプライトは速く動きます(x2やx3など)。playerオブジェクトが内部にあるcharsGroupVAR。

ゲームをW7とUbuntuで実行しました。両方のOSで同じことが起こります。

NPCや弾丸のように動くエンティティがもっとありますが、影響を受けるのはプレイヤーだけです。これを考えると、問題はおそらくプレイヤーの移動システム(矢印キー)と直接関係があると思います。

オブジェクトのupdate()メソッドは次のplayerとおりです。

def update(self):

    for event in pygame.event.get():
        key = pygame.key.get_pressed()
        mouseX, mouseY = pygame.mouse.get_pos()
        if event.type == pygame.MOUSEBUTTONDOWN:
            self.bulletsGroup.add(Bullet(pygame.image.load("bullet.png"),
                                          self.rect.x + (self.image.get_width()/2),
                                           self.rect.y + (self.image.get_height()/2),
                                            mouseX, mouseY, 50, 50))

        if key[pygame.K_RIGHT]:
            if not self.checkCollision():
                self.rect.x += 10
            else:
                self.rect.x -= 10
        if key[pygame.K_LEFT]:
            if not self.checkCollision():
                self.rect.x -= 10
            else:
                self.rect.x += 10
        if key[pygame.K_UP]:
            if not self.checkCollision():
                self.rect.y -= 10
            else:
                self.rect.y += 10
        if key[pygame.K_DOWN]:
            if not self.checkCollision():
                self.rect.y += 10
            else:
                self.rect.y -= 10

そして、ここにwhileループがあります:

while True:

    if PLAYER.healthBase <= 0:
        GAMEOVER = True

    if not GAMEOVER:
        mapTilesGroup.draw(SCREEN)
        charsGroup.update()
        charsGroup.draw(SCREEN)
        npcsGroup.update()
        npcsGroup.draw(SCREEN)
        drawBullets()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

    if GAMEOVER:
        myfont = pygame.font.SysFont("monospace", 30)
        label = myfont.render("GAME OVER!", 1, (255, 255, 0))
        SCREEN.blit(label, (400, 300))

    freq.tick(0)

    pygame.display.flip() 

あなたが私を助けるためにこれ以上何が必要なのかわかりませんが、あなたが必要とするもの(詳細情報またはコード)はそれを尋ねるだけです!


5
実際、多くのアプリケーションには正確なバグが存在します。大きなドキュメントでドラッグ選択し、カーソルを端から移動してみてください。通常、プログラムのエッジスクロールが開始され、徐々にドキュメントが選択されます。マウスを左右に動かすと、スクロール速度がイベントループに結び付けられ、Xモーションがイベントループを繰り返し起動するため、通常ははるかに速くスクロールします。
ベンジャクソン

2
@BenJacksonスクロールが最初から恐ろしく遅い場合、それは有用なバグであることがわかりました。
user253751

1
これはバグとは関係ありませんが、イメージを一度ロードして、オブジェクトに保存することをお勧めします。BULLET_IMAGE = pygame.image.load("bullet.png")その後self.bulletsGroup.add(Bullet(BULLET_IMAGE...
-DJMcMayhem

@DJMcMayhemあなたは完全に正しい、私は残りの画像でそれをやったが、私はこれでそれを逃した..ありがとう!:)
ドラムンバス

回答:


43

tl; dr イベントループゲームループを混在させないでください

マウスを動かすと、ゲームは大量のpygame.MOUSEMOTIONイベントを受け取ります。これらのイベントを実際に使用してマウスの位置を更新するわけではありませんが、次のようにしてマウスの現在の状態を取得しています。pygame.mouse.get_pos()ます。それは非効率的ですが、それは問題ではありません。

問題は、イベントループ内でプレーヤーの位置を更新していることですです!

これが起こるはずです。

game loop:
    event loop # get key presses, mouse moves etc.)
    if key pressed in the event loop:
        move the player

これはあなたのコードが行うことです:

game loop:
    event loop:
        if key pressed:
            move the player

マウスを動かすと、イベントループがフレームごとに何度も実行されます。しかし、どのキーが押されているかを確認するときpygame.key.get_pressed()、しばらくしてから離すまで押されたままになります。そのため、イベントループはマウス移動イベントをめぐって変動しているため、プレーヤーの動きを繰り返し適用します。

解決策は簡単です。プレーヤーをイベントループの外側に移動します。


1
ありがとう!今では完全に機能し、おそらく何が起こっているのか私は理解していなかったでしょう!ところで、なぜそれpygame.mouse.get_pos()が非効率だと言うのですか?どのような選択肢がありますか?
ドラムンバス

こんにちは、@ congusbongus、それを説明してもらえますか?ありがとう。
ドラムンバス

@Drumnbass pygame.mouse.get_pos()は、イベントキューに関係なく、マウスの最新の位置を取得するため、イベントループ内に配置する必要はありません。代わりにすべてをpygame.MOUSEMOTION自分で処理することもできますが、すべてのイベントが必要な場合(たとえば、ペイントプログラムを作成している場合)を除き、最新のポジションで対応します。
コンガスボン

3

ここに、既存の答えを補完するいくつかの考えがあります

Gaffer On Gamesに、ゲームループに関するすばらしい記事がありどこでも参照されています。

ゲームループには、入力、更新、レンダリングという異なる独立したステージが必要です。

たとえば、1秒間に30回(または応答性を向上させるためにリアルタイムで)入力を読み取り、1秒間に30の更新を行い、1秒間に60フレームをレンダリングするか、ゲームに適した値を入力できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.