Saltar a contenido

Juego de bolas

Vamos a crear el clásico juego de una bola rebotando por la pantalla:

Usaremos las teclas Left y Right para mover la paleta y evitar que la bola caiga hasta el borde inferior de la ventana. En la esquina inferior izquierda mostramos la puntuación del juego, que se incrementará cada vez que la bola rebote en la paleta. A medida que aumente la puntuación, el juego se irá acelerando.

Vamos a desarrollar la aplicación en una docena de pasos, añadiendo mejoras en cada paso. Lo primero será crear la ventana.

Crear ventana

El embrión básico de nuestro juego muestra una ventana en blanco:

01CrearVentana.py
 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
class Juego:
    def __init__(self, ventana):
        self.ventana = ventana

        # Configurar ventana
        self.ventana.title('Bola')
        self.ventana.resizable(False, False)
        self.ventana.wm_attributes('-topmost', True)

        # Crear lienzo
        self.lienzo = tkinter.Canvas(self.ventana,
                                     width=500,
                                     height=400,
                                     bd=0)
        self.lienzo.pack()
        self.ventana.update()

    def bucle(self):
        while True:
            self.ventana.update_idletasks()
            self.ventana.update()

v = tkinter.Tk()
juego = Juego(v)
juego.bucle()
juego.ventana.update_idletasks()
juego.ventana.destroy()

Comenzamos por definir una clase que representa al juego y sus componentes. Entre otras cosas, almacenará una referencia a la ventana:

class Juego:
    def __init__(self, ventana):
        self.ventana = ventana
        ...

v = tkinter.Tk()
juego = Juego(v)

De esta forma, para hacer referencia a la ventana, escribimos juego.ventana.

Vamos a sustituir el método mainloop() que tienen las ventanas, para gestionar eventos, por nuestro propio bucle:

juego.bucle()

y definimos el método como:

def bucle(self):
    while True:
        # refrescar continuamente los objetos de pantalla
        # si se pulsa tecla escape, salir del bucle

El método ventana.update_idletasks() gestiona todas las tareas pendientes que tenga tkinter. Esto nos garantiza que no quedan eventos desatendidos.

El método ventana.destroy() elimina la ventana y, siendo la principal, finaliza la ejecución del programa.

¡Cuidado!

En próximos pasos, vamos a utilizar la tecla Esc para salir de la aplicación. El cierre de la ventana pulsando en el icono [x] de la esquina superior puede mostrar en la consola de IDLE algún mensaje de error por intentar gestionar eventos pendientes de una ventana que ya no existe.

Por ahora, podemos finalizar el programa pulsando Ctrl+C en el shell de IDLE.

Configurar la ventanas

Al crear una instancia de la clase Juego, en el método __init__() configuramos la ventana:

  • barra de título

    self.ventana.title('Bola')
    
  • no redimensionable horizontal ni verticalmente

    self.ventana.resizable(False, False)
    
  • el atributo topmost hace que la ventana siempre esté en primer plano:

    self.ventana.wm_attributes('-topmost', True)
    
  • creamos un lienzo con un borde de grosor cero. La ventana se ajustará a las dimensiones del lienzo:

    self.lienzo = tkinter.Canvas(self.ventana,
                                 width=500,
                                 height=400,
                                 bd=0)
    self.lienzo.pack()
    
  • hacemos que el ajuste de la ventana sea efectivo:

    self.ventana.update()