Movimiento circular en Pygame (animación de cañón)

Un dibujo puede moverse de forma circular, si obtenemos las coordenadas que formen una circunferencia esto puede hacerse si usamos las siguientes relaciones.
Coordenadas polares: es un sistema de coordenadas bidimensional en el cual cada punto del plano se determina por una distancia y un ángulo.

Si la trayectoria del objeto debe seguir en forma circular se pueden calcular sus coordenadas en (x,y), a partir de coordenadas polares.

x = r + a * cos(t)
y = r + b * sen(t)

Veamos el siguiente ejemplo:
Si el punto centro que es dado por (a, b), es el punto (100, 100) y queremos que una figura gire al rededor de ese punto a una distancia de r = 50, el código que dibuja la trayectoria de esa figura seria el siguiente.
Los valores de t (ángulo) van de 0 a .

 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
import pygame
import math

ROJO = (255, 0, 0)
AZUL = (0, 0, 255)
VERDE = (0, 255, 0)
NEGRO = (0, 0, 0)

pygame.init()
dimensiones = [500, 600]
pantalla = pygame.display.set_mode(dimensiones)
pygame.display.set_caption("-------- Animación ------")
juego_terminado = False
reloj = pygame.time.Clock()
t = 0
while juego_terminado is False:
    for evento in pygame.event.get():
        if evento.type == pygame.QUIT:
            juego_terminado = True
    t += 20
    if t >= 360:
        t = 0
    x = round(50 * math.cos(math.radians(t)) + 100)
    y = round(50 * math.sin(math.radians(t)) + 100)
    pantalla.fill(NEGRO)
    pygame.draw.circle(pantalla, AZUL, [100, 100], 2)
    pygame.draw.line(pantalla, VERDE, [100, 100], [150, 100])
    pygame.draw.circle(pantalla, ROJO, [x, y], 5)
    pygame.display.flip()
    reloj.tick(20)
pygame.quit()


Para obtener el resultado de la imagen se comento la línea 25 que es la que limpia la pantalla cada ciclo, esto para poder distinguir con más claridad el recorrido que hace la figura en la pantalla. También se dibujan el punto centro en azul y el radio de la circunferencia en verde.

El valor del ángulo es calculado cada ciclo del juego para ir aumentando su valor de 0 a 360, en este ejemplo el aumento es de 20 para poder dejar ese espacio que se puede observar en la imagen. En la línea 21 se comprueba si el valor de t a alcanzado los 360 y volvemos a 0 otra vez, esto podría funcionar sin volver a 0 y que el valor de t se siga aumentando, pero esto servirá para saber en que ángulo se encuentra la figura. Las líneas 23 y 24 son suficientes para calcular las coordenadas (x, y) de la figura.

Ahora veamos un ejemplo más elaborado.


En este ejemplo se requiere mover el cañón al rededor de su base, este cañón es representado por una línea, ya que para dibujar una linea necesitamos el punto a inicial y b final, estas coordenadas estarán dadas por las coordenadas de una circunferencia de radio = 18 para el punto a, y las coordenadas del punto b por una circunferencia de radio = 30, Así podremos obtener que el cañón pueda moverse en los ángulos correctos de acuerdo a su trayectoria.


1
2
3
4
5
6
7
def dibujaCanion(pantalla, xy, angulo):
    x, y = xy
    CoordCanion = puntosCanion(xy, angulo, 30, 18)
    pygame.draw.circle(pantalla, MARRON, xy, 20)
    pygame.draw.rect(pantalla, NEGRO, [x - 30, y, 60, 40])
    pygame.draw.line(pantalla, GRAFITO, CoordCanion[0], CoordCanion[1], 6)
    return CoordCanion[0]

La función anterior la utilizamos para dibujar el cañón y retornar las coordenadas en que se encuentra la punta del cañón.
La función puntosCanion es usada para calcular las coordenadas rectangulares del punto inicial y final de la línea que representa el cañón.

1
2
3
4
5
def puntosCanion(ab, angulo, radio1, radio2):
    puntos = []
    puntos.append(xyCircunferencia(angulo, ab, radio1))
    puntos.append(xyCircunferencia(angulo, ab, radio2))
    return puntos

Hemos pasado a una función el cálculo de las coordenadas (x, y) para reutilizar el código.


1
2
3
4
5
def xyCircunferencia(t, centro, radio):
    t = math.radians(t)
    x = radio * math.cos(t) + centro[0]
    y = radio * math.sin(t) + centro[1]
    return [round(x), round(y)]

La parte principal del juego queda de la siguiente forma.

 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
def main():
    pygame.init()
    pantalla = pygame.display.set_mode(dimensiones)
    pygame.display.set_caption("-------- Animación ------")
    juego_terminado = False
    reloj = pygame.time.Clock()
    a = 185
    av = 1
    xv = 1
    yv = 1
    y, x = [1, 1]
    disparo = False
    while juego_terminado is False:
        for evento in pygame.event.get():
            if evento.type == pygame.QUIT:
                juego_terminado = True
        a += av
        if a > 355 or a < 185:
            av *= -1
        pantalla.fill(AZUL)
        dibujaCanion(pantalla, [200, dimensiones[1] - 10], a)
        if a == 290:
            CoordCanion = puntosCanion([200, dimensiones[1] - 10], a, 30, 18)
            x, y = CoordCanion[0]
            disparo = True
        if a == 185:
            disparo = False
        if x > 395 or x < 5:
            xv *= -1
        if y > 295 or y < 5:
            yv *= -1
        if disparo:
            pygame.draw.circle(pantalla, (255, 0, 0), [x, y], 4)
            x += xv
            y -= yv
        pygame.display.flip()
        reloj.tick(20)
    pygame.quit()


if __name__ == "__main__":
    main()

En la línea 21 se dibuja el cañón, las coordenadas que se le pasan son las necesarias para dibujar en el centro la base del cañón a, es el ángulo el cual se aumenta en 1 en cada ciclo de 185° a 355° y disminuye de 355° a 185°, Cuando la punta del cañón se encuentra en 290° se produce un disparo, para lo cual a partir de la línea 23 se obtienen las coordenadas rectangulares del cañón, luego en la línea 26 se comprueba si el cañón a regresado a 185° para reiniciar la animación del proyectil.
Las líneas 28 a 35 son necesarias para determinar la trayectoria del proyectil de forma vertical y horizontal.

Animación terminada.

Código fuente completo.
Animación Fuente


Comentarios

  1. hola estoy tratande de hacer el primer ejemplo pero no me deja dice que error en linea 12
    trate de coregirlo i me da otro error

    ResponderEliminar
    Respuestas
    1. Hola!
      Puedes mandarme más detalles sobre los errores que estás teniendo

      Eliminar
    2. cuando guardo el codigo en sublime text despues lo ejecuto en command proud marca error en la linea 3

      Eliminar
    3. En la línea 3 se está importando pygame, ya revisaste que si está instalado correctamente pygame?

      Eliminar
  2. hola no me podras dar un coreo para mandarte los erroes que me salen al poner el codigo

    ResponderEliminar

Publicar un comentario

Entradas populares de este blog

Programando: Media, Varianza y Desviación Estándar en Java, C++ y python

Entrada de datos por teclado en PHP, obtenidos desde un formulario HTML

Prácticas JavaScript: Sumar dos números ingresados por el usuario