Un ejemplo de videojuego de plataformas, en los que los personajes tienen que caminar, correr y escalar sobre una serie de plataformas con enemigos, mientras van recogiendo una serie de objetos para poder completar el juego, es 'Donkey Kong', que fue el segundo videojuego de este tipo que se creó (1981).
Pues bien, ya que estoy entreteniéndome programando en python este videojuego, con programación orientada a objetos (POO) y utilizando la librería pygame, en éste y los siguientes tutoriales explico como he implementado el salto de 'Jumpman' (personaje que en posteriores juegos de Nintendo pasó a llamarse Mario).
En este primer tutorial pongo un script para implementar única y exclusivamente el salto, es decir, sin adornos (animación del personaje cuando anda y salta, sonidos, etc.), para centrarme sólo en el salto, y dejo para posteriores posts el completar este script con los detalles estéticos y otros adicionales.
Creo que los comentarios en el código hacen que éste sea autoexplicativo, por lo que los comentarios adicionales que incluyo son los que considero estrictamente necesarios para explicar algúnos aspectos importantes.
1.- Importar las librerías necesarias:
import pygame
import os
2.- Inicializar pygame, crear ventana e instancia del personaje:
def donkey_kong():
# Inicializar módulos internos de pygame.
pygame.init()
# Establecer tamaño de la ventana.
# Crear una superficie de visualización: la ventana, y centrarla.
os.environ['SDL_VIDEO_CENTERED']='1'
ventana = pygame.display.set_mode((674, 430))
# Título de la ventana.
pygame.display.set_caption('Donkey Kong')
# Cargar la imagen del fondo y cambiar el formato de píxel para crear una
# copia que se dibujará más rápidamente en la pantalla.
fondo = pygame.image.load('recursos/imagenes/fondo_1.png')
fondo = fondo.convert()
# Posición inicial de Jumpman.
x, y = 120, 365
# Grupo individual para Jumpman y dibujarlo.
grupo_jumpman = pygame.sprite.GroupSingle()
jumpman = Jumpman(x, y)
grupo_jumpman.add(jumpman)
# Reloj para ejecutar el videojuego.
reloj = pygame.time.Clock()
# El juego se ejecutará a 60 frames por segundo.
fps = 60
3.- Bucle principal del juego:
while True:
# Ejecutar el siguiente frame.
reloj.tick(fps)
# Escuchar cada uno de los eventos de la lista de eventos de Pygame.
for evento in pygame.event.get():
# Finalizar el juego cuando se produzca el evento de terminación
# del programa (cierre de la ventana).
if evento.type == pygame.QUIT:
pygame.quit()
return
# Obtener la lista de teclas pulsadas.
teclas = pygame.key.get_pressed()
# Actualizar sprites.
grupo_jumpman.update(teclas, 365)
# Copiar la imagen de fondo de la ventana en el canvas que la mostrará.
ventana.blit(fondo, (0, 0))
# Dibujar sprites.
grupo_jumpman.draw(ventana)
# Mostrar la ventana dibujada (cambiar buffers, buffer pantalla a
# disponible para dibujar y viceversa.
pygame.display.flip()
pygame.quit()
El manejo de las teclas pulsadas se hará mediante el método key.get_pressed(), que obtiene el estado de todas las teclas del teclado.
4.- Clase del personaje:
class Jumpman(pygame.sprite.Sprite):
# Jumpman (Mario) estará definido por la clase Jumpman, que hereda de la
# clase sprite.Sprite de Pygame. Clase base para objetos visibles del
# juego.
def __init__(self, x, y):
super().__init__()
self.x, self.y = x, y
self.vel_x = 3
self.vel_y = 0
self.en_suelo = True
self.en_salto = False
self.sentido_salto = 0
self.altura_salto = 10
self.gravedad = 1
self.image = pygame.image.load('recursos/imagenes/' +
'jumpman_derecha_1.png').convert_alpha()
def update(self, teclas, suelo_y):
# El método update() se ejecutará en cada frame, y permite gestionar
# las teclas pulsadas para producir los movimientos del personaje
# (andar y saltar) y actualizar la posición de Jumpman.
self.teclas = teclas
self.suelo_y = suelo_y
# Movimiento horizontal (tanto si el personaje está en el suelo como
# si está saltando).
if self.en_suelo:
if self.teclas[pygame.K_LEFT]:
self.image = pygame.image.load('recursos/imagenes/' +
'jumpman_izquierda_1.png') \
.convert_alpha()
self.x -= self.vel_x
elif self.teclas[pygame.K_RIGHT]:
self.image = pygame.image.load('recursos/imagenes/' +
'jumpman_derecha_1.png') \
.convert_alpha()
self.x += self.vel_x
elif self.en_salto:
self.x += self.sentido_salto * self.vel_x * 2
# Salto.
if self.teclas[pygame.K_SPACE] and self.en_suelo:
self.vel_y = -self.altura_salto
self.en_suelo = False
self.en_salto = True
# Guardar el sentido en el que se inicia el salto.
if self.teclas[pygame.K_LEFT]:
self.sentido_salto = -1
elif self.teclas[pygame.K_RIGHT]:
self.sentido_salto = 1
else:
self.sentido_salto = 0
# Aplicar gravedad
self.vel_y += self.gravedad
self.y += self.vel_y
# Colisión con el suelo
if self.y >= self.suelo_y:
self.y = self.suelo_y
self.vel_y = 0
self.en_suelo = True
self.en_salto = False
# Actualizar la posición de Jumpman.
self.rect = self.image.get_rect(center=(self.x, self.y))
Hay que tener en cuenta que en el salto se pretende que cuando éste se inicie se complete a una misma velocidad hasta su finalización, es decir, el pulsar o levantar las teclas de movimiento horizontal durante el mismo no debe tener ningún efecto sobre su desarrolllo.
5.- Poniendo todo junto:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# SALTAR 1:
#
# Primera aproximación al salto de un personaje de videojuego.
#
# Autor: Mikel García Larragan.
# https://mikelgarcialarragan.blogspot.com/
import pygame
import os
class Jumpman(pygame.sprite.Sprite):
# Jumpman (Mario) estará definido por la clase Jumpman, que hereda de la
# clase sprite.Sprite de Pygame. Clase base para objetos visibles del
# juego.
def __init__(self, x, y):
super().__init__()
self.x, self.y = x, y
self.vel_x = 3
self.vel_y = 0
self.en_suelo = True
self.en_salto = False
self.sentido_salto = 0
self.altura_salto = 10
self.gravedad = 1
self.image = pygame.image.load('recursos/imagenes/' +
'jumpman_derecha_1.png').convert_alpha()
def update(self, teclas, suelo_y):
# El método update() se ejecutará en cada frame, y permite gestionar
# las teclas pulsadas para producir los movimientos del personaje
# (andar y saltar) y actualizar la posición de Jumpman.
self.teclas = teclas
self.suelo_y = suelo_y
# Movimiento horizontal (tanto si el personaje está en el suelo como
# si está saltando).
if self.en_suelo:
if self.teclas[pygame.K_LEFT]:
self.image = pygame.image.load('recursos/imagenes/' +
'jumpman_izquierda_1.png') \
.convert_alpha()
self.x -= self.vel_x
elif self.teclas[pygame.K_RIGHT]:
self.image = pygame.image.load('recursos/imagenes/' +
'jumpman_derecha_1.png') \
.convert_alpha()
self.x += self.vel_x
elif self.en_salto:
self.x += self.sentido_salto * self.vel_x * 2
# Salto.
if self.teclas[pygame.K_SPACE] and self.en_suelo:
self.vel_y = -self.altura_salto
self.en_suelo = False
self.en_salto = True
# Guardar el sentido en el que se inicia el salto.
if self.teclas[pygame.K_LEFT]:
self.sentido_salto = -1
elif self.teclas[pygame.K_RIGHT]:
self.sentido_salto = 1
else:
self.sentido_salto = 0
# Aplicar gravedad
self.vel_y += self.gravedad
self.y += self.vel_y
# Colisión con el suelo
if self.y >= self.suelo_y:
self.y = self.suelo_y
self.vel_y = 0
self.en_suelo = True
self.en_salto = False
# Actualizar la posición de Jumpman.
self.rect = self.image.get_rect(center=(self.x, self.y))
def donkey_kong():
# Inicializar módulos internos de pygame.
pygame.init()
# Establecer tamaño de la ventana.
# Crear una superficie de visualización: la ventana, y centrarla.
os.environ['SDL_VIDEO_CENTERED']='1'
ventana = pygame.display.set_mode((674, 430))
# Título de la ventana.
pygame.display.set_caption('Donkey Kong')
# Cargar la imagen del fondo y cambiar el formato de píxel para crear una
# copia que se dibujará más rápidamente en la pantalla.
fondo = pygame.image.load('recursos/imagenes/fondo_1.png')
fondo = fondo.convert()
# Posición inicial de Jumpman.
x, y = 120, 365
# Grupo individual para Jumpman y dibujarlo.
grupo_jumpman = pygame.sprite.GroupSingle()
jumpman = Jumpman(x, y)
grupo_jumpman.add(jumpman)
# Reloj para ejecutar el videojuego.
reloj = pygame.time.Clock()
# El juego se ejecutará a 60 frames por segundo.
fps = 60
while True:
# Ejecutar el siguiente frame.
reloj.tick(fps)
# Escuchar cada uno de los eventos de la lista de eventos de Pygame.
for evento in pygame.event.get():
# Finalizar el juego cuando se produzca el evento de terminación
# del programa (cierre de la ventana).
if evento.type == pygame.QUIT:
pygame.quit()
return
# Obtener la lista de teclas pulsadas.
teclas = pygame.key.get_pressed()
# Actualizar sprites.
grupo_jumpman.update(teclas, 365)
# Copiar la imagen de fondo de la ventana en el canvas que la mostrará.
ventana.blit(fondo, (0, 0))
# Dibujar sprites.
grupo_jumpman.draw(ventana)
# Mostrar la ventana dibujada (cambiar buffers, buffer pantalla a
# disponible para dibujar y viceversa.
pygame.display.flip()
pygame.quit()
if __name__ == '__main__':
donkey_kong()
Si lo ejecutamos:
Comentarios
Publicar un comentario