Чому мій спрайт-плеєр рухається швидше, коли я переміщую мишу?


17

Я намагаюся розробити просту гру, зроблену з Pygame (бібліотека Python).

У мене є spriteоб'єкт, який є, playerі переміщую його за допомогою клавіш зі стрілками. Якщо я не переміщую мишу, спрайт рухається нормально, але коли я рухаю мишкою, спрайт рухається швидше (наприклад, x2 або x3). playerОб'єкт знаходиться всередині charsGroupвар.

Я запускав гру в W7 та в Ubuntu. Те саме відбувається в обох ОС.

У мене є більше сутностей, які рухаються як 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 Я вважаю, що це буде корисною помилкою, коли прокрутка починається жахливо повільно.
користувач253751

1
Це не пов’язано з вашою помилкою, але я б рекомендував завантажити зображення один раз та зберегти його в об’єкті. BULLET_IMAGE = pygame.image.load("bullet.png")а потім пізнішеself.bulletsGroup.add(Bullet(BULLET_IMAGE...
DJMcMayhem

@DJMcMayhem Ви абсолютно праві, я зробив це з іншими зображеннями, але я пропустив це зробити з цим .. дякую! :)
Drumnbass

Відповіді:


42

тл; д-р , не змішуйте цикл подій з ігровим циклом .

Під час переміщення миші гра отримує набір 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самостійно, але якщо вам не потрібна кожна подія (наприклад, ви пишете програму живопису), остання позиція зробить це.
congusbongus

3

Ось ще кілька думок для доповнення існуючої відповіді .

У Gaffer On Games є чудова стаття про ігрові петлі, на яку посилаються всюди.

Ваш цикл гри повинен мати різні незалежні етапи: введення, оновлення, візуалізація.

Наприклад, ви можете прочитати вводи 30 разів на секунду (або в режимі реального часу для кращої реакції), зробити 30 оновлень за секунду і зробити 60 кадрів в секунду, або будь-які значення, які добре працюють для вашої гри.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.