bclose

Gráficos con Pygame

Pequeños programas para ir entrando en calor

Primeros gráficos con Pygame

 
    • Empezaremos a usar las primitivas gráficas de Python / Pygame.
    • Dibujaremos unas lineas..
    • Haremos un primer programa que dibuje un circulo para sentar las bases de gráficas mas complicada.
 

Material requerido.

 

Vista lateral Una Raspberry Pi 3, aunque valen la 2 y la 1

 

 

Introducción a Pygame

 

En la sesión anterior vimos cómo crear una pantalla en Python Pygame que podamos usar como fondo para nuestros programas, y también vimos que tenemos que plantear una condición de salida para que cuando alguien pinche en el botón de cerrar lo detectemos y acabemos con el programa. Lo que vimos allí va a ser el armazón básico sobre el que montaremos nuestros programas Pygame

Siguiendo con esta pequeña introducción a Pygame que hemos planteado, es el momento de empezar a ver que primitivas gráficas tenemos disponibles para dibujar en esa pantalla de forma que podamos hacer nuestros primeros pasitos en Pygame

En la última sesión, creamos una especie de programa tipo que podemos usar como marco base para todo lo que mencionamos y lo usaremos para ir añadiendo instrucciones graficas

import pygame, sys
from pygame.locals import *

pygame.init()
Display = pygame.display.set_mode((600,400))
pygame.display.set_caption("Prometec")

while True:
    for event in pygame.event.get():
        if event.type() == quit:
            pygame.quit()
            sys.exit()
Pygame.display.upadate()

Bueno lo primero que nos gustaría hacer por pura sencillez es usar alguna instrucción sencilla como dibujar una línea en la pantalla. ¿Inocente no? Y para eso hay una primitiva disponible que podemos usar directamente:

pygame.draw.line(screen, color, closed, (x1,y1), (x2,y2), thickness)

Donde screen es la pantalla que creamos antes, el color se especifica como RGB y la lista de puntos son conjuntos de valores x,y entre los que queremos dibujar

Vamos con un ejemplo, si queremos dibujar una línea desde el punto (0,0) hasta el punto (300,100), podemos hacer algo así:

Color = ( 200,200,255)  
Pygame.draw.line (Display,Color,(0,0), (300,100))
Pygame.display.upadate()

while True:
    for event in pygame.event.get():
        if event.type() == quit:
            pygame.quit()
            sys.exit()

Y el resultado será este:

Aquí tenemos la primera sorpresa. Fíjate que aunque en el cole siempre nos enseñaron que el punto 0,0 era la esquina inferior izquierda, en los gráficos por ordenador, rara vez lo es (Salvo que lo adaptes tú) y en Pygame el punto (0,0) es la esquina superior izquierda, no la inferior, ojo con esto.

El color lo especificamos como una terna de valores entre paréntesis que indica la saturación de cada componente (R, G, B) y que hemos definido previamente. Y finalmente podemos especificar o no, el grosor de la línea.

Imagínate que cambiamos color a

Color = ( 0,255,200)
while True:
   Pygame.draw.line(Display,Color,(0,0), (300,100), 5)
   Pygame.display.upadate()
Modificando el grosor de una linea

Hemos cambiado el tono de color y además el último parámetro nos permite definir el grosor de la línea (O no ponerlo en absoluto, porque es una función con overload claro)

Y ya que estamos en estas, vamos a aprovechar para comentar que uno de los errores más típicos que suelen cometer los novatos es omitir por despiste la instrucción:

Pygame.display.upadate()

Lo que provoca que no se muestre nada en la pantalla. La razón es que Pygame usa doble buffer para escribir en la pantalla y los cambios solo se muestran cuando invocas el refresco con update(). Recordad esto y os ahorrareis un montón de dolores de cabeza.

 
  • Tanto el color, que pasamos entre paréntesis, como los puntos (x,y) son lo que en Python se llaman tuples. Pronto hablaremos de que son y para qué sirve pero de momento quédate con la idea de que un conjunto de valores separados por comas entre paréntesis son un tipo especial de Python llamado tuple.  

Podemos jugar un poco asignando un fondo blanco a nuestra ventana y dibujando varias líneas consecutivas

Azul = (100,255,200)
Blanco =(255,255,255)
Negro = (0,0,0)

