🐍Videojuego Snake
Última actualización
Última actualización
¡En este ejercicio práctico vamos a implementar nuestro segundo videojuego en Python!
Concretamente el juego que vamos a programar es el Snake, uno de los juegos más populares de todos los tiempos al que seguro que muchos de nosotros hemos jugado alguna vez. Este juego consiste en mover una serpiente dentro de un rectángulo comiendo puntos que hacen que el cuerpo de la serpiente aumente de tamaño. Si nos chocamos con alguno de los bordes o el propio cuerpo de la serpiente perderemos la partida. A continuación se muestra una imagen del juego.
Turtle
Esta vez vamos a intentar que nuestro juego tenga una interfaz gráfica una poco más visual que la que implementamos en el juego del cuatro en raya. Para implementar estos gráficos en Python, vamos a utilizar un paquete muy sencillo denominado Turtle.
Turtle es un paquete de Python preinstalado que permite a los usuarios crear imágenes y formas proporcionándoles un lienzo virtual. El lápiz en pantalla que se utiliza para dibujar se llama turtle
y esto es lo que da nombre a la biblioteca.
Más información: https://docs.python.org/3/library/turtle.html
Explora el paquete de Python Turtle y familiarízate con sus estructuras más populares.
Pista: Presta especial atención a las siguientes clases Screen()
y a los siguientes métodos que exponen los objetos de esta clase: title()
, bgcolor()
, setup()
y tracer()
.
import turtle
screen = turtle.Screen()
screen.title('Videojuego Snake') # Título de la ventana
screen.bgcolor('red') # Color de fondo
screen.setup(width=800, height=800) # Tamaño de la ventana
Pista: Presta especial atención a las siguientes clases Turtle()
y a los siguientes métodos que exponen los objetos de esta clase: goto()
, speed()
, shape()
, color()
penup()
, write()
t = turtle.Turtle()
t.goto(150, 5) # Establecer una dirección
t.goto(-100, -30) # Establecer otra dirección
t.speed(0) # Establecer velocidad de movimiento
t.shape('square') # Cambiar la forma del puntero
t.color('white') # Cambiar el color del puntero
t.penup() # Que los elementos se superpongan
t.write('Videojuego Snake', align='center', font=("Courier", 24, 'normal'))
t2 = turtle.Turtle() # Crear un nuevo objeto en el tablero
t2.sety(t2.ycor() + 100) # Editar coordenada Y del nuevo elemento
t.forward(20) # Mover elemento 20 posiciones hacia alante
Pista: Regresa de nuevo al objeto generados partir de la clase Screen()
e intenta mover el objeto turtle utilizando los métodos listen()
y onkeypress()
# Definimos una función que va a mover el objeto t2
def move():
t2.sety(t2.ycor() - 20)
# Instanciamos el objeto
move()
# Hacer que el puntero se mueva hacia abajo cuando pulsemos la s
screen.listen()
screen.onkeypress(move, 's')
# Bucle infinito que cada 0.1 segundos actualiza la pantalla
import time
while True:
screen.update() # Actualizar estado del lienzo
time.sleep(0.1)
screen.mainloop() # Hace que la librería se quede en bucle
Vamos a comenzar creando la pantalla en la que vamos a jugar al juego y la serpiente. Cuando comienza el juego, la serpiente es únicamente un cuadrado en la pantalla.
Implementa una clase que inicialice la pantalla en la que vamos a jugar al juego, la serpiente y el texto que vamos a mostrar por pantalla.
import turtle
class SnakeGame:
def __init__(self, width=800, height=800, color="#CEFF00"):
'''Inicializa los componentes del juego.'''
# Inicializa el lienzo
self.screen = turtle.Screen()
self.screen.title('Videojuego Snake')
self.screen.bgcolor(color)
self.screen.setup(width=width, height=height)
# inicializa la serpiente
self.snake = turtle.Turtle()
self.snake.speed(0)
self.snake.shape('square')
self.snake.color('black')
self.snake.penup()
self.snake.goto(0,0)
# Inicializa el texto que se muestra en pantalla
self.texto = turtle.Turtle()
self.texto.speed(0)
self.texto.penup()
self.texto.color('black')
self.texto.hideturtle() # Método que oculta el puntero
self.texto.goto(0, (height / 2) - 40) # Posición arriba del todo
self.texto.write('Puntos: 0 Record:0', align='center', font=('Courier', 24, 'normal'))
snake_game = SnakeGame()
Ya tenemos nuestra pantalla implementada y la serpiente representada como un cuadrado negro. En este punto debemos comenzar a implementar los movimientos de la serpiente por la pantalla.
Añade a la clase Snake los métodos que consideres necesarios para habilitar el movimiento de serpiente por la pantalla. Ten en cuenta que estos métodos tendrán que invocarse más adelante mediante la pulsación de una tecla.In [9]:
import turtle
class SnakeGame:
def __init__(self, width=800, height=800, color="#CEFF00"):
'''Inicializa los componentes del juego.'''
# Inicializa el lienzo
self.screen = turtle.Screen()
self.screen.title('Videojuego Snake')
self.screen.bgcolor(color)
self.screen.setup(width=width, height=height)
# inicializa la serpiente
self.snake = turtle.Turtle()
self.snake.speed(0)
self.snake.shape('square')
self.snake.color('black')
self.snake.penup()
self.snake.goto(0,0)
# Inicializa el texto que se muestra en pantalla
self.texto = turtle.Turtle()
self.texto.speed(0)
self.texto.penup()
self.texto.color('black')
self.texto.hideturtle() # Método que oculta el puntero
self.texto.goto(0, (height / 2) - 40) # Posición arriba del todo
self.texto.write('Puntos: 0 Record: 0', align='center', font=('Courier', 24, 'normal'))
# Atributos de la clase
self._direccion = None
# Hace que la librería se quede en bucle
self.screen.mainloop()
def arriba(self):
'''Este método define el movimiento hacia arriba de la serpiente'''
if self._direccion != 'abajo':
self._direccion = 'arriba'
def abajo(self):
'''Este método define el movimiento hacia abajo de la serpiente'''
if self._direccion != 'arriba':
self._direccion = 'abajo'
def izquierda(self):
'''Este método define el movimiento hacia la izquierda de la serpiente'''
if self._direccion != 'derecha':
self._direccion = 'izquierda'
def derecha(self):
'''Este método define el movimiento hacia la derecha de la serpiente'''
if self._direccion != 'izquierda':
self._direccion = 'derecha'
def move(self):
if self._direccion == 'arriba':
y = self.snake.ycor()
self.snake.sety(y + 20)
elif self._direccion == 'abajo':
y = self.snake.ycor()
self.snake.sety(y - 20)
elif self._direccion == 'izquierda':
x = self.snake.xcor()
self.snake.setx(x - 20)
elif self._direccion == 'derecha':
x = self.snake.xcor()
self.snake.setx(x + 20)
snake_game = SnakeGame()
snake_game.arriba()
snake_game.move()
Si has llegado hasta este apartado, ya tienes una parte importante de tu videojuego implementada. Una vez que has conseguido mover la serpiente por la pantalla, ahora debes permitir que estos movimientos se realicen mediante la pulsación de una tecla.
Implementan el código dentro de la clase Snake y fuera de ella que consideres necesarios para mover la serpiente por la pantalla pulsando una tecla.
import turtle
import time
class SnakeGame:
def __init__(self, width=800, height=800, color="#CEFF00"):
'''Inicializa los componentes del juego.'''
# Inicializa el lienzo
self.screen = turtle.Screen()
self.screen.title('Videojuego Snake')
self.screen.bgcolor(color)
self.screen.setup(width=width, height=height)
# inicializa la serpiente
self.snake = turtle.Turtle()
self.snake.speed(0)
self.snake.shape('square')
self.snake.color('black')
self.snake.penup()
self.snake.goto(0,0)
# Inicializa el texto que se muestra en pantalla
self.texto = turtle.Turtle()
self.texto.speed(0)
self.texto.penup()
self.texto.color('black')
self.texto.hideturtle() # Método que oculta el puntero
self.texto.goto(0, (height / 2) - 40) # Posición arriba del todo
self.texto.write('Puntos: 0 Record: 0', align='center', font=('Courier', 24, 'normal'))
# Atributos de la clase
self._direccion = None
self._delay = 0.1
# Asociar movimientos a las teclas
self.screen.listen()
self.screen.onkeypress(self.arriba, 'w')
self.screen.onkeypress(self.abajo, 's')
self.screen.onkeypress(self.izquierda, 'a')
self.screen.onkeypress(self.derecha, 'd')
def arriba(self):
'''Este método define el movimiento hacia arriba de la serpiente'''
if self._direccion != 'abajo':
self._direccion = 'arriba'
def abajo(self):
'''Este método define el movimiento hacia abajo de la serpiente'''
if self._direccion != 'arriba':
self._direccion = 'abajo'
def izquierda(self):
'''Este método define el movimiento hacia la izquierda de la serpiente'''
if self._direccion != 'derecha':
self._direccion = 'izquierda'
def derecha(self):
'''Este método define el movimiento hacia la derecha de la serpiente'''
if self._direccion != 'izquierda':
self._direccion = 'derecha'
def move(self):
'''Este método mueve y actualiza las coordenadas la serpiente'''
if self._direccion == 'arriba':
y = self.snake.ycor()
self.snake.sety(y + 20)
elif self._direccion == 'abajo':
y = self.snake.ycor()
self.snake.sety(y - 20)
elif self._direccion == 'izquierda':
x = self.snake.xcor()
self.snake.setx(x - 20)
elif self._direccion == 'derecha':
x = self.snake.xcor()
self.snake.setx(x + 20)
def play(self):
'''Este método hace que la serpiente avance constantemente'''
while True:
self.screen.update()
time.sleep(self._delay)
self.move()
self.screen.mainloop()
snake_game.play()
Ya tenemos implementado uno de los comportamientos más importantes de nuestro videojuego como es el movimiento de la serpiente. Sin embargo, podemos observar como la serpiente no respeta los bordes y puede traspasarlos. Implementa las colisiones con los bordes de la pantalla para que se mantenga siempre en el recuadro.
Implementa los métodos que consideres necesarios para limitar el movimiento de la serpiente a la pantalla que se está mostrando. Si la serpiente choca con un borde, debe volver al centro de la pantalla.
import turtle
import time
class SnakeGame:
def __init__(self, width=800, height=800, color="#CEFF00"):
'''Inicializa los componentes del juego.'''
self._ancho = width
self._alto = height
# Inicializa el lienzo
self.screen = turtle.Screen()
self.screen.title('Videojuego Snake')
self.screen.bgcolor(color)
self.screen.setup(width=width, height=height)
self.screen.tracer(0)
# inicializa la serpiente
self.snake = turtle.Turtle()
self.snake.speed(0)
self.snake.shape('square')
self.snake.color('black')
self.snake.penup()
self.snake.goto(0,0)
# Inicializa el texto que se muestra en pantalla
self.texto = turtle.Turtle()
self.texto.speed(0)
self.texto.penup()
self.texto.color('black')
self.texto.hideturtle() # Método que oculta el puntero
self.texto.goto(0, (height / 2) - 40) # Posición arriba del todo
self.texto.write('Puntos: 0 Record: 0', align='center', font=('Courier', 24, 'normal'))
# Atributos de la clase
self._direccion = None
self._delay = 0.1
# Asociar movimientos a las teclas
self.screen.listen()
self.screen.onkeypress(self.arriba, 'w')
self.screen.onkeypress(self.abajo, 's')
self.screen.onkeypress(self.izquierda, 'a')
self.screen.onkeypress(self.derecha, 'd')
def arriba(self):
'''Este método define el movimiento hacia arriba de la serpiente'''
if self._direccion != 'abajo':
self._direccion = 'arriba'
def abajo(self):
'''Este método define el movimiento hacia abajo de la serpiente'''
if self._direccion != 'arriba':
self._direccion = 'abajo'
def izquierda(self):
'''Este método define el movimiento hacia la izquierda de la serpiente'''
if self._direccion != 'derecha':
self._direccion = 'izquierda'
def derecha(self):
'''Este método define el movimiento hacia la derecha de la serpiente'''
if self._direccion != 'izquierda':
self._direccion = 'derecha'
def move(self):
'''Este método mueve y actualiza las coordenadas la serpiente'''
if self._direccion == 'arriba':
y = self.snake.ycor()
self.snake.sety(y + 20)
elif self._direccion == 'abajo':
y = self.snake.ycor()
self.snake.sety(y - 20)
elif self._direccion == 'izquierda':
x = self.snake.xcor()
self.snake.setx(x - 20)
elif self._direccion == 'derecha':
x = self.snake.xcor()
self.snake.setx(x + 20)
def play(self):
'''Este método hace que la serpiente avance constantemente'''
while True:
self.screen.update()
self.colision_borde() # Llamamos a la función colision en el play
time.sleep(self._delay)
self.move()
self.screen.mainloop()
def colision_borde(self):
# Definimos los bordes del tablero
bxcor = (self._ancho // 2) - 20
bycor = (self._alto // 2) - 20
if self.snake.xcor() > bxcor or self.snake.xcor() < -bxcor or self.snake.ycor() > bycor or self.snake.ycor() < -bycor:
time.sleep(1)
self.snake.goto(0,0)
self._direccion = None
self.texto.clear()
self.texto.write('Puntos: 0 Record: 0', align='center', font=('Courier', 24, 'normal'))
snake_game = SnakeGame()
snake_game.play()
Lo siguiente importante que debemos implementar en nuestro juego es la comida de la serpiente. Esto es lo que nos permite aumentar los puntos y que la serpiente aumente de tamaño. La comida debe aparecer aleatoriamente por la pantalla.
Implementa los métodos que consideres necesarios para generar la comida de manera aleatoria en la pantalla. La comida debe ser un circulo del mismo tamaño que la serpiente.
import turtle
import time
import random
class SnakeGame:
def __init__(self, width=800, height=800, color="#CEFF00"):
'''Inicializa los componentes del juego.'''
self._ancho = width
self._alto = height
# Inicializa el lienzo
self.screen = turtle.Screen()
self.screen.title('Videojuego Snake')
self.screen.bgcolor(color)
self.screen.setup(width=width, height=height)
self.screen.tracer(0)
# Inicializa la serpiente
self.snake = turtle.Turtle()
self.snake.speed(0)
self.snake.shape('square')
self.snake.color('black')
self.snake.penup()
self.snake.goto(0,0)
# Inicializa la comida de la serpiente
self.comida = turtle.Turtle()
self.comida.speed(0)
self.comida.shape('circle')
self.comida.color('white')
self.comida.penup()
self.comida.goto(0, 100)
# Inicializa el texto que se muestra en pantalla
self.texto = turtle.Turtle()
self.texto.speed(0)
self.texto.penup()
self.texto.color('black')
self.texto.hideturtle() # Método que oculta el puntero
self.texto.goto(0, (height / 2) - 40) # Posición arriba del todo
# Atributos de la clase
self._direccion = None
self._delay = 0.1
self._score = 0
self._high_score = 0
# Asociar movimientos a las teclas
self.screen.listen()
self.screen.onkeypress(self.arriba, 'w')
self.screen.onkeypress(self.abajo, 's')
self.screen.onkeypress(self.izquierda, 'a')
self.screen.onkeypress(self.derecha, 'd')
# Inicializar score
self._print_score()
def arriba(self):
'''Este método define el movimiento hacia arriba de la serpiente'''
if self._direccion != 'abajo':
self._direccion = 'arriba'
def abajo(self):
'''Este método define el movimiento hacia abajo de la serpiente'''
if self._direccion != 'arriba':
self._direccion = 'abajo'
def izquierda(self):
'''Este método define el movimiento hacia la izquierda de la serpiente'''
if self._direccion != 'derecha':
self._direccion = 'izquierda'
def derecha(self):
'''Este método define el movimiento hacia la derecha de la serpiente'''
if self._direccion != 'izquierda':
self._direccion = 'derecha'
def move(self):
'''Este método mueve y actualiza las coordenadas la serpiente'''
if self._direccion == 'arriba':
y = self.snake.ycor()
self.snake.sety(y + 20)
elif self._direccion == 'abajo':
y = self.snake.ycor()
self.snake.sety(y - 20)
elif self._direccion == 'izquierda':
x = self.snake.xcor()
self.snake.setx(x - 20)
elif self._direccion == 'derecha':
x = self.snake.xcor()
self.snake.setx(x + 20)
def play(self):
'''Este método hace que la serpiente avance constantemente y evalua las colisiones'''
while True:
self.screen.update()
self.colision_borde()
self.colision_comida()
time.sleep(self._delay)
self.move()
self.screen.mainloop()
def colision_borde(self):
# Definimos los bordes del tablero
bxcor = (self._ancho // 2) - 20
bycor = (self._alto // 2) - 20
if self.snake.xcor() > bxcor or self.snake.xcor() < -bxcor or self.snake.ycor() > bycor or self.snake.ycor() < -bycor:
time.sleep(1)
self.snake.goto(0,0)
self._direccion = None
# Reiniciar el delay
self._delay = 0.1
# Actualizar puntuación máxima
if self._score > self._high_score:
self._high_score = self._score
self._score = 0
self._print_score()
def colision_comida(self):
if self.snake.distance(self.comida) < 20:
# Mover la comida a un lugar aleatorio
bxcor = (self._ancho // 2) - 20
bycor = (self._alto // 2) - 20
x = random.randint(-bxcor, bxcor)
y = random.randint(-bycor, bycor)
self.comida.goto(x, y)
# Reducir el delay cada vez que come
self._delay -= 0.001
# Aumentar el score
self._score += 10
self._print_score()
def _print_score(self):
self.texto.clear()
self.texto.write('Puntos: {} Record: {}'.format(self._score, self._high_score), align='center', font=('Courier', 24, 'normal'))
snake_game = SnakeGame()
snake_game.play()
La siguiente funcionalidad que debemos implementar es el aumento de puntuación y tamaño de la serpiente como cuando come la comida que hemos implementado anteriormente.
Implementa los métodos que consideres necesarios para aumentar la puntuación y el tamaño de la serpiente cuando come la comida implementada en el apartado anterior.
import turtle
import time
import random
class SnakeGame:
def __init__(self, width=800, height=800, color="#CEFF00"):
'''Inicializa los componentes del juego.'''
self._ancho = width
self._alto = height
# Inicializa el lienzo
self.screen = turtle.Screen()
self.screen.title('Videojuego Snake')
self.screen.bgcolor(color)
self.screen.setup(width=width, height=height)
self.screen.tracer(0)
# Inicializa la serpiente
self.snake = turtle.Turtle()
self.snake.speed(0)
self.snake.shape('square')
self.snake.color('black')
self.snake.penup()
self.snake.goto(0, 0)
# Inicializa los segmentos de la serpiente
self._segmentos = []
self._segmentos.append(turtle.Turtle())
self._segmentos[0].speed(0)
self._segmentos[0].shape('square')
self._segmentos[0].color('black')
self._segmentos[0].penup()
self._segmentos[0].goto(0, 0)
# Inicializa la comida de la serpiente
self.comida = turtle.Turtle()
self.comida.speed(0)
self.comida.shape('circle')
self.comida.color('white')
self.comida.penup()
self.comida.goto(0, 100)
# Inicializa el texto que se muestra en pantalla
self.texto = turtle.Turtle()
self.texto.speed(0)
self.texto.penup()
self.texto.color('black')
self.texto.hideturtle() # Método que oculta el puntero
self.texto.goto(0, (height / 2) - 40) # Posición arriba del todo
# Atributos de la clase
self._direccion = None
self._delay = 0.1
self._score = 0
self._high_score = 0
# Asociar movimientos a las teclas
self.screen.listen()
self.screen.onkeypress(self.arriba, 'w')
self.screen.onkeypress(self.abajo, 's')
self.screen.onkeypress(self.izquierda, 'a')
self.screen.onkeypress(self.derecha, 'd')
# Inicializar score
self._print_score()
def arriba(self):
'''Este método define el movimiento hacia arriba de la serpiente'''
if self._direccion != 'abajo':
self._direccion = 'arriba'
def abajo(self):
'''Este método define el movimiento hacia abajo de la serpiente'''
if self._direccion != 'arriba':
self._direccion = 'abajo'
def izquierda(self):
'''Este método define el movimiento hacia la izquierda de la serpiente'''
if self._direccion != 'derecha':
self._direccion = 'izquierda'
def derecha(self):
'''Este método define el movimiento hacia la derecha de la serpiente'''
if self._direccion != 'izquierda':
self._direccion = 'derecha'
def move(self):
'''Este método mueve y actualiza las coordenadas la serpiente'''
if self._direccion == 'arriba':
y = self.snake.ycor()
self.snake.sety(y + 20)
elif self._direccion == 'abajo':
y = self.snake.ycor()
self.snake.sety(y - 20)
elif self._direccion == 'izquierda':
x = self.snake.xcor()
self.snake.setx(x - 20)
elif self._direccion == 'derecha':
x = self.snake.xcor()
self.snake.setx(x + 20)
# Mover los segmentos en reversa
for i in range(len(self._segmentos) - 1, 0, -1):
x = self._segmentos[i - 1].xcor()
y = self._segmentos[i - 1].ycor()
self._segmentos[i].goto(x, y)
# Mover el primer segmento a la cabeza de la serpiente
if len(self._segmentos) > 0:
x = self.snake.xcor()
y = self.snake.ycor()
self._segmentos[0].goto(x, y)
def play(self):
'''Este método hace que la serpiente avance constantemente y evalúa las colisiones'''
while True:
self.screen.update()
self.colision_borde()
self.colision_comida()
time.sleep(self._delay)
self.move()
self.screen.mainloop()
def colision_borde(self):
# Definimos los bordes del tablero
bxcor = (self._ancho // 2) - 20
bycor = (self._alto // 2) - 20
if (
self.snake.xcor() > bxcor
or self.snake.xcor() < -bxcor
or self.snake.ycor() > bycor
or self.snake.ycor() < -bycor
):
time.sleep(1)
self.snake.goto(0, 0)
self._direccion = None
# Reiniciar el delay
self._delay = 0.1
# Actualizar puntuación máxima
if self._score > self._high_score:
self._high_score = self._score
self._score = 0
self._print_score()
# Reiniciar el cuerpo de la serpiente con solo un segmento
for segmento in self._segmentos:
segmento.hideturtle()
self._segmentos.clear()
self._segmentos.append(turtle.Turtle())
self._segmentos[0].speed(0)
self._segmentos[0].shape('square')
self._segmentos[0].color('black')
self._segmentos[0].penup()
self._segmentos[0].goto(0, 0)
def colision_comida(self):
if self.snake.distance(self.comida) < 20:
# Mover la comida a un lugar aleatorio
bxcor = (self._ancho // 2) - 20
bycor = (self._alto // 2) - 20
x = random.randint(-bxcor, bxcor)
y = random.randint(-bycor, bycor)
self.comida.goto(x, y)
# Reducir el delay cada vez que come
self._delay -= 0.001
# Aumentar el score
self._score += 10
self._print_score()
# Agregar un nuevo segmento
self._agregar_segmento()
def _agregar_segmento(self):
segmento = turtle.Turtle()
segmento.speed(0)
segmento.shape('square')
segmento.color('black')
segmento.penup()
self._segmentos.append(segmento)
def _print_score(self):
self.texto.clear()
self.texto.write('Puntos: {} Record: {}'.format(self._score, self._high_score), align='center', font=('Courier', 24, 'normal'))
snake_game = SnakeGame()
snake_game.play()
¡Enhorabuena! Ya casi has completado la implementación de tu videojuego. Lo único que te queda por añadir son las colisiones con el propio cuerpo de la serpiente.
Implementa los métodos que consideres necesarios para introducir colisiones con el propio cuerpo de la serpiente.
import turtle
import time
import random
class SnakeGame:
def __init__(self, width=800, height=800, color="#CEFF00"):
'''Inicializa los componentes del juego.'''
self._ancho = width
self._alto = height
# Inicializa el lienzo
self.screen = turtle.Screen()
self.screen.title('Videojuego Snake')
self.screen.bgcolor(color)
self.screen.setup(width=width, height=height)
self.screen.tracer(0)
# Inicializa la serpiente
self.snake = turtle.Turtle()
self.snake.speed(0)
self.snake.shape('square')
self.snake.color('black')
self.snake.penup()
self.snake.goto(0, 0)
# Inicializa los segmentos de la serpiente
self._segmentos = []
self._segmentos.append(turtle.Turtle())
self._segmentos[0].speed(0)
self._segmentos[0].shape('square')
self._segmentos[0].color('black')
self._segmentos[0].penup()
self._segmentos[0].goto(0, 0)
# Inicializa la comida de la serpiente
self.comida = turtle.Turtle()
self.comida.speed(0)
self.comida.shape('circle')
self.comida.color('white')
self.comida.penup()
self.comida.goto(0, 100)
# Inicializa el texto que se muestra en pantalla
self.texto = turtle.Turtle()
self.texto.speed(0)
self.texto.penup()
self.texto.color('black')
self.texto.hideturtle() # Método que oculta el puntero
self.texto.goto(0, (height / 2) - 40) # Posición arriba del todo
# Atributos de la clase
self._direccion = None
self._delay = 0.1
self._score = 0
self._high_score = 0
# Asociar movimientos a las teclas
self.screen.listen()
self.screen.onkeypress(self.arriba, 'w')
self.screen.onkeypress(self.abajo, 's')
self.screen.onkeypress(self.izquierda, 'a')
self.screen.onkeypress(self.derecha, 'd')
# Inicializar score
self._print_score()
def arriba(self):
'''Este método define el movimiento hacia arriba de la serpiente'''
if self._direccion != 'abajo':
self._direccion = 'arriba'
def abajo(self):
'''Este método define el movimiento hacia abajo de la serpiente'''
if self._direccion != 'arriba':
self._direccion = 'abajo'
def izquierda(self):
'''Este método define el movimiento hacia la izquierda de la serpiente'''
if self._direccion != 'derecha':
self._direccion = 'izquierda'
def derecha(self):
'''Este método define el movimiento hacia la derecha de la serpiente'''
if self._direccion != 'izquierda':
self._direccion = 'derecha'
def move(self):
'''Este método mueve y actualiza las coordenadas la serpiente'''
if self._direccion == 'arriba':
y = self.snake.ycor()
self.snake.sety(y + 20)
elif self._direccion == 'abajo':
y = self.snake.ycor()
self.snake.sety(y - 20)
elif self._direccion == 'izquierda':
x = self.snake.xcor()
self.snake.setx(x - 20)
elif self._direccion == 'derecha':
x = self.snake.xcor()
self.snake.setx(x + 20)
# Verificar colisiones con el cuerpo de la serpiente
for segmento in self._segmentos:
if self.snake.distance(segmento) < 20:
self.colision_cuerpo()
# Mover los segmentos en reversa
for i in range(len(self._segmentos) - 1, 0, -1):
x = self._segmentos[i - 1].xcor()
y = self._segmentos[i - 1].ycor()
self._segmentos[i].goto(x, y)
# Mover el primer segmento a la cabeza de la serpiente
if len(self._segmentos) > 0:
x = self.snake.xcor()
y = self.snake.ycor()
self._segmentos[0].goto(x, y)
def play(self):
'''Este método hace que la serpiente avance constantemente y evalúa las colisiones'''
while True:
self.screen.update()
self.colision_borde()
self.colision_comida()
time.sleep(self._delay)
self.move()
self.screen.mainloop()
def colision_borde(self):
# Definimos los bordes del tablero
bxcor = (self._ancho // 2) - 20
bycor = (self._alto // 2) - 20
if (
self.snake.xcor() > bxcor
or self.snake.xcor() < -bxcor
or self.snake.ycor() > bycor
or self.snake.ycor() < -bycor
):
time.sleep(1)
self.snake.goto(0, 0)
self._direccion = None
# Reiniciar el delay
self._delay = 0.1
# Actualizar puntuación máxima
if self._score > self._high_score:
self._high_score = self._score
self._score = 0
self._print_score()
# Reiniciar el cuerpo de la serpiente con solo un segmento
for segmento in self._segmentos:
segmento.hideturtle()
self._segmentos.clear()
self._segmentos.append(turtle.Turtle())
self._segmentos[0].speed(0)
self._segmentos[0].shape('square')
self._segmentos[0].color('black')
self._segmentos[0].penup()
self._segmentos[0].goto(0, 0)
def colision_comida(self):
if self.snake.distance(self.comida) < 20:
# Mover la comida a un lugar aleatorio
bxcor = (self._ancho // 2) - 20
bycor = (self._alto // 2) - 20
x = random.randint(-bxcor, bxcor)
y = random.randint(-bycor, bycor)
self.comida.goto(x, y)
# Reducir el delay cada vez que come
self._delay -= 0.001
# Aumentar el score
self._score += 10
self._print_score()
# Agregar un nuevo segmento
self._agregar_segmento()
def colision_cuerpo(self):
time.sleep(1)
self.snake.goto(0, 0)
self._direccion = None
# Reiniciar el delay
self._delay = 0.1
# Actualizar puntuación máxima
if self._score > self._high_score:
self._high_score = self._score
self._score = 0
self._print_score()
# Reiniciar el cuerpo de la serpiente con solo un segmento
for segmento in self._segmentos:
segmento.hideturtle()
self._segmentos.clear()
self._segmentos.append(turtle.Turtle())
self._segmentos[0].speed(0)
self._segmentos[0].shape('square')
self._segmentos[0].color('black')
self._segmentos[0].penup()
self._segmentos[0].goto(0, 0)
def _agregar_segmento(self):
segmento = turtle.Turtle()
segmento.speed(0)
segmento.shape('square')
segmento.color('grey')
segmento.penup()
self._segmentos.append(segmento)
def _print_score(self):
self.texto.clear()
self.texto.write('Puntos: {} Record: {}'.format(self._score, self._high_score), align='center', font=('Courier', 24, 'normal'))
Y ya tendríamos implementado nuestro videojuego Snake. Aquí os dejo un enlace a mi repositorio de GitHub donde podéis verlo en detalle y ejecutarlo: