Blog
El juego Snake (en español, la Serpiente) es un videojuego de arcade en el que el jugador controla una larga y delgada criatura, parecida a una serpiente, que vaga alrededor de un plano delimitado, recogiendo alimentos (o cualquier otro elemento), tratando de evitar golpear a su propia cola o a las “paredes” que rodean el área del juego. Cada vez que la serpiente come un pedazo de comida, la cola crece más, haciendo que aumente la dificultad del juego. En este tutorial veremos como crear una implementación sencilla del juego de Snake con IA en Python.
Representaremos al jugador como una serpiente que crecerá cada vez que coma una manzana. Estas manzanas irán apareciendo aleatoriamente en el área del juego luego de ser tragadas por la serpiente.
Diseñando el juego de Snake con IA en Python
Nuestro juego debe involucrar varias clases que definirán diferentes aspectos del juego:
- Clase Jugador: esta clase representará a la serpiente que será controlada por el jugador. Aquí estarán contenidos: la posición del jugador y la velocidad a la cual se mueve.
- Clase Aplicación: aquí se definirá la ventana en la cual se ejecutará el juego, definirá tamaños, limpiará la pantalla y estará al tanto de responder cualquier acción del teclado.
- Clase Manzana: esta clase se encargará de crear los alimentos para nuestro jugador y los posicionará aleatoriamente en el mapa.
Podemos crear todo el juego en un solo archivo y ejecutar solo ese pero eso está considerado una mala práctica de programación. En este post vamos a implementar una arquitectura de software profesional para tomar buenas costumbres en cuanto al desarrollo de aplicaciones. Así que vamos a crear un archivo para cada una de nuestras clases, enlazarlos todos a un archivo main a través de sentencias import el cual será ejecutado para correr el juego.
Clase Jugador:
from pygame.locals import * import pygame class Jugador: x = [0] y = [0] pasos = 44 direccion = 0 longitud = 3 updateCuentaMax = 2 updateCuenta = 0 def __init__(self, longitud): self.longitud = longitud for i in range(0,2000): self.x.append(-100) self.y.append(-100) # posicion inicial sin colisiones self.x[1] = 1*44 self.x[2] = 2*44 def update(self): self.updateCuenta = self.updateCuenta + 1 if self.updateCuenta > self.updateCuentaMax: # actualiza posiciones anteriores for i in range(self.longitud-1,0,-1): self.x[i] = self.x[i-1] self.y[i] = self.y[i-1] # actualiza la posicion de la cabeza de la serpiente if self.direccion == 0: self.x[0] = self.x[0] + self.pasos if self.direccion == 1: self.x[0] = self.x[0] - self.pasos if self.direccion == 2: self.y[0] = self.y[0] - self.pasos if self.direccion == 3: self.y[0] = self.y[0] + self.pasos self.updateCuenta = 0 def moveRight(self): self.direccion = 0 def moveLeft(self): self.direccion = 1 def moveUp(self): self.direccion = 2 def moveDown(self): self.direccion = 3 def draw(self, surface, image): for i in range(0,self.longitud): surface.blit(image,(self.x[i],self.y[i]))
El constructor de la clase Jugador, la inicializa con una longitud jugable mínima (3) y la ubica en un espacio en la pantalla donde no hayan colisiones. Define también las funciones que se llamarán cuando se reciba una acción del teclado.
Clase Manzana:
class Manzana: x = 0 y = 0 step = 44 def __init__(self,x,y): self.x = x * self.step self.y = y * self.step def draw(self, surface, image): surface.blit(image,(self.x, self.y))
La clase Manzana es bastante simple, solo define un objeto en el área del juego y lo posiciona aleatoriamente.
Clase Juego
class Juego: def isCollision(self,x1,y1,x2,y2,bsize): if x1 >= x2 and x1 <= x2 + bsize: if y1 >= y2 and y1 <= y2 + bsize: return True return False
La clase Juego, se encarga de las colisiones que ocurran para acabar la partida.
Clase Aplicacion
from pygame.locals import * from Juego import * from Jugador import * from Manzana import * from random import randint import pygame import time class Aplicacion: windowWidth = 800 windowHeight = 600 jugador = 0 manzana = 0 def __init__(self): self._running = True self._display_surf = None self._image_surf = None self._manzana_surf = None self.juego = Juego() self.jugador = Jugador(3) self.manzana = Manzana(5,5) def on_init(self): pygame.init() self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE) pygame.display.set_caption('Ejemplo de juego Snake aprenderPython.net') self._running = True self._image_surf = pygame.image.load("block.jpg").convert() self._manzana_surf = pygame.image.load("manzana.jpg").convert() def on_event(self, event): if event.type == QUIT: self._running = False def on_loop(self): self.jugador.update() # does snake eat manzana? for i in range(0,self.jugador.longitud): if self.juego.isCollision(self.manzana.x,self.manzana.y,self.jugador.x[i], self.jugador.y[i],44): self.manzana.x = randint(2,9) * 44 self.manzana.y = randint(2,9) * 44 self.jugador.longitud = self.jugador.longitud + 1 # does snake collide with itself? for i in range(2,self.jugador.longitud): if self.juego.isCollision(self.jugador.x[0],self.jugador.y[0],self.jugador.x[i], self.jugador.y[i],40): print("You lose! Collision: ") print("x[0] (" + str(self.jugador.x[0]) + "," + str(self.jugador.y[0]) + ")") print("x[" + str(i) + "] (" + str(self.jugador.x[i]) + "," + str(self.jugador.y[i]) + ")") exit(0) pass def on_render(self): self._display_surf.fill((0,0,0)) self.jugador.draw(self._display_surf, self._image_surf) self.manzana.draw(self._display_surf, self._manzana_surf) pygame.display.flip() def on_cleanup(self): pygame.quit() def on_execute(self): if self.on_init() == False: self._running = False while( self._running ): pygame.event.pump() keys = pygame.key.get_pressed() if (keys[K_RIGHT]): self.jugador.moveRight() if (keys[K_LEFT]): self.jugador.moveLeft() if (keys[K_UP]): self.jugador.moveUp() if (keys[K_DOWN]): self.jugador.moveDown() if (keys[K_ESCAPE]): self._running = False self.on_loop() self.on_render() time.sleep (50.0 / 1000.0); self.on_cleanup()
Esta clase contiene la mayoría de la lógica del juego en sí. Esta clase define el tamaño de la ventana en la que se ejecutará el juego. Aquí también se crea el jugador, las manzanas y se reciben las pulsaciones del teclado para llamar a las funciones necesarias. “block.jpg” y “manzana.jpg” son imágenes que usaremos para contruir nuestra serpiente y manzana, puedes encontrar las imágenes aquí.
Clase Main
from Juego import * from Aplicacion import * from Manzana import * from Jugador import * # Recuerda tener todos los archivos en una misma carpeta # para que los imports no tengan problemas. if __name__ == '__main__': aplicacion = Aplicacion() aplicacion.on_execute()
Como explicamos anteriormente, usaremos una clase “main” para ejecutar nuestro juego desde ahí. Esta clase solo va a contener la definición de un objeto Aplicación y llamará a la función on_execute() de la misma.
Ejecución:
(aprendePython) ➜ snakeGame python main.py pygame 1.9.4 Hello from the pygame community. https://www.pygame.org/contribute.html Chocaste, perdiste!: x[0] (176,220) x[2] (176,220) (aprendePython) ➜ snakeGame
Podemos ver que nuestra implementación del juego ejecuta sin ningún problema y podemos jugar en solitario. Sin embargo, nuestro juego de Snake con IA en Python no está completo: debemos aplicar la IA (Inteligencia Artificial) para que cree otro “jugador” que será controlado por el propio juego para que compita contra nosotros.
Agregando inteligencia artificial
Vamos a agregar a nuestro juego, la capacidad de que la computadora pueda jugar en contra nuestra (quitándonos el alimento y tratando de hacernos chocar). En pocas palabras: nuestro oponente intentará determinar nuestra ubicación e ir a este punto.
Agregando un jugador Computadora:
Extendamos un poco nuestro código con una nueva clase Computadora que será nuestro oponente. Va a contener las rutinas para dibujar y mover a su serpiente:
import pygame from pygame.locals import * class Computer: x = [0] y = [0] pasos = 44 direccion = 0 longitud = 3 updateCuentaMaxima = 2 updateCuenta = 0 def __init__(self, longitud): self.longitud = longitud for i in range(0,2000): self.x.append(-100) self.y.append(-100) # initial positions, no collision. self.x[0] = 1*44 self.y[0] = 4*44 def update(self): self.updateCuenta = self.updateCuenta + 1 if self.updateCuenta and self.updateCuentaMaxima: # update previous positions for i in range(self.longitud-1,0,-1): self.x[i] = self.x[i-1] self.y[i] = self.y[i-1] # update position of head of snake if self.direccion == 0: self.x[0] = self.x[0] + self.pasos if self.direccion == 1: self.x[0] = self.x[0] - self.pasos if self.direccion == 2: self.y[0] = self.y[0] - self.pasos if self.direccion == 3: self.y[0] = self.y[0] + self.pasos self.updateCuenta = 0 def moveRight(self): self.direccion = 0 def moveLeft(self): self.direccion = 1 def moveUp(self): self.direccion = 2 def moveDown(self): self.direccion = 3 def draw(self, surface, image): for i in range(0,self.longitud): surface.blit(image,(self.x[i],self.y[i]))
Luego llamamos a los métodos update() y draw() para dibujar y actualizar la posición de la serpiente oponente en nuestra clase Aplicación:
def on_loop(self): self.jugador.update() self.computadora.update() .... def on_render(self): self._display_surf.fill((0,0,0)) self.jugador.draw(self._display_surf, self._image_surf) self.manzana.draw(self._display_surf, self._apple_surf) self.computadora.draw(self._display_surf, self._image_surf) pygame.display.flip()
Agregar inteligencia a la clase Computadora:
Ya que esto es una implementación simple, no necesitamos crear completamente una máquina pensante dentro de nuestra aplicación. Simplemente necesitamos que nuestra clase Computadora exhiba un tipo de “inteligencia básica“. La inteligencia en los juegos a menudo es limitada ya que la mayoría de las veces no se necesita tanta complejidad o simplemente no hay tiempo suficiente para implementar mejores algoritmos.
El algoritmo simplemente le dirá a que ubicación dirigirse:
def target(self, dx, dy): if self.x[0] > dx: self.moveLeft() if self.x[0] < dx: self.moveRight() if self.x[0] == dx: if self.y[0] < dy: self.moveDown() if self.y[0] > dy: self.moveUp()
Ejecutando:
(aprendePython) ➜ snakeGame python main.py pygame 1.9.4 Hello from the pygame community. https://www.pygame.org/contribute.html Chocaste, perdiste!: x[0] (220,132) x[2] (220,132) (aprendePython) ➜ snakeGame
Al ejecutar nuestro juego vemos que tenemos otro jugador. Tu objetivo será intentar llegar primero a la manzana que él!
➡ Continúa aprendiendo sobre desarrollo de videojuegos con python en nuestro Curso Python de Videojuegos:
test
ey ayuda
nose espero haberte ayudado
Al final me sale un error