Programar Juegos Arcade
con Python y Pygame

Chapter 16: Retículas y Matrices

16.1 Introducción

Vídeo: Retículas y Matrices'

Juegos como el buscaminas, el tres en raya, y muchos de aventuras, almacenan los datos del juego en retículas de números. Por ejemplo, un tablero de tres en raya como éste:

 OO
 X 
X  

...puede utilizar una retícula numérica para representar los espacios vacíos, los 0's y lad X's de la manera siguiente:

022
010
100

También podemos llamar a esta retícula numérica como array bidimensional o matriz. (Finalmente aprenderemos algo de The Matrix.) Los valores numéricos de la retícula representan lo que debería ser mostrado en cada una de las posiciones del tablero. Para nuestro ejemplo, el 0 representa un lugar donde nadie ha jugado, el 1 representa a la X y el 2 al 0.

fig.minesweeper
Figure 16.1: Buscaminas y su Retícula Numérica

La Figura 16.1 es un ejemplo del clásico buscaminas. Lo hemos modificado para mostrar, tanto el juego clásico a la izquierda, como la retícula numérica empleada, a la derecha.

El número 10 representa una mina, el 0 un espacio que no ha sido tocado, y el 9 una casilla que ya lo fue. Los números del 1 al 8 representan la cantidad de minas que hay en las 8 casillas de alrededor, y solo se muestran cuando el jugador pulsa la casilla.

En realidad, el buscaminas puede tener dos retículas. Una para mostrar el juego en curso y otra, separada por completo, que llevará la cuenta de los lugares “marcados” por la jugadora en el tablero, donde cree que pueden encontrarse las minas.

Los mapas de los clásicos juegos de aventura son creados con lo que se denomina un editor de mapas. Éstos, son retículas enormes donde cada localización es un simple número que representa el tipo de terreno que va allí. El terreno puede ser polvoriento, un camino, una senda, césped verde, césped amarillento, etc. Los programas como Tiled Qt, mostrados en la Figura 16.2, permiten que el desarrollador cree mapas fácilmente y que pueda guardar la retícula en el disco.

fig.qt_tiled
Figure 16.2: Uso de Tiled Qt para crear una mapa de aventura

Los juegos de aventuras también emplean múltiples retículas numéricas, algo similar al buscaminas, donde hay una retícula para las minas y otra para las marcas. En los juegos de aventuras, una retícula, o “capa”, representa el tipo de terreno por el que puedes caminar; otra representa objetos por donde no se puede andar, tales como paredes y árboles; otra representaría cosas que te pueden matar al instante, como la lava o pozos sin fondo; otra podría representar objetos que se pueden recoger y desplazar; y aún otra, que podría contener la posición inicial de los monstruos.

Los mapas como estos se pueden cargar en Python, pero desadortunadamente, una descripción completa de cómo hacerlo, está más allá del propósito de este libro. Ciertos proyectos, como PyTMX, proporcionan algo del código necesario para cargar este tipo de mapas.

16.2 Aplicación

Basta de charla y vamos a escribir algo de código. En este ejemplo crearemos una retícula que se activará si mostramos un bloque de color blanco o verde. Podemos cambiar el valor de la retícula y hacer que sea verde haciendo clic sobre ella. Es un primer paso hacia un juego del tipo el buscaminas, hundir la flota, etc. (Hubo un año en que una estudiante me llamó para enseñarme una versión modificada de un programa como éste, donde aparecía mi nombre en luces parpadeantes. Fue como mínimo....inquietante. Por favor, usen su conocimiento para hacer el bien solamente!)

Ir a la página de códigos de ejemplo y descargarse la siguiente plantilla:
ProgramArcadeGames.com/python_examples/f.php?file=pygame_base_template_es.py

Intenta recrear este programa usando las instrucciones contenidas en la plantilla. El programa final está al final del capítulo. No te vayas hasta allí y lo copies! No habrás aprendido nada si haces eso. Cualquiera puede copiar y pegar código, pero si eres capaz de hacer este programa, estás adquiriendo las habilidades por las que la gente está dispuesta a pagar. Si solo puedes copiar y pegar, has estado desperdiciando tu tiempo aquí.

    16.2.1 Dibujar la Retícula

  1. Ajusta las dimensiones de la ventana del programa en 255x255 píxeles.
  2. Crea unas variables llamadas largo, alto, y margen. Establece el valor de largo y alto en 20. Esto representará cuán grande es cada una de las cuadrículas. El margen lo estableces en 5, lo que representa el espacio entre cada cuadrícula y los bordes de la pantalla. Crea estas variables antes del bucle principal del programa.
  3. Dibuja un cuadrado blanco en la esquina superior izquierda de la pantalla. Dibújalo usando las variables largo y alto que creaste anteriormente. (Eres libre de elegir el color que quieras.) Cuando hallas acabado, la ventana de tu programa debería ser como la de la Figura 16.3.
    step_03
    Figure 16.3: Paso 3
  4. Utiliza un bucle for para dibujar 10 cajas en la fila. Usa columna como nombre de variable en el bucle for. La salida se verá como una caja larga hasta que no añadamos los márgenes entre las celdas. Observa la Figura 16.4.
    step_04
    Figure 16.4: Paso 4
  5. Ajusta el dibujo de la caja para añadirle la variable margen. En este momento deberían aparecer los espacios entre las celdas. Observa la Figura 16.5.
    step_05
    Figure 16.5: Paso 5
  6. Además de hacerlo entre las celdas, añade el margen antes de dibujarlas. Esto impedirá que la celda se vea pegada al borde de la ventana. Observa la Figura 16.6.
    step_06
    Figure 16.6: Paso 6
  7. Añade otro bucle for que itere para cada fila. Llama fila a la variable dentro de este nuevo bucle for. En este momento tendremos completa nuestra retícula. Observa la Figura 16.7.
    step_07
    Figure 16.7: Paso 7

    16.2.2 Rellenamos la Retícula

  8. En estos momentos tenemos que crearnos una array bidimensional. Hacerlo en Python, desafortunadamente, no es tan fácil como en otros lenguajes. Existen algunas bibliotecas que podemos descargar para Python que facilitan esto, pero en nuestro ejemplo no las vamos a utilizar. Para crear un array bidimensional usaremos el siguiente código:
    # --- Creamos una retícula numérica
    # Creamos una lista vacía
    grid = []
    # Iteramos para cada fila
    for fila in range(10):
        # Para cada fila, creamos una lista que
        # representará una fila completa
        grid.append([])
        # Iteramos para cada columna
        for columna in range(10):
            # Añade el número cero a la fila actual
            grid[fila].append(0)
    

    Podemos ver un ejemplo más reducido debajo en el que se utilizan ciertas particularidades de Python, pero que no voy a explicar en este libro:

    grid = [[0 for x in range(10)] for y in range(10)]
    

    Utiliza cualquiera de los dos ejemplos anteriores, y coloca el código que creará nuestro array antes del bucle principal.

  9. Como ejemplo, introducimos un 1 en una de las celdas del array.

    Los arrays dimensionales se suelen representar indicando primero la fila y luego la columna. Esto se llama ordenamiento por filas. La mayoría de lenguajes utilizan esta característica, con la excepción de Fortran y MATLAB, que emplean ordenamiento por columnas.

    # Fila 1, columna 5 = 1
    grid[1][5] = 1
    

    Coloca el anterior código en algún lugar antes del bucle principal.

  10. Selecciona el color de la celda basándote en el valor de la variable llamada color. Para hacerlo tienes primero que encontrar la línea de código donde se dibuja la celda. Antes de ella, crea una variable llamada color y establécela en blanco. Luego, sustituye el color blanco en la declaración de la celda con la variable color.
  11. Selecciona el color basándote en el valor de la celda. Luego de haber establecido color como blanco, coloca una declaración if que busque en el valor de grid[fila][columna], y cambie el color a verde si el valor de la celda es igual a 1. Ahora deberíamos tener un cuadrado verde. Observa la Figura 16.8.
    step_11
    Figure 16.8: Paso 11
  12. Imprime “click” por pantalla si el jugador pulsa el ratón.
    Revisa bitmapped_graphics.py para que veas cómo detectar un click del ratón.
  13. Imprime las coordenadas del ratón cuando el jugador haga click.
    Revisa move_mouse.py para que veas cómo obtener la posición del ratón. Observa la Figura 16.9.
    step_13
    Figure 16.9: Paso 13
  14. Convierte las coordenadas del ratón en coordenadas de retícula. Imprime éstas últimas. Recuerda que debes usar el largo y alto de cada celda en combinación con el margen. Será necesario que conviertas en número entero los valores finales. Lo puedes hacer usando int o la división parte entera //, en lugar de la división normal /. Observa la Figura 16.10.
    step_14
    Figure 16.10: Paso 14
  15. Convierte en 1 la celda. Observa la Figura 16.11.
    step_15
    Figure 16.11: Paso 15

