Mengapa pemain sprite saya bergerak lebih cepat ketika saya menggerakkan mouse?

17

Saya mencoba mengembangkan game sederhana yang dibuat dengan Pygame (Python library).

Saya memiliki spriteobjek yang mana playerdan saya memindahkannya menggunakan tombol panah. Jika saya tidak menggerakkan mouse, sprite bergerak secara normal, tetapi ketika saya menggerakkan mouse, sprite bergerak lebih cepat (seperti x2 atau x3). The playerobjek adalah dalam charsGroupvar.

Saya sudah menjalankan game di W7 dan di Ubuntu. Hal yang sama terjadi di kedua OS.

Saya memiliki lebih banyak entitas yang bergerak seperti NPC dan peluru tetapi mereka tidak terpengaruh, hanya pemainnya. Mengingat ini, saya pikir masalahnya mungkin memiliki koneksi langsung dengan sistem pemain yang bergerak (tombol panah).

Berikut adalah update()metode playerobjek:

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

Dan inilah loop 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() 

Saya tidak tahu apa lagi yang bisa Anda butuhkan untuk membantu saya, tetapi apa pun yang Anda butuhkan (info lebih lanjut atau kode) minta saja!

Drumnbass
sumber
5
Bug Anda sebenarnya ada di banyak aplikasi. Coba seret memilih dalam dokumen besar dan gerakkan kursor Anda dari tepi. Biasanya gulir tepi program akan muncul dan perlahan memilih lebih banyak dokumen. Jika Anda menggerakkan mouse Anda dari sisi ke sisi biasanya akan menggulir lebih cepat, karena kecepatan gulir mereka terikat ke loop acara mereka, dan gerakan X membangunkan loop acara mereka berulang kali.
Ben Jackson
2
@ BenJackson Saya menemukan itu menjadi bug yang berguna ketika menggulir sangat lambat untuk memulai.
user253751
1
Ini tidak terkait dengan bug Anda, tetapi saya akan merekomendasikan memuat gambar satu kali, dan menyimpannya di objek. BULLET_IMAGE = pygame.image.load("bullet.png")dan kemudianself.bulletsGroup.add(Bullet(BULLET_IMAGE...
DJMcMayhem
@DJMcMayhem Anda benar sekali, saya sudah melakukannya dengan sisa gambar tapi saya rindu melakukannya dengan ini .. terima kasih! :)
Drumnbass

Jawaban:

43

tl; dr jangan gabungkan loop acara Anda dengan loop game Anda .

Saat Anda menggerakkan tetikus, game menerima banyak pygame.MOUSEMOTIONacara. Anda tidak benar-benar menggunakan acara ini untuk memperbarui posisi mouse Anda, Anda mendapatkan kondisi saat ini menggunakan mouse pygame.mouse.get_pos(). Itu tidak efisien, tapi bukan itu masalahnya.

Masalahnya adalah Anda memperbarui posisi pemain di dalam loop acara !

Inilah yang seharusnya terjadi:

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

Inilah yang dilakukan oleh kode Anda:

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

Ketika Anda menggerakkan mouse Anda, loop acara akan mengeksekusi berkali-kali per frame. Tetapi ketika Anda memeriksa tombol mana yang ditekan pygame.key.get_pressed(), mereka tetap ditekan sampai Anda melepaskannya, beberapa saat kemudian. Jadi saat loop acara Anda berputar melalui event gerakan mouse, itu akan menerapkan kembali gerakan pemain berulang kali.

Solusinya sederhana: pindahkan pemain ke luar loop acara.

congusbongus
sumber
1
Terima kasih! Sekarang berfungsi dengan baik dan mungkin saya tidak pernah menyadari apa yang terjadi! Btw, mengapa Anda mengatakan itu pygame.mouse.get_pos()tidak efisien? Alternatif apa yang saya miliki?
Drumnbass
Halo, @congusbongus, bisakah Anda menjelaskannya kepada saya? Terima kasih.
Drumnbass
@Drumnbass pygame.mouse.get_pos()mendapatkan posisi terbaru mouse, terlepas dari antrian acara, jadi tidak perlu untuk memasukkannya ke dalam loop acara. Alternatifnya adalah mengolah pygame.MOUSEMOTIONsendiri, tetapi kecuali Anda membutuhkan setiap acara (misalnya Anda menulis program melukis), posisi terakhir akan dilakukan.
congusbongus
3

Berikut adalah beberapa pemikiran untuk melengkapi jawaban yang ada .

Gaffer On Games memiliki artikel hebat tentang loop game yang telah dirujuk di mana-mana.

Putaran game Anda harus memiliki tahapan independen yang berbeda: Input, Perbarui, Render.

Misalnya Anda dapat membaca input 30 kali per detik (atau secara real-time untuk responsif yang lebih baik), melakukan 30 pembaruan per detik dan membuat 60 frame per detik, atau nilai apa pun bekerja dengan baik untuk permainan Anda.

HgMerk
sumber