Entrada destacada

Como usar enums en Android, kotlin

Mover objetos con el teclado en Pygame

En este tutorial se muestra como mover objetos de dibujo en la pantalla utilizando el teclado, para lo cual usaremos un ejemplo anterior en el que se simulaba una pista de carreras en la cual los objetos se movían pero de manera automática. Haremos algunas modificaciones a ese ejemplo para poder interactuar con la escena.
El ejemplo anterior puede verlo en el siguiente link: AnimacionesBasicas


Mover el objeto en la pantalla en distintas direcciones

Comenzaremos con un programa base que dibuje la pista y dibuje un rectángulo azul que representara el personaje que moveremos.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import pygame
import random

NEGRO = (10, 8, 12)
COLOR_PISTA2 = (50, 58, 52)
BLANCO = (255, 255, 255)
VERDE = (90, 232, 64)
ROJO = (255, 20, 20)
AZUL = (10, 222, 255)
COLOR_FUENTE = (255, 122, 88)


def dibujar_texto(screen, texto, pos):
    fuente = pygame.font.SysFont('Barber Street_PersonalUseOnly', 50)
    text = fuente.render(texto, 1, COLOR_FUENTE)
    screen.blit(text, pos)


def dibujar_pista(x_pista, ancho, color_pista):
    pygame.draw.rect(pantalla, color_pista, [x_pista, 0, ancho, dimensiones[1]])
    for i in range(10, dimensiones[1], 20):
        pygame.draw.rect(pantalla, BLANCO, [234, i, 6, 8])


pygame.init()

dimensiones = [480, 600]
pantalla = pygame.display.set_mode(dimensiones)
pygame.display.set_caption("Animaciones")

auto = [185, 540, 40, 54]
velocidad_auto = 0

inicio_pista = 160
ancho_pista = 160

game_over = False
reloj = pygame.time.Clock()

while not game_over:
    for evento in pygame.event.get():
        if evento.type == pygame.QUIT:
            game_over = True
    pantalla.fill(VERDE)
    dibujar_pista(inicio_pista, ancho_pista, NEGRO)
    pygame.draw.rect(pantalla, AZUL, auto)
    pygame.display.flip()
    reloj.tick(60)

pygame.quit()



Para detectar cuando una tecla es pulsada podemos incluir un condición dentro de la lectura de la lista de eventos en el bucle principal, debemos comprobar si el tipo del evento es igual a pygame.KEYDOWN, con esto podremos saber si alguna tecla ha sido pulsada, una vez que sabemos que una tecla a sido pulsada necesitamos saber de que tecla se trata. 

Agregamos el siguiente código después de la línea 43.


44
45
46
47
48
49
50
        if evento.type == pygame.KEYDOWN:
            if evento.key == pygame.K_RIGHT:
                velocidad_auto = 2
        if evento.type == pygame.KEYUP:
            if evento.key == pygame.K_RIGHT:
                velocidad_auto = 0
    auto[0] += velocidad_auto

Con el código anterior podremos mover el objeto hacia la derecha si la tecla de dirección derecha es pulsada y usamos una variable velocidad_auto para que el objeto pueda seguir avanzando mientras mantengamos pulsada la tecla. Cuando se detecta que la tecla ha sido liberada (líneas 47 a 49) cambiamos el valor de la velocidad a 0 para que el objeto deje de moverse.

44
45
46
47
48
49
50
51
52
53
54
        if evento.type == pygame.KEYDOWN:
            if evento.key == pygame.K_RIGHT:
                velocidad_auto = 2
            if evento.key == pygame.K_LEFT:
                velocidad_auto = -2
        if evento.type == pygame.KEYUP:
            if evento.key == pygame.K_RIGHT:
                velocidad_auto = 0
            if evento.key == pygame.K_LEFT:
                velocidad_auto = 0
    auto[0] += velocidad_auto

Para movernos a la derecha aumentamos el valor de la posición en el eje x, que en este caso está almacenado en el indice cero de la lista auto.
auto[0] : Posición en x
auto[1] : Posición en Y
auto[2] : Ancho del objeto
auto[3] : Alto del objeto

