En todos estos desarrollos he intentado que los fuentes estén convenientemente comentados, incluso en ocasiones 'pecando' por exceso, pero aún así, tal y como digo, creo que algunas explicaciones adicionales sobre ciertos aspectos pueden ser útiles para aquellas personas que se introduzcan en la programación en python con pygame.
En esta primera entrada, comienzo con la primera entrega del tutorial correspondiente al juego de cartas Klondike (la variante más popular del solitario), que consiste en ir apilando, en orden ascendente, los cuatro palos de una baraja francesa o de póker; y cuando termine con todas las entregas publicaré mi propia versión del mismo.En este juego se utilizan 52 cartas de una baraja estándar (es decir, todas menos los dos comodines). Todos lo conoceremos porque adquirió una gran popularidad cuando Microsoft lo incluyó en su sistema operativo Windows 3.0.2.
En la programación de este solitario, y en general de cuaquier juego de cartas, juegan un papel fundamental el ratón y la gestión de sus eventos, ya que hay que implementar, entre otras, la funcionalidad del arrastre de cartas ('drag and drop').
Para ello, pygame permite interactuar con la entrada del ratón en un entorno de juego a modo de interface entre el juego en sí y el jugador, de forma que se pueda detectar la posición del ratón y gestionar los eventos asociados al mismo: clics realizados, arrastrar y soltar objetos ('drag and drop'), etc.
Pues bien, en esta primera entrega de este tutorial voy a empezar por cómo implementar esta última funcionalidad: arrastrar y soltar objetos.
Antes que nada voy a crear, centrar y dibujar la ventana:
Tras la ejecución de este script obtenemos lo siguiente:Ahora, voy a dibujar una carta (por ejemplo, el As de corazones) y los sitios para ir apilando las cartas de los difentes palos de la baraja francesa o de póker (corazones, diamantes, picas y tréboles). Para ello creo las respectivas clases ('Palo' y 'Carta').!/usr/bin/env python #!/usr/bin/env python # -*- coding: utf-8 -*- # # TUTORIAL: KLONDIKE(I). # # Pygame es una colección de módulos Python diseñados para crear videojuegos. # # Autor: Mikel García Larragan. # https://mikelgarcialarragan.blogspot.com/ import pygame import os def klondike(): while True: # inicializar módulos internos de pygame. pygame.init() # Obtener las dimensiones de la pantalla. informacion_pantalla = pygame.display.Info() # Establecer tamaño de la ventana. ancho_pantalla = informacion_pantalla.current_w - int(informacion_pantalla.current_w * 0.5) alto_pantalla = informacion_pantalla.current_h - int(informacion_pantalla.current_h * 0.45) # crear una superficie de visualización: la ventana, y centrarla. os.environ['SDL_VIDEO_CENTERED']='1' ventana = pygame.display.set_mode((ancho_pantalla,alto_pantalla)) # Título de la ventana. pygame.display.set_caption('Klondike') # Icono de la ventana. # Cargar la imagen del icono. icono = pygame.image.load('klondike.ico') # Establecer el icono de la ventana en tiempo de ejecución. pygame.display.set_icon(icono) # Cargar la imagen del fondo del juego. fondo_juego = pygame.image.load('fondo_juego.png') # Cambiar el formato de píxel del fondo del juego para crear una copia que se dibujará más rápidamente en la pantalla. fondo_juego = fondo_juego.convert() # Cargar archivos de fuentes y sonidos. sonido_click = pygame.mixer.Sound('click.wav') # Crear canal para sonidos. canal1 = pygame.mixer.Channel(0) # Reloj para ejecutar el juego. reloj = pygame.time.Clock() # El juego se ejecutará a 60 frames por segundo. fps = 60 # Bucle juego. while True: # Ejecutar el siguiente frame. reloj.tick(fps) # Escuchar cada uno de 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 # Copiar la imagen de fondo de la ventana en el canvas que la mostrará. ventana.blit(fondo_juego, (0, 0)) # Mostrar la ventana dibujada (cambiar buffers, buffer pantalla a disponible para dibujar y viceversa). pygame.display.flip() if __name__ == '__main__': klondike()
#!/usr/bin/env python # -*- coding: utf-8 -*- # # TUTORIAL: KLONDIKE(I). # # Pygame es una colección de módulos Python diseñados para crear videojuegos. # # Autor: Mikel García Larragan. # https://mikelgarcialarragan.blogspot.com/ import pygame import os class Palo(pygame.sprite.Sprite): # Los palos de las cartas del mazo estará definidos por la clase Palo. def __init__(self, palo, x, y): super().__init__() self.palo = palo + 1 self.x, self.y = x, y self.image = pygame.image.load('F_' + str(self.palo) + '.png').convert_alpha() self.rect = self.image.get_rect(center=(self.x, self.y)) class Carta(pygame.sprite.Sprite): # Las cartas estarán definidas por la clase Carta. def __init__(self): super().__init__() self.image = pygame.image.load('F_1_1.png').convert_alpha() def mover(self, x, y): # Método que permite mover las cartas. self.x, self.y = x, y self.rect = self.image.get_rect(center=(self.x, self.y)) def klondike(): while True: # inicializar módulos internos de pygame. pygame.init() # Obtener las dimensiones de la pantalla. informacion_pantalla = pygame.display.Info() # Establecer tamaño de la ventana. ancho_pantalla = informacion_pantalla.current_w - int(informacion_pantalla.current_w * 0.5) alto_pantalla = informacion_pantalla.current_h - int(informacion_pantalla.current_h * 0.45) # crear una superficie de visualización: la ventana, y centrarla. os.environ['SDL_VIDEO_CENTERED']='1' ventana = pygame.display.set_mode((ancho_pantalla,alto_pantalla)) # Título de la ventana. pygame.display.set_caption('Klondike') # Icono de la ventana. # Cargar la imagen del icono. icono = pygame.image.load('klondike.ico') # Establecer el icono de la ventana en tiempo de ejecución. pygame.display.set_icon(icono) # Cargar la imagen del fondo del juego. fondo_juego = pygame.image.load('fondo_juego.png') # Cambiar el formato de píxel del fondo del juego para crear una copia que se dibujará más rápidamente en la pantalla. fondo_juego = fondo_juego.convert() # Cargar archivos de fuentes y sonidos. sonido_click = pygame.mixer.Sound('click.wav') # Crear canal para sonidos. canal1 = pygame.mixer.Channel(0) # Dibujar los sitios de las pilas de los palos e incluirlos en un grupo. grupo_palos = pygame.sprite.Group() x, y = ancho_pantalla - 485, alto_pantalla - 494 for num_palo in range(4): palo = Palo(num_palo, x, y) grupo_palos.add(palo) x += 120 # Grupo individual para la carta a arrastrar y soltar. grupo_carta = pygame.sprite.GroupSingle() carta = Carta() grupo_carta.add(carta) carta.mover(255, 100) # Reloj para ejecutar el juego. reloj = pygame.time.Clock() # El juego se ejecutará a 60 frames por segundo. fps = 60 # Bucle juego. while True: # Ejecutar el siguiente frame. reloj.tick(fps) # Escuchar cada uno de 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 # Actualiza sprites. grupo_palos.update() grupo_carta.update() # Copiar la imagen de fondo de la ventana en el canvas que la mostrará. ventana.blit(fondo_juego, (0, 0)) # dibujar sprites. grupo_palos.draw(ventana) grupo_carta.draw(ventana) # Mostrar la ventana dibujada (cambiar buffers, buffer pantalla a disponible para dibujar y viceversa). pygame.display.flip() if __name__ == '__main__': klondike()
# Comprobar si se ha presionado o liberado el botón izquierdo del ratón.
if evento.type == pygame.MOUSEBUTTONDOWN:
if evento.button == 1:
print('Se ha pulsado el botón izquierdo del ratón')
elif evento.type == pygame.MOUSEBUTTONUP:
if evento.button == 1:
print('Se ha liberado el botón izquierdo del ratón')
2.- Obtener la posición del ratón y comprobar, si cuando se hace clic del botón izquierdo del ratón, éste se realiza sobre la carta:# Seguimiento del movimiento del ratón. elif evento.type == pygame.MOUSEMOTION: print('rastreando el movimiento del ratón', evento.pos)
Como se puede observar en el código anterior, además de lo indicado he añadido dos variables para guardar la posición de la carta en el momento en el que se comienza a arrastrar ésta, y una variable boolena para indicar que se está arrastrando.if evento.type == pygame.MOUSEBUTTONDOWN: if evento.button == 1: # Obtener posición del puntero del ratón. posicion_raton = pygame.mouse.get_pos() # Comprobar si se ha realizado click del botón izquierdo del ratón sobre la carta. if carta.rect.collidepoint(posicion_raton): canal1.play(sonido_click) carta_a_arrastrar_x, carta_a_arrastrar_y = carta.rect.center[0], carta.rect.center[1] arrastrando_carta = True
if evento.type == pygame.MOUSEBUTTONUP:
if evento.button == 1 and arrastrando_carta:
for sitio_palo in grupo_palos:
if carta.rect.colliderect(sitio_palo):
colision_palo = True
if not colision_palo:
carta.mover(carta_a_arrastrar_x, carta_a_arrastrar_y)
else:
colision_palo = False
arrastrando_carta = False
#!/usr/bin/env python # -*- coding: utf-8 -*- # # TUTORIAL: KLONDIKE(I). # # Pygame es una colección de módulos Python diseñados para crear videojuegos. # # Autor: Mikel García Larragan. # https://mikelgarcialarragan.blogspot.com/ import pygame import os class Palo(pygame.sprite.Sprite): # Los palos de las cartas del mazo estará definidos por la clase Palo. def __init__(self, palo, x, y): super().__init__() self.palo = palo + 1 self.x, self.y = x, y self.image = pygame.image.load('F_' + str(self.palo) + '.png').convert_alpha() self.rect = self.image.get_rect(center=(self.x, self.y)) class Carta(pygame.sprite.Sprite): # Las cartas estarán definidas por la clase Carta. def __init__(self): super().__init__() self.image = pygame.image.load('F_1_1.png').convert_alpha() def mover(self, x, y): # Método que permite mover las cartas. self.x, self.y = x, y self.rect = self.image.get_rect(center=(self.x, self.y)) def klondike(): while True: # inicializar módulos internos de pygame. pygame.init() # Obtener las dimensiones de la pantalla. informacion_pantalla = pygame.display.Info() # Establecer tamaño de la ventana. ancho_pantalla = informacion_pantalla.current_w - int(informacion_pantalla.current_w * 0.5) alto_pantalla = informacion_pantalla.current_h - int(informacion_pantalla.current_h * 0.45) # crear una superficie de visualización: la ventana, y centrarla. os.environ['SDL_VIDEO_CENTERED']='1' ventana = pygame.display.set_mode((ancho_pantalla,alto_pantalla)) # Título de la ventana. pygame.display.set_caption('Klondike') # Icono de la ventana. # Cargar la imagen del icono. icono = pygame.image.load('klondike.ico') # Establecer el icono de la ventana en tiempo de ejecución. pygame.display.set_icon(icono) # Cargar la imagen del fondo del juego. fondo_juego = pygame.image.load('fondo_juego.png') # Cambiar el formato de píxel del fondo del juego para crear una copia que se dibujará más rápidamente en la pantalla. fondo_juego = fondo_juego.convert() # Cargar archivos de fuentes y sonidos. sonido_click = pygame.mixer.Sound('click.wav') # Crear canal para sonidos. canal1 = pygame.mixer.Channel(0) # Dibujar los sitios de las pilas de los palos e incluirlos en un grupo. grupo_palos = pygame.sprite.Group() x, y = ancho_pantalla - 485, alto_pantalla - 494 for num_palo in range(4): palo = Palo(num_palo, x, y) grupo_palos.add(palo) x += 120 # Grupo individual para la carta a arrastrar y soltar. grupo_carta = pygame.sprite.GroupSingle() carta = Carta() grupo_carta.add(carta) carta.mover(255, 100) # Variables booleanas que indican si se está arrastrando la carta y si hay colision con uno o más de los sitios de # los palos, respectivamente. arrastrando_carta, colision_palo = False, False # Reloj para ejecutar el juego. reloj = pygame.time.Clock() # El juego se ejecutará a 60 frames por segundo. fps = 60 # Bucle juego. while True: # Ejecutar el siguiente frame. reloj.tick(fps) # Escuchar cada uno de 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 # Comprobar si se ha presionado o liberado el botón izquierdo del ratón. elif evento.type == pygame.MOUSEBUTTONDOWN: if evento.button == 1: # Obtener posición del puntero del ratón. posicion_raton = pygame.mouse.get_pos() # Comprobar si se ha realizado click del botón izquierdo del ratón sobre la carta. if carta.rect.collidepoint(posicion_raton): canal1.play(sonido_click) carta_a_arrastrar_x, carta_a_arrastrar_y = carta.rect.center[0], carta.rect.center[1] arrastrando_carta = True elif evento.type == pygame.MOUSEBUTTONUP: if evento.button == 1 and arrastrando_carta: for sitio_palo in grupo_palos: if carta.rect.colliderect(sitio_palo): colision_palo = True if not colision_palo: carta.mover(carta_a_arrastrar_x, carta_a_arrastrar_y) else: colision_palo = False arrastrando_carta = False # Seguimiento del movimiento del ratón. elif evento.type == pygame.MOUSEMOTION: if arrastrando_carta: posicion_raton_x, posicion_raton_y = evento.pos carta.mover(posicion_raton_x, posicion_raton_y) # Actualiza sprites. grupo_palos.update() grupo_carta.update() # Copiar la imagen de fondo de la ventana en el canvas que la mostrará. ventana.blit(fondo_juego, (0, 0)) # dibujar sprites. grupo_palos.draw(ventana) grupo_carta.draw(ventana) # Mostrar la ventana dibujada (cambiar buffers, buffer pantalla a disponible para dibujar y viceversa). pygame.display.flip() if __name__ == '__main__': klondike()
Comentarios
Publicar un comentario