16.2.3 Programa Final

"""
 Programa de ejemplo de cómo usar un array para respaldar una retícula en pantalla.
 
 Sample Python/Pygame Programs
 Simpson College Computer Science
 http://programarcadegames.com/
 http://simpson.edu/computer-science/

Vídeo explicativo: http://youtu.be/mdTeqiWyFnc
"""
import pygame

# Definimos algunos colores
NEGRO = (0, 0, 0)
BLANCO = (255, 255, 255)
VERDE = ( 0, 255, 0)
ROJO = (255, 0, 0)

# Establecemos el LARGO y ALTO de cada celda de la retícula.
LARGO  = 20
ALTO = 20

# Establecemos el margen entre las celdas.
MARGEN = 5

# Creamos un array bidimensional. Un array bidimensional
# no es más que una lista de listas.
grid = []
for fila in range(10):
    # Añadimos un array vacío que contendrá cada celda 
    # en esta fila
    grid.append([])
    for columna in range(10):
        grid[fila].append(0) # Añade una celda

# Establecemos la fila 1, celda 5 a uno. (Recuerda, los números de las filas y
# columnas empiezan en cero.)
grid[1][5] = 1

# Inicializamos pygame
pygame.init()
 
# Establecemos el LARGO y ALTO de la pantalla
DIMENSION_VENTANA = [255, 255]
pantalla = pygame.display.set_mode(DIMENSION_VENTANA)

# Establecemos el título de la pantalla.
pygame.display.set_caption("Retículas y Matrices")

# Iteramos hasta que el usuario pulse el botón de salir.
hecho = False

# Lo usamos para establecer cuán rápido de refresca la pantalla.
reloj = pygame.time.Clock()

# -------- Bucle Principal del Programa-----------
while not hecho:
    for evento in pygame.event.get(): 
        if evento.type == pygame.QUIT: 
            hecho = True 
        elif evento.type == pygame.MOUSEBUTTONDOWN:
            # El usuario presiona el ratón. Obtiene su posición.
            pos = pygame.mouse.get_pos()
            # Cambia las coordenadas x/y de la pantalla por coordenadas reticulares
            columna = pos[0] // (LARGO + MARGEN)
            fila = pos[1] // (ALTO + MARGEN)
            # Establece esa ubicación a cero
            grid[fila][columna] = 1
            print("Click ", pos, "Coordenadas de la retícula: ", fila, columna)

    # Establecemos el fondo de pantalla.
    pantalla.fill(NEGRO)

    # Dibujamos la retícula
    for fila in range(10):
        for columna in range(10):
            color = BLANCO
            if grid[fila][columna] == 1:
                color = VERDE
            pygame.draw.rect(pantalla,
                             color,
                             [(MARGEN+LARGO) * columna + MARGEN,
                              (MARGEN+ALTO) * fila + MARGEN,
                              LARGO,
                              ALTO])
    
    # Limitamos a 60 fotogramas por segundo.
    reloj.tick(60)

    # Avanzamos y actualizamos la pantalla con lo que hemos dibujado.
    pygame.display.flip()
    
# Pórtate bien con el IDLE.
pygame.quit()


y empieza a trabajar en tu propio videojuego!

16.2.4 Test

Haz click para ir al Test.

16.2.5 Ejercicios

Haz click para ir a los Ejercicios.


You are not logged in. Log in here and track your progress.