Si para movernos a la derecha sumamos entonces para movernos a la izquierda restamos, la operación en la línea 54 no cambia, sólo volvemos el valor del aumento a negativo y así nos ahorramos algunas líneas de código.

Ahora para mover el objeto hacia arriba y abajo, crearemos una nueva variable de velocidad para 'y' en la línea 31 justo después de velocidad_auto_x.

43
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
        if evento.type == pygame.KEYDOWN:
            if evento.key == pygame.K_RIGHT:
                velocidad_auto_x = 2
            if evento.key == pygame.K_LEFT:
                velocidad_auto_x = -2
            if evento.key == pygame.K_DOWN:
                velocidad_auto_y = 2
            if evento.key == pygame.K_UP:
                velocidad_auto_y = -2
        if evento.type == pygame.KEYUP:
            if evento.key == pygame.K_RIGHT:
                velocidad_auto_x = 0
            if evento.key == pygame.K_LEFT:
                velocidad_auto_x = 0
            if evento.key == pygame.K_DOWN:
                velocidad_auto_y = 0
            if evento.key == pygame.K_UP:
                velocidad_auto_y = 0
    auto[0] += velocidad_auto_x
    auto[1] += velocidad_auto_y

Para mover el objeto en el eje 'y' será similar que para el eje 'x' sólo tenemos que incluir la condiciones correspondientes. En este caso si queremos ir hacia arriba restamos y si queremos ir hacia abajo sumamos. 

Hasta este punto ya podremos mover el objeto en todas direcciones.

Ejemplo final

Ahora agregaremos objetos a los que tengamos que esquivar, comenzado con crear una lista que almacene las coordenadas y medidas de cada objeto justo antes de la lista auto.

31
32
33
34
35
36
37
autos = [[185, 0, 35, 50], [255, -180, 35, 50], [185, -340, 35, 50], [255, -490, 35, 50]]
auto = [185, 540, 35, 54]
velocidad_auto_x = 0
velocidad_auto_y = 0
velocidad = 2
inicio_pista = 160
ancho_pista = 160

También definimos una variable que controle la velocidad de los nuevos objetos.

66
67
68
69
70
71
72
73
74
    pantalla.fill(VERDE)
    dibujar_pista(inicio_pista, ancho_pista, NEGRO)
    pygame.draw.rect(pantalla, AZUL, auto)
    for autoObjeto in autos:
        if autoObjeto[1] > dimensiones[1]:
            autoObjeto[1] = random.randrange(-150, -100)
        pygame.draw.rect(pantalla, ROJO, autoObjeto)
        autoObjeto[1] += velocidad
    velocidad += 0.0005

Para dibujar cada uno de los rectángulos a esquivar usamos un bucle for y los dibujamos de color rojo, en la línea 70 comprobamos si el objeto ha salido de la pantalla para reposicionarlo antes del inicio de la pantalla en el eje 'y'. En cada ciclo aumentamos la posición en y de cada objeto para hacer que se muevan hacia abajo, finalmente en la línea 74 a la variable velocidad aumentamos su valor para que con el tiempo los objetos avancen más rápido.


Ahora detectaremos la colisión entre el objeto azul y los objetos de color rojo implementando la siguiente función.

25 
26
27
28
29
30
def rect_collider(objeto1, objeto2):
    colisiono = False
    if objeto1[0] < objeto2[0] + objeto2[2] and objeto1[0] + objeto1[2] > objeto2[0] and \
            objeto1[1] < objeto2[1] + objeto2[3] and objeto1[1] + objeto1[3] > objeto2[1]:
        colisiono = True
    return colisiono

Con la función rect_collider verificamos si dos objetos entran en contacto, esto se hace comprobando que cualquiera de las esquinas de un rectángulo estén dentro del área del otro.



77
78
79
80
    for autoObjeto in autos:
        game_over = rect_collider(auto, autoObjeto)
        if game_over:
            break

Dentro del bucle for que dibuja los objetos rojos comprobamos si estos han colisionado con el objeto azul si existe colisión salimos del bucle y como la variable game_over pasa a ser True sale del bucle principal y terminamos la ejecución.


Código fuente final

En el siguiente link se muestra el código completo del ejemplo de este tutorial.

Racing.py



Comenta tus dudas en la sección de comentarios.

Comentarios