Estou tentando desenvolver um jogo simples feito com Pygame (biblioteca Python).
Eu tenho um sprite
objeto que é o player
e movo-o usando as setas. Se eu não mover o mouse, o sprite se moverá normalmente, mas quando movo o mouse, o sprite se moverá mais rápido (como x2 ou x3). O player
objeto está dentro da charsGroup
var.
Eu executei o jogo no W7 e no Ubuntu. A mesma coisa acontece nos dois sistemas operacionais.
Eu tenho mais entidades que se movem como NPCs e balas, mas elas não são afetadas, apenas o jogador. Diante disso, acho que o problema talvez tenha uma conexão direta com o sistema de movimentação do player (teclas de seta).
Aqui está o update()
método do player
objeto:
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
E aqui está o 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()
Não sei o que mais você pode precisar para me ajudar, mas qualquer coisa que você precise (mais informações ou código) é só pedir!
BULLET_IMAGE = pygame.image.load("bullet.png")
e depoisself.bulletsGroup.add(Bullet(BULLET_IMAGE...
Respostas:
tl; dr não misture seu loop de eventos com seu loop de jogo .
Quando você move o mouse, o jogo recebe uma carga de
pygame.MOUSEMOTION
eventos. Na verdade, você não usa esses eventos para atualizar a posição do mouse, mas está obtendo o estado atual do mousepygame.mouse.get_pos()
. Isso é ineficiente, mas não é o problema.O problema é que você está atualizando a posição do jogador dentro do loop de eventos !
Isto é o que deveria acontecer:
Isto é o que seu código faz:
Quando você move o mouse, o loop de eventos é executado várias vezes por quadro. Mas quando você verifica com quais teclas é pressionada
pygame.key.get_pressed()
, elas permanecem pressionadas até você soltar, algum tempo depois. Portanto, à medida que o loop de eventos estiver agitando os eventos de movimentação do mouse, ele reaplicará os movimentos da reprodutora repetidamente.A solução é simples: mova o player para fora do loop de eventos.
fonte
pygame.mouse.get_pos()
é ineficiente? Que alternativas eu tenho?pygame.mouse.get_pos()
obtém a posição mais recente do mouse, independentemente da fila de eventos, portanto, não há necessidade de colocá-lo dentro do loop de eventos. A alternativa seria processarpygame.MOUSEMOTION
você mesmo, mas, a menos que você precise de todos os eventos (por exemplo, você esteja escrevendo um programa de pintura), a última posição será necessária.Aqui estão mais algumas reflexões para complementar a resposta existente .
O Gaffer On Games tem um ótimo artigo sobre loops de jogos que foi mencionado em todos os lugares.
O loop do seu jogo deve ter diferentes estágios independentes: Entrada, Atualização, Render.
Você pode, por exemplo, ler entradas 30 vezes por segundo (ou em tempo real para obter melhor capacidade de resposta), fazer 30 atualizações por segundo e renderizar 60 quadros por segundo, ou quaisquer valores que funcionem bem para o seu jogo.
fonte