Display.fill(Blanco) # Rellena el fondo a blanco
pygame.draw.line(Display, Negro, (0,0), (200,100))
pygame.draw.line(Display, Negro, (200,100), (200,280))
pygame.draw.line(Display, Negro, (200,280) , (280,150)
Pygame.display.circle(Display, Azul, (200,150), 100,2)
pygame.display.update()
Lineas y circulos

Es de lo más sencillo dibujar primitivas desde Pygame como podéis ver y no es cuestión de ponernos aquí a hacer listas de posibilidades porque las encontrareis sin problemas en Google, Así que vamos a dibujar algo con un poco más sentido.

Personalmente siempre intento dibujar un circulo a  mano como mi primer programa gráfico en cualquier lenguaje, porque supone mezclar una serie de conceptos interesantes, y por ello vamos con el tema.

 
  • Si, ya sé que hay una instrucción que los dibuja, pero creo que va a ser de lo más instructivo.  

 

Dibujando un circulo

 

La mayor parte de la gente intenta usar Pygame para hacer juegos (De ahí su nombre) pero personalmente encuentro mucho mi interesante usarlo para hacer gráficos matemáticos o de cualquier tipo, y para eso necesitamos un poquito de trigonometría (Cerrar las puertas, que no huya nadie)

Sé que la trigonometría aterra mucho debido a las palizas que nos dieron en el cole, pero en serio, es bastante fácil y te permite hacer todo tipo de gráficos simpáticos rápidamente. Por ejemplo imagínate que queremos hacer una ventana de 720 x 400 y dibujar un círculo más o menos centrado ¿Cómo podríamos hacer un programa así?

Tenemos como siempre que empezar con los import:

Import pygame, sys, math
From pygame locals import *

pygame.init()
Display = pygame.display.set_mode((600,400))
pygame.display.set_caption("Prometec")

Fijaros que en esta ocasión hemos importado math, una librería que tiene todo lo necesario para amargaros la vida si estas cosas no os van, incluyendo trigonometría. Si hacéis un esfuerzo para recordar cómo era ese asunto:

calculando puntos

La trigonometría (Disfrutad)  nos permite calcular los puntos x,y que forman un circulo de un modo muy sencillo, Bastan este par de operaciones (No hace falta que te lo aprendas, basta con que copies la formulas):

x = Radio * Seno ( angulo)
y = Radio * Coseno (angulo)

A medida que vayamos haciendo variar el Angulo entre 0 y 360º (Con un for ), los puntos (x,y) que obtenemos son un circulo. La cosa parece chupada, pero naturalmente hay más de un truco. Lo primero es que nuestro querido Python no calcula la trigo con grados sexagesimales como nos enseñaron de críos, sino con radianes, que es lo mismo, pero asusta mucho más y hace que todo parezca importante y oscuro, aunque es pura fachada. (Los matemáticos son gente con poca vida social y tienen que hacer algo para darse importancia)

Y naturalmente la libreria math nos permite pasar un angulo de grados a radianes mediante la funcion :

math.radians(angulo)

Así que podríamos plantearnos algo como esto:

Radio = 200
x0 = 0
y0 = 0
Blanco =( 100,100,100)

while True:
    for i in range(0, 360):
        angulo = (math.radians(i))
            x1 = Radio * math.sin(angulo )
            y1 = Radio * math.cos(angulo )
            pygame.draw.line(Display, Blanco, (x0,y0),  (x1,y1))
            x0 = x1
            y0 = y1
    pygame.display.update()

Que por supuesto conviene que expliquemos un poquito. Empezamos definiendo el radio del circulo que nos interesa para después calcular el punto ( x1,y1 )  correspondiente al Angulo que vamos barriendo. Queremos dibujar una línea que vaya del nuevo punto al último que calculamos, y como al principio no tenemos ninguno, nos conviene definirlos antes como ( x0,y0 )

Si intentamos este programa, lo que obtendremos será:

un cuadrante

Que sorprendentemente se parece mucho a lo que pretendíamos, pero que solo nos ha dibujado un cuadrante. ¿Por qué?

Pues simplemente porque el centro del circulo es (0,0) y nos convendría que fuera un punto un poco más centrado en la pantalla como él (320, 200) y basta con sumarle esas cantidades a la hora de calcular la x e y de los puntos del circulo:

while True:
    for i in range(0, 166):
        angulo = (math.radians(i))
            x1 = Radio * math.sin(angulo ) + 320
            y1 = Radio * math.cos(angulo ) + 200
            pygame.draw.line(Display, Blanco, (x0,y0),  (x1,y1))
            x0 = x1
            y0 = y1
    pygame.display.update()

 

Dibujando un circulo completo

Que va pareciéndose más a lo que queríamos, pero… ¿Y esa línea?

Como hemos definido x0=0 e y0=0, la primera línea se traza desde el punto (0,0) al primer punto que calculamos y para arreglarlo basta con hace que x0,y0 tengan el mismo valor que este primer punto.

x0 = 360
y0 = 400
k = 200
Blanco =( 100,100,100)

while True:
    for i in range(0, 360):
       angulo = (math.radians(i))
       x1 = k * math.sin(angulo )  + 320
       y1 = k * math.cos(angulo )  + 200
       pygame.draw.line(Display, Blanco, (x0,y0),  (x1,y1))
       x0 = x1
       y0 = y1
pygame.display.update()
dibujando un circulo limpio

Una última curiosidad. La ventaja del sistema de cálculo gráfico mediante trigonometría es que podemos plotear casi lo que se te ocurra en pantalla con una cierta facilidad. Por ejemplo ¿Qué crees que pasaría si en el programa anterior partimos de Radio = 0 y añadimos una línea como esta en el bucle que dibuja el circulo?

Radio = Radio + 0.1

¿Adivinas lo que va a ocurrir? Piensa un poco a ver si se te ocurre.

Pues sencillamente que a medida que giramos el vamos modificando el radio del circulo de un modo casi inapreciable, pero a medida que va creciendo el circulo se abre y dibuja una espiral:

Dibujando una espiral forzada

Puedes aumentar o disminuir lo que añades al radio para apretar mas o menos la espiral

 

Resumen de la sesión

 

 
    • Empezamos a usar algunas primitivas de pygame par ver como dibujar graficos.
    • Repasamos un poc la trigonometria porque dibujar graficos es muy sencillo si usamos coordenadas polares y no queriamos vaciar la sala.
    • Vimos como dibujar una espiral. 

 

No Comments

Give a Reply

WordPress Anti-Spam by WP-SpamShield