Razón Artificial

La ciencia y el arte de crear videojuegos

Juego de la serpiente paso a paso. Parte 1

Escrito por adrigm el 17 de julio de 2010 en Desarrollo Videojuegos, Noticias, Programación | 2 Comentarios.

Vamos a hacer paso a paso el juego de la serpiente usando Python y Pygame. La idea del juego para el que no lo conozca es una pequeña serpiente que debemos mover por una pantalla cogiendo la comida que aparece que es lo que da puntos, pero entre más comes más crece la serpiente. Manos a la obra.

Antes de hacer este tutorial es totalmente recomendable hacer el tutorial del Pong ya que las cosas que explique en él no las voy a volver a explicar y las daré por sabidas.

Directorio Base

Lo primero de todo os dejo el directorio base para trabajar que contiene todo lo necesario para hacer nuestro juego: Imágenes, tipografías y plantilla base de Pygame que ya creamos en el tutorial del pong. También contiene un txt que será el mapa de nuestro juego.

La clase Mapa

Al ser un juego tan simple no voy a hacer una clase para cada Sprite, sino que será la clase Mapa la que gestione todos los sprites del juego. Solo habrá 3 sprites: Uno que representa a las paredes, otro para la serpiente y otro para la comida.

Así que lo primero que haremos será inicializar la clase mapa y cargar nuestros gráficos con la función load_image que tenemos ya ahí.

class Mapa(pygame.sprite.Sprite):
	def __init__(self, archivo):
		pygame.sprite.Sprite.__init__(self)

		self.bloque = load_image("images/bloque.png")
		self.rect_bloque = self.bloque.get_rect()

		self.snake = load_image("images/snake.png")
		self.rect_snake = self.snake.get_rect()

		self.comida = load_image("images/comida.png", True)
		self.rect_comida = self.comida.get_rect()

El archivo mapa.txt

El archivo mapa.txt será el que usemos para cargar nuestro mapa base, si abrimos el mapa.txt veremos esto:

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . * . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

Las almohadillas representan las paredes, los puntos por donde se puede pasar y el asterísco representa la cabeza de la serpiente (Ojo, los 3 caracteres a la izquierda de la cabeza de la serpiente deben ser puntos porque irá el resto del cuerpo de la serpiente).

Bien, necesitamos convertir este txt en una lista de Python y darle valores según el carácter, yo voy a usar la siguiente combinación para representar los elementos:

  • Muros → 1
  • Libres → 0
  • Serpiente → 2
  • Cabeza serpiente → 5
  • Comida → 3

Bueno ya teniendo un código lo que hay que hacer es convertir el mapa, lo voy a hacer a través de 3 funciones:

# Quita el ultimo caracter de una lista.
def quitarUltimo(lista):
	for i in range(len(lista)):
		lista[i] = lista[i][:-1]
	return lista

# Covierte una cadena en una lista.	
def listarCadena(cadena):
	lista = []
	for i in range(len(cadena)):
		if cadena[i] == ".":
			lista.append(0)
		if cadena[i] == "#":
			lista.append(1)
		if cadena[i] == "*":
			lista.append(2)
	return lista

# Lee un archivo de texto y lo convierte en una lista.
def leerMapa(archivo):
	mapa = open(archivo, "r")
	mapa = mapa.readlines()
	mapa = quitarUltimo(mapa)
	for i in range(len(mapa)):
		mapa[i] = listarCadena(mapa[i])
	return mapa

La que lee el mapa realmente es la última de todas, pero necesita las dos anteriores. Así que explico esta última y las 2 anteriores.

leerMapa recibe como parámetro un archivo de texto, la primera línea abre y lee el archivo, la segunda utiliza la el método readlines() que tienen los archivos abiertos y que lee las lineas de nuestro archivo. Con esto lo que tenemos es una lista que contiene unas cadenas de caracteres por cada línea de nuestro archivo (ojo que contiene al final el carácter de salto de línea también “\n”).

Para solucionar esto último la función quitarUltimo que se encarga de eliminar el último carácter de cada una de las cadenas de la lista. Nada complicado de ver como lo hace.

Bien ahora lo que necesitamos es convertir las cadanas de nuestra lista en listas con los valores que representan cada carácter, para ello recorremos la lista de cadenas y a cada una de ellas le aplicamos la función listarCadena que como vemos lo que hace es crear una lista vacía y recorrer la cadena pasada y si encuantra un punto (.) añade a la lista un 1, si encuentre una almuhadilla (#) un 2 y así con todo, finalmente retorna la nueva lista y en la función leerMapa sustituimos la cadena que había por la nueva lista. Finalmente leerMapa nos retorna el mapa perfectamente convertido a un array bidimensional.

Ahora lo que queda es cargarlo en nuestra clase mapa, añadimos después de la creación de Sprites lo siguiente:

self.mapa = leerMapa(archivo)
self.fil = len(self.mapa)
self.col = len(self.mapa[0])

Recuerda que archivo se lo pasamos como parámetro a nuestro método __init__, es decir cuando se crea la clase. Como vez almacenamos el mapa en self.mapa y creamos también self.fil y seld.col que contiene el tamaño de las filas y columnas del mapa, muy útil para recorrer el mapa.

Bueno con esto ya tenemos los Sprites creadosy el mapa cargado. El juego nos queda por ahora así:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Módulos
import sys, pygame
from pygame.locals import *

# Constantes
WIDTH = 640
HEIGHT = 480

# Clases
# ---------------------------------------------------------------------

class Mapa(pygame.sprite.Sprite):
	def __init__(self, archivo):
		pygame.sprite.Sprite.__init__(self)
		
		self.bloque = load_image("images/bloque.png")
		self.rect_bloque = self.bloque.get_rect()
		
		self.snake = load_image("images/snake.png")
		self.rect_snake = self.snake.get_rect()
		
		self.comida = load_image("images/comida.png", True)
		self.rect_comida = self.comida.get_rect()
		
		self.mapa = leerMapa(archivo)
		self.fil = len(self.mapa)
		self.col = len(self.mapa[0])

# ---------------------------------------------------------------------

# Funciones
# ---------------------------------------------------------------------

# Quita el ultimo caracter de una lista.
def quitarUltimo(lista):
	for i in range(len(lista)):
		lista[i] = lista[i][:-1]
	return lista

# Covierte una cadena en una lista.	
def listarCadena(cadena):
	lista = []
	for i in range(len(cadena)):
		if cadena[i] == ".":
			lista.append(0)
		if cadena[i] == "#":
			lista.append(1)
		if cadena[i] == "*":
			lista.append(2)
	return lista

# Lee un archivo de texto y lo convierte en una lista.
def leerMapa(archivo):
	mapa = open(archivo, "r")
	mapa = mapa.readlines()
	mapa = quitarUltimo(mapa)
	for i in range(len(mapa)):
		mapa[i] = listarCadena(mapa[i])
	return mapa

# Carga una imagen a Pygame
def load_image(filename, transparent=False):
        try: image = pygame.image.load(filename)
        except pygame.error, message:
                raise SystemExit, message
        image = image.convert()
        if transparent:
                color = image.get_at((0,0))
                image.set_colorkey(color, RLEACCEL)
        return image
        
def salir(keys):
	for eventos in pygame.event.get():
		if eventos.type == QUIT:
			sys.exit(0)
		if keys[K_ESCAPE]:
			sys.exit(0)

# ---------------------------------------------------------------------

def main():
	screen = pygame.display.set_mode((WIDTH, HEIGHT))
	pygame.display.set_caption("Pruebas Pygame")
	background_image = load_image('images/fondo.jpg');
	
	clock = pygame.time.Clock()
	
	while True:
		time = clock.tick(60)
		keys = pygame.key.get_pressed()
		salir(keys)

		screen.blit(background_image, (0, 0))
		pygame.display.flip()
	return 0

if __name__ == '__main__':
	pygame.init()
	main()

2 Comentarios en "Juego de la serpiente paso a paso. Parte 1"

  1. carlos jaramilloe dice:

    hola,

    oie, resulta que tengo como proyecto en la u presentar este mismo proyecto y lo e estado adelantando pero, no puedo aplicar las colisiones me puedes ayudar,

    no se como darle mivimiento al rectangulo de la cabeza de la serpiente se queda estatica, si la convierto en superficie si se mueve que puede hacer,

    GRACIAS

  2. […] Juego de la serpiente paso a paso. Parte 1 […]

Deja un comentario