pos oficial left initialize event down color python pygame movement

python - left - pygame oficial



Pygame: key.get_pressed() no coincide con la cola de eventos (4)

Estoy intentando trabajar con controles simples para una aplicación que usa pygame en Python. Tengo los conceptos básicos funcionando, pero estoy golpeando una pared extraña: estoy usando las teclas de flecha para controlar a mi personaje. Si mantengo presionada una tecla de flecha, mantengo presionada otra tecla de flecha (para moverme diagonalmente), el personaje se mueve como se esperaba. Sin embargo, si suelto la segunda tecla que presioné (mientras mantengo presionada la primera tecla), el personaje deja de moverse, aunque todavía estoy presionando esa primera tecla. Aquí está mi código de movimiento simple:

for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == KEYDOWN: if pygame.key.get_pressed()[K_LEFT]: player.pos = (player.pos[0] - 2, player.pos[1]) if pygame.key.get_pressed()[K_RIGHT]: player.pos = (player.pos[0] + 2, player.pos[1]) if pygame.key.get_pressed()[K_UP]: player.pos = (player.pos[0], player.pos[1] - 2) if pygame.key.get_pressed()[K_DOWN]: player.pos = (player.pos[0], player.pos[1] + 2)

Ahora, naturalmente estaba muy confundido por esto. Así que traté de imprimir algunas líneas para depurar. En la parte superior del ciclo de control principal, escribí:

print (pygame.key.get_pressed()[K_DOWN], pygame.key.get_pressed()[K_RIGHT]) print pygame.event.get()

... para mostrar una tupla que muestra el estado de las teclas de flecha hacia abajo y derecha, y luego muestra la cola de eventos de pygame. Mis resultados me desconcertaron aún más. Si muevo el personaje en diagonal hacia abajo y hacia la derecha, presionando la tecla hacia abajo primero y luego la derecha, luego suelto la tecla derecha para hacer que se mueva simplemente hacia abajo, el personaje deja de moverse como antes ... pero esto se imprime en el caparazón:

(1, 0) []

Es decir, cuando suelto la tecla de la flecha hacia la derecha y sigo manteniendo presionada la tecla de la flecha hacia abajo, pygame.key.get_pressed () entiende que la tecla con la flecha hacia abajo todavía se mantiene presionada, pero no hay nada en la cola del evento.

Además, antes en el código (antes del ciclo de control) estoy invocando

pygame.key.set_repeat(1, 2)

para hacer que el personaje continúe moviéndose mientras se mantiene presionada la tecla.

¡Cualquier ayuda será apreciada! Gracias :)


Está utilizando una entrada basada en eventos, pero en este caso desea una entrada basada en encuestas. Entonces no te metas con repeticiones de teclas.

import pygame from pygame.locals import * done = False player.pos = Rect(0,0,10,10) while not done: for event in pygame.event.get(): # any other key event input if event.type == QUIT: done = True elif event.type == KEYDOWN: if event.key == K_ESC: done = True elif event.key == K_F1: print "hi world mode" # get key current state keys = pygame.key.get_pressed() if keys[K_LEFT]: player.pos.left -= 10 if keys[K_RIGHT]: player.pos.left += 10 if keys[K_UP]: player.pos.top -= 10 if keys[K_DOWN]: player.pos.left += 10 if keys[K_SPACE]: print ''firing repeated gun''


Mi suposición es que la repetición de series no funciona de la manera que crees que será. Básicamente, después de que su segunda tecla sube, la repetición no ocurre. Esto parece tener sentido para mí: abra un editor de texto y mantenga presionada la tecla "A". "A" se extenderá a través de la pantalla. Luego, presione la tecla "J" con la tecla "A" aún presionada. La parada "A". Ese es un sistema típico de repetición de teclas.

No estoy seguro de que el uso de este método "set_repeat" vaya a funcionar al final de todos modos. Básicamente, cualquier tecla que pulse el jugador ahora "repetirá", incluso si hacen clic en "disparar" o "saltar".

Como alternativa, intente guardar el estado cuando el usuario presiona o suelta. No use set_repeat, pero haga algo como lo siguiente:

for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == KEYDOWN: if pygame.key.get_pressed()[K_LEFT]: player.moving_left = True if pygame.key.get_pressed()[K_RIGHT]: player.moving_right = True if pygame.key.get_pressed()[K_UP]: player.moving_up = True if pygame.key.get_pressed()[K_DOWN]: player.moving_down = True elif event.type == KEYUP: if pygame.key.get_pressed()[K_LEFT]: player.moving_left = False if pygame.key.get_pressed()[K_RIGHT]: player.moving_right = False if pygame.key.get_pressed()[K_UP]: player.moving_up = False if pygame.key.get_pressed()[K_DOWN]: player.moving_down = False # Somewhere else in your game loop... if player.moving_left: player.pos[0] -= 2 if player.moving_right: player.pos[0] += 2 if player.moving_up: player.pos[1] -= 2 if player.moving_right: player.pos[1] += 2


Para cosas como el movimiento, no debe verificar los eventos (como KEYDOWN o KEYUP ), pero revise cada iteración de su mainloop si se presionan sus teclas de movimiento (usando get_pressed ).

En su código, usted verifica las teclas presionadas solo si también hay un evento KEYDOWN .

También hay algunas otras cosas a considerar:

  • Debería separar el mapeo de teclas y la velocidad de su reproductor, por lo que más adelante será más fácil cambiar cualquiera de estos.

  • Debería determinar un vector de movimiento y normalizarlo primero, ya que de lo contrario, si su velocidad de movimiento vertical y horizontal es 10 , su velocidad de movimiento diagonal sería ~ 14 .

Ejemplo de trabajo:

import pygame import math pygame.init() screen = pygame.display.set_mode((200, 200)) run = True pos = (100, 100) clock = pygame.time.Clock() # speed of your player speed = 2 # key bindings move_map = {pygame.K_LEFT: (-1, 0), pygame.K_RIGHT: (1, 0), pygame.K_UP: (0, -1), pygame.K_DOWN: (0, 1)} while run: screen.fill((0, 255, 0)) # draw player, but convert position to integers first pygame.draw.circle(screen, (255, 0, 0), map(int, pos), 10) pygame.display.flip() # determine movement vector pressed = pygame.key.get_pressed() move_vector = (0, 0) for m in (move_map[key] for key in move_map if pressed[key]): move_vector = map(sum, zip(move_vector, m)) # normalize movement vector if necessary if sum(map(abs, move_vector)) == 2: move_vector = [p/1.4142 for p in move_vector] # apply speed to movement vector move_vector = [speed*p for p in move_vector] # update position of player pos = map(sum, zip(pos, move_vector)) for e in pygame.event.get(): if e.type == pygame.QUIT: run = False clock.tick(60)


solo use los datos de retorno de eventos, en lugar de intentar sondear, ya está verificando si se trata de un evento tipo keydown TYPE, ahora solo interrogue al índice KEY, así:

for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == KEYDOWN: if event.key == K_LEFT: player.pos = (player.pos[0] - 2, player.pos[1])

resto del código .....

También considere usar una estructura de datos separada para almacenar el estado de sus controles, luego solo use los eventos para actualizar esa estructura de datos. Eso ayudará a que los controles sean un poco más flexibles ya que no dependerás de la cola del evento para hacer que tu personaje se mueva, lo que en mi experiencia causa problemas como: no poder presionar más de dos botones a la vez, y retraso o problemas de tiempo con los movimientos de los personajes. algo así como:

keystates={''up'':False, ''down'':False, ''left'':False, ''right'':False} running=True #start main pygame event processing loop here while running: for event in pygame.event.get(): if event.type == QUIT: running=False #check for key down events if event.type == KEYDOWN: if event.key == K_UP: keystates[''up'']=True if event.key == K_DOWN: keystates[''down'']=True if event.key == K_LEFT: keystates[''left'']=True if event.key == K_RIGHT: keystates[''right'']=True #check for key up events if event.type == KEYUP: if event.key == K_UP: keystates[''up'']=False if event.key == K_DOWN: keystates[''down'']=False if event.key == K_LEFT: keystates[''left'']=False if event.key == K_RIGHT: keystates[''right'']=False #do something about the key states here, now that the event queue has been processed if keystates[''up'']: character.moveUp() #or whatever your call for these are... if keystates[''down'']: character.moveDown() if keystates[''left'']: character.moveLeft() if keystates[''right'']: character.moveRight() #gracefully exit pygame here pygame.quit()