SlideShare a Scribd company logo
1 of 23
Download to read offline
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
    
                        CURSO: 1º BACHILLERATO




Animaciones Realistas
Guy se pone a andar
La animación es algo más que volcar una imagen en pantalla y moverla por ella. En
realidad, para que las animaciones parezcan realistas, necesitamos mucho más;
necesitamos que la propia imagen varíe a medida que la desplazamos. Para
ilustrar la forma de hacerlo, vamos a usar un personaje famoso; Guybrush
Threepwood, el protagonista de la saga de videojuegos Monkey Island (por cierto, si
no la conoces te la aconsejo, es una de las sagas más famosas y entretenidas de la historia
de los videojuegos).




Conseguiremos algunas imágenes de nuestro personaje por Internet y trabajaremos hasta
que la animación sea aceptable (no perfecta, pues las imágenes disponibles son limitadas;
en un juego real, el ilustrador que trabaja con el programador dibuja cada una de las
posiciones y los movimientos para que produzca un movimiento suave)
¡Escribamos código!


 PÁGINA 1 DE 23
                              
             DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
    
                    CURSO: 1º BACHILLERATO


guy01.py
El primer paso es, partiendo de una imagen de nuestro personaje, cargarla en memoria y
hacer que se desplace por la pantalla. Sería algo así:



 # -*- coding: utf-8 -*-

 # En este primer ejemplo, ponemos la imagen de Guy en pantalla,
 # desplazándolo con las teclas 'a' y 's'.

 import pygame, sys
 from pygame.locals import *

 # Inicializar pygame
 pygame.init()

 # Crear la surface
 visor = pygame.display.set_mode((600, 600), 0, 32)

 # Poner el título de la ventana
 pygame.display.set_caption('Guy')

 # Cargar la imagen del hombre
 guy = pygame.image.load('guy.jpg').convert()

 # Variable que controla la posición de Guy
 pos = 100

 # El bucle de eventos
 while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
    # Modificar posición en función de la tecla pulsada
    teclasPulsadas = pygame.key.get_pressed()
    if teclasPulsadas[K_a]:
        pos = pos - 1
    if teclasPulsadas[K_s]:
        pos = pos + 1

    # Dibujar el fondo de color
    visor.fill((233,233,233))

    # Dibujar a Guy
    visor.blit(guy, (pos,100))

    # Volcar la surface en la ventana de pygame
    pygame.display.update()




 PÁGINA 2 DE 23
                              
          DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
   
                       CURSO: 1º BACHILLERATO

Ya conocemos las técnicas necesarias para entender el código anterior. Sabemos cargar
imágenes en memoria, comprobar si se ha pulsado una determinada tecla y desplazar
objetos por la pantalla modificando sus coordenadas.
Lo único matizable es que usamos una imagen sin transparencias. Si tuviera un fondo
transparente, se nos movería por la pantalla sin problemas. Como no es el caso, para
disimularlo, hemos elegido un color de fondo para la ventana similar al de la
propia imagen (hay otros métodos, se puede indicar a PyGame que use determinado
color como color transparente, pero entonces nos hemos asegurar que el propio
fondo de la imagen es exactamente de ese color y no varía ningún pixel que se notaría con
el movimiento; éste, por desgracia, es nuestro caso).




 PÁGINA 3 DE 23
                             
            DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
    
                       CURSO: 1º BACHILLERATO


guy02.py
Lo anterior queda muy artificial. ¿Acaso alguien va por la calle completamente rígido y
deslizándose? Si queremos animaciones realistas, necesitamos que la imagen del
protagonista vaya cambiando a medida que va andando; pies juntos, avanza el pie derecho,
lo apoya, hace lo propio con el pie izquierdo, etc.
Hay varias maneras de hacer esto, pero todas pasan por cargar diferentes imágenes del
personaje que queremos animar y dibujarlas en los momentos apropiados. Pero antes de
ello, ¿cómo conseguimos esas imágenes y cómo disponemos de ellas?
Tanto si eres un buen dibujante como si buscas por Internet tus recursos (libres), una
forma típica de tener archivadas las diferentes imágenes es en un solo archivo de
sprite. Para que te hagas una idea, éste es el que vamos a usar:




Esta única imagen contiene todos los pasos intermedios que va a dar nuestro protagonista
(de paso puedes ver cómo era en la versión original del juego y cómo quedó en la nueva
versión). Un aviso; como este trabajo es sólo con intención pedagógica, la animación no va
a quedar del todo bien. En realidad necesitaríamos más fotogramas del movimiento o
gestionar mejor la posición de como lo vamos a hacer (fíjate que el tamaño que ocupa cada
fotograma es distinto). En cualquier caso, para aprender la técnica nos bastará.
El código que simplemente extrae uno de los fotogramas de la imagen anterior es el
siguiente:




 PÁGINA 4 DE 23
                              
            DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
     
                      CURSO: 1º BACHILLERATO



   # -*- coding: utf-8 -*-

   # En este segundo ejemplo, ponemos la imagen de Guy cargándola
   # desde el archivo de sprites que contiene todas las imágenes.

   import pygame, sys
   from pygame.locals import *

   # Inicializar pygame
   pygame.init()

   # Crear la surface
   visor = pygame.display.set_mode((600, 600), 0, 32)

   # Poner el título de la ventana
   pygame.display.set_caption('Guy')

   # Cargar la imagen de Guy
   guy = pygame.image.load('sprites.jpg').convert()

   # Variable que controla la posición de Guy
   pos = 100

   # Posición de la parte de la imagen que se visualiza
   x = 130
   y = 10
   w = 120
   h = 340

   # El bucle de eventos
   while True:
      for event in pygame.event.get():
          if event.type == QUIT:
              pygame.quit()
              sys.exit()
      # Modificar posición en función de la tecla pulsada
      teclasPulsadas = pygame.key.get_pressed()
      if teclasPulsadas[K_a]:
          pos = pos - 1
      if teclasPulsadas[K_s]:
          pos = pos + 1

      # Dibujar el fondo de color
      visor.fill((233,233,233))

      # Dibujar a Guy
      visor.blit(guy, (pos,100), (x,y,w,h))

      # Volcar la surface en la ventana de pygame
      pygame.display.update()




PÁGINA 5 DE 23
                               
            DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
    
                        CURSO: 1º BACHILLERATO

La primera modificación, obviamente, es que al archivo de imagen que hemos de cargar en
memoria es distinto:

guy = pygame.image.load('sprites.jpg').convert()

En la variable guy, por tanto, se almacenan todos los fotogramas de la animación del
personaje. Para indicar cuál es el fotograma que queremos usar, necesitamos indicárselo
con las coordenadas de un rect de PyGame (con cualquier programa de dibujo o retoque,
como GIMP, podemos ver cuáles son).

x = 130
y = 10
w = 120
h = 340


El significado, aunque debiera ser evidente, lo tenemos en la siguiente imagen:
           x                         y


                    h




                               w




El resto es simplemente usar la función blit para indicar que se quiere volcar en pantalla
sólo esta parte de la imagen:

   visor.blit(guy, (pos,100), (x,y,w,h))

En efecto, la última tupla (x,y,w,h), como puede verse en el documento de referencia de
PyGame, indica que sólo debe dibujarse parte de una imagen.



 PÁGINA 6 DE 23
                              
             DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
   
                       CURSO: 1º BACHILLERATO


guy03.py
Aunque en las dos versiones anteriores el resultado es el mismo, hemos visto que el código
hace cosas muy distintas. En la primera versión se carga una imagen que se mueve por la
pantalla. En la segunda, se carga otra imagen y se mueve por la pantalla parte de esta.
El resultado de este tercer paso va a ser el mismo también, pero de camino habremos
cargado en memoria todos los fotogramas que forman la animación del personaje aunque
sólo mostremos una. Éste es el código:


    # -*- coding: utf-8 -*-

    # En este tercer ejemplo, cargamos todas las imágenes de Guy desde
    # el archivo de sprites aunque solo mostramos una.

    import pygame, sys
    from pygame.locals import *

    # Inicializar pygame
    pygame.init()

    # Crear la surface
    visor = pygame.display.set_mode((600, 600), 0, 32)

    # Poner el título de la ventana
    pygame.display.set_caption('Guy')

    # Cargar la imagen de Guy
    fotogramas = pygame.image.load('sprites.jpg').convert()

    # Variable que controla la posición de Guy
    pos = 100

    # Almacenamos las diferentes imágenes en un diccionario
    guy = {}
    guy[0] = (0, 10, 120, 340)
    guy[1] = (130, 10, 120, 340)
    guy[2] = (260, 10, 120, 340)
    guy[3] = (405, 10, 140, 340)
    guy[4] = (600, 10, 120, 340)
    guy[5] = (730, 10, 130, 340)
    guy[6] = (870, 10, 170, 340)

    # El bucle de eventos
    while True:
       for event in pygame.event.get():
          if event.type == QUIT:
              pygame.quit()
              sys.exit()




 PÁGINA 7 DE 23
                             
             DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
     
                      CURSO: 1º BACHILLERATO




       # Modificar posición en función de la tecla pulsada
       teclasPulsadas = pygame.key.get_pressed()
       if teclasPulsadas[K_a]:
           pos = pos - 1
       if teclasPulsadas[K_s]:
           pos = pos + 1

       # Dibujar el fondo de color
       visor.fill((233,233,233))

       # Dibujar una imagen del hombre

       visor.blit(fotogramas, (pos,100), guy[1])

       # Volcar la surface en la ventana de pygame
       pygame.display.update()




Para empezar, hemos cambiado el nombre de la variable que contiene a la imagen de
sprites, pues ahora es simplemente una variable intermedia.

fotogramas = pygame.image.load('sprites.jpg').convert()

El nombre de guy lo reservamos para la variable que contendrá todos los fotogramas.
¿Qué tipo de variable usar? ¿Una lista? Lo más flexible es, quizá, usar un diccionario:

guy = {}
guy[0] =   (0, 10, 120, 340)
guy[1] =   (130, 10, 120, 340)
guy[2] =   (260, 10, 120, 340)
guy[3] =   (405, 10, 140, 340)
guy[4] =   (600, 10, 120, 340)
guy[5] =   (730, 10, 130, 340)
guy[6] =   (870, 10, 170, 340)


Las claves del diccionario son, simplemente, números enteros que indican el orden del
fotograma. Para cada una de ellas, almacenamos un rect que indica la posición del
fotograma en la imagen de sprites (lo que antes poníamos como x, y,w y h). Observa que,
de nuevo, debemos usar un programa de dibujo o retoque para mirar cuáles son las
coordenadas de cada una de esas imágenes.
Finalmente, sólo dibujamos una de ellas con

   visor.blit(fotogramas, (pos,100), guy[1])




 PÁGINA 8 DE 23
                               
            DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
   
                     CURSO: 1º BACHILLERATO


guy04.py
Tres versiones y Guy aún no da ningún paso... Por fin ha llegado el momento de cambiar
esto. En esta versión vamos a conseguir que, al mismo tiempo que nuestro personaje
avance, su imagen vaya cambiando.
Éste es el código:


    # -*- coding: utf-8 -*-

    # Y en el cuarto ejemplo, mostramos una imagen de la animación
    # distinta en cada paso.

    import pygame, sys
    from pygame.locals import *

    # Inicializar pygame
    pygame.init()

    # Crear la surface
    visor = pygame.display.set_mode((600, 600), 0, 32)

    # Poner el título de la ventana
    pygame.display.set_caption('Guy')

    # Cargar la imagen de Guy
    fotogramas = pygame.image.load('sprites.jpg').convert()

    # Variable que controla la posición de Guy
    pos = 100

    # Almacenamos las diferentes imágenes en un diccionario
    guy = {}
    guy[0] = (0, 10, 120, 340)
    guy[1] = (130, 10, 120, 340)
    guy[2] = (260, 10, 120, 340)
    guy[3] = (405, 10, 140, 340)
    guy[4] = (600, 10, 120, 340)
    guy[5] = (730, 10, 130, 340)
    guy[6] = (870, 10, 170, 340)

    # Variable que controla qué imagen del hombre se muestra
    cual = 0

    # El bucle de eventos
    while True:
       for event in pygame.event.get():




 PÁGINA 9 DE 23
                             
           DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
   
                        CURSO: 1º BACHILLERATO



           if event.type == QUIT:
               pygame.quit()
               sys.exit()
       # Modificar posición en función de la tecla pulsada
       teclasPulsadas = pygame.key.get_pressed()
       if teclasPulsadas[K_a]:
           pos = pos - 1
       if teclasPulsadas[K_s]:
           pos = pos + 1
           cual = cual + 1
           if cual > 6:
               cual = 0

       # Dibujar el fondo de color
       visor.fill((233,233,233))

       # Dibujar a Guy
       visor.blit(fotogramas, (pos,100), guy[cual])

       # Volcar la surface en la ventana de pygame
       pygame.display.update()




Observa que si ejecutas este programa verás que las cosas no salen como uno desea, ya que
la imagen cambia excesivamente rápido y no da tiempo a verla. Pero para arreglar esto
tendremos que esperar a la próxima versión...
Ahora de lo que se trata es de ver cómo cambiar la imagen en cada paso.
Vamos a hacerlo, primero, en una sola dirección (pongamos que hacia la derecha). Como
es fácil de imaginar, primero necesitamos una variable que almacene cuál es la imagen que
toca dibujar en cada momento. De ello se encarga cual:

cual = 0

Recuerda que las imágenes (en realidad, la indicación de qué parte de la imagen de sprites
hay que dibujar) están almacenadas en el diccionario guy. Como cual vale inicialmente
0, la expresión guy[cual] será en realidad guy[0], es decir, el primer fotograma de la
animación del movimiento de nuestro protagonista. Sin más que cambiar el valor de la
variable cual, la expresión anterior nos daría otro fotograma.
¿Dónde hacer el cambio de imagen? Acertaste, allí donde se mire si se ha pulsado la tecla
s, cuando hay que desplazarse a la derecha y se aumenta la coordenada pos:


   if teclasPulsadas[K_s]:
       pos = pos + 1
       cual = cual + 1
       if cual > 6:
           cual = 0




 PÁGINA 10 DE 23
                            
              DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
   
                       CURSO: 1º BACHILLERATO

Como puedes ver en el if anterior, si se ha pulsado la tecla s primero se aumenta la
variable pos (recuerda que allí se almacena la coordenada x del personaje) y luego
aumentamos la variable cual para indicar, cuando más adelante se llegue al momento de
dibujar, que hay que cambiar el fotograma de la animación.
Hay que tener cuidado con el número de fotograma indicado. Fíjate que tenemos 7
imágenes para simular el movimiento, indicadas con las claves 0, 1, 2, 3, 4, 5 y 6. Eso
quiere decir que, al aumentar la variable cual no nos debemos pasar de 6. De allí que se
compruebe con un if y, en tal caso, la variable cual se ponga de nuevo a 0.




Como hemos indicado antes, no todo es tan bonito como parece. Visto en movimiento,
¡Guy parece mover los pies a toda velocidad como alma que lleva el diablo! Hmmm...




 PÁGINA 11 DE 23
                            
             DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
   
                      CURSO: 1º BACHILLERATO


guy05.py
El problema que tenemos en la versión anterior de nuestra animación es que no
controlamos la velocidad de ésta, con lo que en cada fotograma se cambia el dibujo de
nuestro personaje; si el programa se ejecuta a 60 fotogramas por segundo, por ejemplo,
Guy cambia de aspecto 60 veces cada segundo y de ahí la locura del movimiento de sus
piernas...
La manera de solucionarlo será ésta:


    # -*- coding: utf-8 -*-

    # Quinto ejemplo, controlamos la velocidad de la animación.

    import pygame, sys
    from pygame.locals import *
    import time

    # Inicializar pygame
    pygame.init()

    # Crear la surface
    visor = pygame.display.set_mode((600, 600), 0, 32)

    # Poner el título de la ventana
    pygame.display.set_caption('Guy')

    # Cargar la imagen de Guy
    fotogramas = pygame.image.load('sprites.jpg').convert()

    # Variable que controla la posición de Guy
    pos = 0

    # Almacenamos las diferentes imágenes en un diccionario
    guy = {}
    guy[0] = (0, 10, 120, 340)
    guy[1] = (130, 10, 120, 340)
    guy[2] = (260, 10, 130, 340)
    guy[3] = (405, 10, 170, 340)
    guy[4] = (600, 10, 120, 340)
    guy[5] = (730, 10, 130, 340)
    guy[6] = (870, 10, 170, 340)

    # Variable que controla qué imagen de Guy se muestra
    cual = 0

    # Controlando el tiempo
    cuanto = 100
    tiempo = 0




 PÁGINA 12 DE 23
                            
            DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
    
                        CURSO: 1º BACHILLERATO



    # El bucle de eventos
    while True:
       for event in pygame.event.get():
           if event.type == QUIT:
               pygame.quit()
               sys.exit()
       # Modificar posición en función de la tecla pulsada
       teclasPulsadas = pygame.key.get_pressed()
       if teclasPulsadas[K_a]:
           pos = pos - 1
       if teclasPulsadas[K_s]:
           pos = pos + 1
           if pygame.time.get_ticks()-tiempo > cuanto:
               tiempo = pygame.time.get_ticks()
               cual = cual + 1
               if cual > 6:
                  cual = 1

       # Dibujar el fondo de color
       visor.fill((233,233,233))

       # Dibujar al hombre
       visor.blit(fotogramas, (pos,100), guy[cual])

       # Volcar la surface en la ventana de pygame
       pygame.display.update()




La forma de controlar la velocidad a la que se cambia el aspecto del personaje es muy
parecida a la que ya vimos cuando regulamos la velocidad en el juego del Pong. Para
empezar, necesitamos dos variables que nos gestionen el tiempo de ejecución y el tiempo
que hay que esperar:

cuanto = 100
tiempo = 0


cuanto indica el número de milisegundos que hay que esperar para cambiar el dibujo.
Los valores concretos que pongamos en esta variable y en otras similares dependerán de
nosotros, de la velocidad que queramos y del número de dibujos que tengamos. La variable
tiempo, recuerda, se encarga de almacenar el momento en el que se cambia el aspecto del
fotograma, para poder comparar con este momento y ver si ha pasado el tiempo suficiente.
Por supuesto, no olvides importar la librería que gestiona el tiempo

import time

ya que allí es donde reside la función pygame.time.get_ticks() que usamos para ver el
tiempo que ha pasado:



 PÁGINA 13 DE 23
                             
             DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
   
                       CURSO: 1º BACHILLERATO



     if pygame.time.get_ticks()-tiempo > cuanto:
        tiempo = pygame.time.get_ticks()
        cual = cual + 1
        if cual > 6:
            cual = 1


¿Ves que es casi lo mismo que en el Pong? Aquí se mira si ha pasado el tiempo suficiente,
en cuyo caso se cambia el fotograma. Y en caso contrario no se hace nada pues no se
ejecuta ninguna de las instrucciones del bloque if.
Otro matiz; habrás notado, quizá que hemos cambiado el número de fotograma en el que
se vuelve a empezar la animación. Antes era cual = 0 y ahora cual = 1. ¿Adivinas por
qué? En efecto, el fotograma número 0 es el que muestra a Guy parado y queda la
animación muy rara al pasar el dibujo por allí cuando está en proceso de andar. Pruébalo:
cambia el 1 por un 0 y ejecuta el programa. ¿Ves a lo que nos referimos? Claramente, el
primer fotograma de la animación andadora ha de ser el 1.




 PÁGINA 14 DE 23
                            
            DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
   
                       CURSO: 1º BACHILLERATO


guy06.py
Hay un defecto evidente en la versión anterior de nuestro programa, y es que cuando
dejamos de pulsar la tecla s el movimiento se para allí donde estuviera, incluido a mitad
de paso.... Lo deseable es que al dejar de moverse, Guy quede esperando quieto, no en esa
postura artificial. Otro ajuste que podemos hacer es con los dos fotogramas que abren el
paso, pues las imágenes son más anchas que las demás (no es lo mismo estar con las
piernas juntas que con las piernas abiertas).
Veamos:


    # -*- coding: utf-8 -*-

    # Sexto ejemplo, ajustamos la animación para que tenga
    # un aspecto más realista.

    import pygame, sys
    from pygame.locals import *
    import time

    # Inicializar pygame
    pygame.init()

    # Crear la surface
    visor = pygame.display.set_mode((600, 600), 0, 32)

    # Poner el título de la ventana
    pygame.display.set_caption('Guy')

    # Cargar la imagen del hombre
    fotogramas = pygame.image.load('sprites.jpg').convert()

    # Variable que controla la posición de Guy
    pos = 0

    # Almacenamos las diferentes imágenes en un diccionario
    guy = {}
    guy[0] = (0, 10, 120, 340)
    guy[1] = (130, 10, 120, 340)
    guy[2] = (260, 10, 130, 340)
    guy[3] = (405, 10, 170, 340)
    guy[4] = (600, 10, 120, 340)
    guy[5] = (730, 10, 130, 340)
    guy[6] = (870, 10, 170, 340)

    # Variable que controla qué imagen de Guy se muestra
    cual = 0

    # Controlando el tiempo
    cuanto = 100




 PÁGINA 15 DE 23
                            
             DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
    
                       CURSO: 1º BACHILLERATO




    tiempo = 0

    # El bucle de eventos
    while True:
       for event in pygame.event.get():
           if event.type == QUIT:
               pygame.quit()
               sys.exit()
       # Modificar posición en función de la tecla pulsada
       teclasPulsadas = pygame.key.get_pressed()
       if teclasPulsadas[K_a]:
           pos = pos - 1
       elif teclasPulsadas[K_s]:
           pos = pos + 1
           if pygame.time.get_ticks()-tiempo > cuanto:
               tiempo = pygame.time.get_ticks()
               cual = cual + 1
               if cual == 3 or cual == 6:
                  pos = pos + 5
               if cual > 6:
                  cual = 1
       else:
           cual = 0

       # Dibujar el fondo de color
       visor.fill((233,233,233))

       # Dibujar a Guy
       visor.blit(fotogramas, (pos,100), guy[cual])

       # Volcar la surface en la ventana de pygame
       pygame.display.update()




Lo primero es implementar la imagen de Guy parado. Ésa es precisamente la imagen 0 de
nuestro diccionario. Así que cuando no se pulse ninguna tecla, tenemos que indicar que sea
ésta y no otra la imagen que se dibuje cuando toque. Para ello, lo más sencillo es modificar
los if que miran que tecla se ha pulsado en uno solo:


   if teclasPulsadas[K_a]:
       ...
   elif teclasPulsadas[K_s]:
       ...
   else:
       cual = 0




 PÁGINA 16 DE 23
                             
             DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
    
                       CURSO: 1º BACHILLERATO

Con una estructura de esta forma, se mira si se ha pulsado la tecla a, en caso contrario se
mira si se ha pulsado la tecla s y si no se ha pulsado ninguna de las dos es cuando se
pone la variable cual a 0 para indicar que se dibujará la imagen de Guy quieto.
Lo siguiente es ajustar el desplazamiento con imágenes de diferentes tamaños. Vamos a
hacerlo de manera sencilla, simplemente dando más desplazamiento en la posición cuando
toca una de los fotogramas más anchos:

        if cual == 3 or cual == 6:
            pos = pos + 5


Como habrás notado, los fotogramas que en la imagen del sprite aparecen con las piernas
abiertas son la 3 y la 6 (recuerda que la primera es la 0). La cantidad que añadamos a la
variable pos dependerá del tamaño de la imagen y de cómo nos quede la animación al
probarla.




 PÁGINA 17 DE 23
                             
             DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
     
                       CURSO: 1º BACHILLERATO


guy07.py
Llegamos al último paso. ¿Qué nos queda? El movimiento hacia la derecha está
conseguido. Pero si pulsamos la tecla a para mover a Guy hacia la izquierda, veremos que
éste se desliza. ¡Claro! No hemos implementado el movimiento en esa dirección. Además lo
ideal sería tener otro sprite con los fotogramas del movimiento en la otra dirección, pero
este no es nuestro caso... ¿Qué podemos hacer?
El código fuente de nuestra versión definitiva será el siguiente:


    # -*- coding: utf-8 -*-

    # Séptimo y último ejemplo. Implementamos la animación
    # en sentido contrario.

    import pygame, sys
    from pygame.locals import *
    import time

    # Inicializar pygame
    pygame.init()

    # Crear la surface
    visor = pygame.display.set_mode((600, 600), 0, 32)

    # Poner el título de la ventana
    pygame.display.set_caption('Guy')

    # Variable que controla la posición de Guy
    pos = 0

    # Cargar la imagen de Guy y su reflejo
    fotogramas = pygame.image.load('sprites.jpg').convert()
    fotogramas2 = pygame.transform.flip(fotogramas,True, False)

    # Almacenamos las diferentes imágenes en un diccionario
    guy = {}
    guy2 = {}
    guy[0] = (0, 10, 120, 340)
    guy2[0]= (941, 10, 120, 340)
    guy[1] = (130, 10, 120, 340)
    guy2[1]= (811, 10, 120, 340)
    guy[2] = (260, 10, 130, 340)
    guy2[2]= (671, 10, 130, 340)
    guy[3] = (405, 10, 170, 340)
    guy2[3]= (486, 10, 170, 340)
    guy[4] = (600, 10, 120, 340)
    guy2[4]= (341, 10, 120, 340)
    guy[5] = (730, 10, 130, 340)




 PÁGINA 18 DE 23
                              
             DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
   
                         CURSO: 1º BACHILLERATO



   guy2[5]= (201, 10, 130, 340)
   guy[6] = (870, 10, 170, 340)
   guy2[6]= (21, 10, 170, 340)

   # Controlando la dirección
   izquierda = True

   # Variable que controla qué imagen de Guy se muestra
   cual = 0

   # Controlando el tiempo
   cuanto = 100
   tiempo = 0

   # Función que actualiza el fotograma
   def actualizar():
      global cual, pos, tiempo
      if izquierda:
          pos = pos + 1
      else:
          pos = pos - 1
      if pygame.time.get_ticks()-tiempo > cuanto:
          tiempo = pygame.time.get_ticks()
          cual = cual + 1
          if izquierda:
              if cual == 3 or cual == 6:
                 pos = pos + 5
              if cual > 6:
                 cual = 1
          else:
              if cual == 3 or cual == 6:
                 pos = pos - 5
              if cual > 6:
                 cual = 1

   # El bucle de eventos
   while True:
      for event in pygame.event.get():
          if event.type == QUIT:
              pygame.quit()
              sys.exit()
      # Modificar dirección en función de la tecla pulsada
      teclasPulsadas = pygame.key.get_pressed()
      if teclasPulsadas[K_a]:
          izquierda = False
          actualizar()
      elif teclasPulsadas[K_s]:
          izquierda = True
          actualizar()




PÁGINA 19 DE 23
                            
               DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
   
                        CURSO: 1º BACHILLERATO



       else:
          cual = 0

       # Dibujar el fondo de color
       visor.fill((233,233,233))

       # Dibujar a Guy
       if izquierda:
           visor.blit(fotogramas, (pos,100), guy[cual])
       else:
           visor.blit(fotogramas2, (pos,100), guy2[cual])

       # Volcar la surface en la ventana de pygame
       pygame.display.update()




En primer lugar necesitamos la imagen de los fotogramas del movimiento inverso al que
hemos tratado. Es cierto, no la tenemos, pero PyGame es estupendo y dispone de una
función que hace el trabajo por nosotros:

fotogramas2 = pygame.transform.flip(fotogramas,True, False)

La función pygame.transform.flip() toma como primer argumento una imagen y nos
devuelve una nueva imagen invertida respecto a la anterior. La forma de invertirla depende
de los dos argumentos siguientes. Si el primero de ellos es True intercambia izquierda y
derecha (es decir, una reflexión respecto al eje vertical); si el segundo es True, hace
lo propio con arriba y abajo (reflexión con respecto al eje horizontal). En nuestro
caso sólo queremos lo primero y de ahí que pasemos True y False. (Podíamos haber
cogido un programa de dibujo o de retoque y haber invertido la imagen, es cierto, pero al
hacerlo así hemos aprendido una nueva técnica que a veces es útil).
Lo siguiente es almacenar también las imágenes del nuevo sprite. Un nuevo diccionario
viene a realizar la tarea:

guy = {}
guy2 = {}
guy[0] = (0, 10, 120, 340)
guy2[0]= (941, 10, 120, 340)
guy[1] = (130, 10, 120, 340)
guy2[1]= (811, 10, 120, 340)
guy[2] = (260, 10, 130, 340)
guy2[2]= (671, 10, 130, 340)
guy[3] = (405, 10, 170, 340)
guy2[3]= (486, 10, 170, 340)
guy[4] = (600, 10, 120, 340)
guy2[4]= (341, 10, 120, 340)
guy[5] = (730, 10, 130, 340)
guy2[5]= (201, 10, 130, 340)
guy[6] = (870, 10, 170, 340)
guy2[6]= (21, 10, 170, 340)



 PÁGINA 20 DE 23
                            
              DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
    
                      CURSO: 1º BACHILLERATO

guy contiene los fotogramas del movimiento hacia la derecha y guy2 los de la izquierda.
Los valores concretos que hay que poner, como antes, o los miramos con un programa de
dibujo/retoque o hacemos algo de algebra teniendo encuenta el tamaño de la imagen y que
los segundos son un reflejo de los primeros.
Necesitamos también saber cual de los dos movimientos hay que dibujar, es decir, saber
hacia dónde nos estamos moviendo:

izquierda = True

La variable booleana izquierda indica, si es True (como ocurre al principio de la
ejecución del programa), que el movimiento es hacia la izquierda y si es False hacia la
derecha. Esto es importante, pues sólo tendremos que modificar el valor de esta variable
en el lugar apropiado de nuestro código para indicar qué imagen dibujar, siempre que
modifiquemos la parte en la que dibujamos a nuestro protagonista a esto:

   if izquierda:
       visor.blit(fotogramas, (pos,100), guy[cual])
   else:
       visor.blit(fotogramas2, (pos,100), guy2[cual])

¿Entiendes la idea? Con un bloque if miramos el valor de la variable izquierda; cuando sea
True dibujará un fotograma de guy y cuando sea False de guy2.
Pasemos a seleccionar exactamente de qué fotograma se trata. Fíjate que hay que hacer
prácticamente lo mismo en las dos direcciones, así que ¿por qué no definir una función
que lo haga y así no repetimos el código? Llamemos a esa función actualizar(), ya que
actualiza el dibujo de nuestro personaje. La parte que indica que hemos pulsado una tecla y
hay que cambiar el dibujo quedará ahora así:

   if teclasPulsadas[K_a]:
       izquierda = False
       actualizar()
   elif teclasPulsadas[K_s]:
       izquierda = True
       actualizar()
   else:
       cual = 0


Observa que si no se ha pulsado ninguna tecla, cual se pone a 0 y, más adelante, gracias a
nuestra modificación anterior, el programa dibujará el fotograma de parado correcta (hay
dos distintas, una con Guy parado mirando hacia la derecha y otra mirando hacia la
izquierda).
Respecto al movimiento, si se ha pulsado la tecla a sabemos que hay que mover a Guy
hacia la derecha, así que izquierda se pone a False y se llama a nuestra función
actualizar() para que cambie el dibujo. Si se ha pulsado la tecla s, por su parte, el
movimiento es hacia la izquierda, el valor correcto de la variable izquierda es ahora True
y se llama de nuevo a nuestra función.
Es el momento de abordar la implementación de la función actualizar(). Su código será
el siguiente:

 PÁGINA 21 DE 23
                             
            DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
   
                       CURSO: 1º BACHILLERATO


def actualizar():
  global cual, pos, tiempo
  if izquierda:
      pos = pos + 1
  else:
      pos = pos - 1
  if pygame.time.get_ticks()-tiempo > cuanto:
      tiempo = pygame.time.get_ticks()
      cual = cual + 1
      if izquierda:
          if cual == 3 or cual == 6:
              pos = pos + 5
          if cual > 6:
              cual = 1
      else:
          if cual == 3 or cual == 6:
              pos = pos - 5
          if cual > 6:
              cual = 1


Un matiz no muy elegante y que cambiará por completo cuando veamos como trabaja de
forma nativa PyGame con los sprites y la orientación a objetos, es la gestión de las
variables externas a la función. Una función puede usar sus propias variables,
definidas en su interior y también usar el valor de las variables que se han definido fuera
de ella. Hasta aquí todo correcto. Pero en cuanto queremos cambiar el valor de una de
estas últimas variables externas obtendremos un grosero error; Python protege las
externas y piensa que son internas y, como no están definidas, la cosa no funciona. Para
solucionarlo, existe la instrucción global. Las variables que pongamos a continuación de
dicha instrucción se declaran como externas y Python nos permite modificarlas dentro
del cuerpo de la función. En nuestro caso, vamos a modificar las variables cual, pos y
tiempo.
Lo siguiente que hay que hacer dentro de la función es modificar la posición de Guy. Aquí
no hace falta que miremos si se ha pulsado el teclado, puesto que ya se ha hecho y se ha
puesto la información en la variable izquierda. Basta poner, como vemos más arriba

   if izquierda:
       pos = pos + 1
   else:
       pos = pos - 1

(¿Ves como modificamos la variable externa pos? De ahí el global al comienzo de la
función).
El resto también es similar a la versión anterior del programa, con las modificaciones
correspondientes a las dos direcciones posibles. Simplemente miramos el valor de la
variable izquierda y actuamos en consecuencia sumando o restando y cambiando el valor
de la variable cual. Por supuesto, el código puede mejorarse, es algo redundante, pero
para nuestros efectos, es suficiente:




 PÁGINA 22 DE 23
                            
             DURACIÓN: PERÍODOS DE DOS CLASES
ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME
   
                     CURSO: 1º BACHILLERATO


  if pygame.time.get_ticks()-tiempo > cuanto:
     tiempo = pygame.time.get_ticks()
     cual = cual + 1
     if izquierda:
         if cual == 3 or cual == 6:
             pos = pos + 5
         if cual > 6:
             cual = 1
     else:
         if cual == 3 or cual == 6:
             pos = pos - 5
         if cual > 6:
             cual = 1


Con todos estos cambios, la animación funciona aceptablemente en las dos direcciones,
como podemos comprobar si ejecutamos el programa.




 PÁGINA 23 DE 23
                            
           DURACIÓN: PERÍODOS DE DOS CLASES

More Related Content

Viewers also liked

Programación con Pygame (II)
Programación con Pygame (II)Programación con Pygame (II)
Programación con Pygame (II)Fernando Salamero
 
Taller de Pilas Engine, un motor de juegos en Python - PyConES 2014
Taller de Pilas Engine, un motor de juegos en Python - PyConES 2014Taller de Pilas Engine, un motor de juegos en Python - PyConES 2014
Taller de Pilas Engine, un motor de juegos en Python - PyConES 2014Fernando Salamero
 
(Sin anotaciones) - En busca de la Física
(Sin anotaciones) - En busca de la Física(Sin anotaciones) - En busca de la Física
(Sin anotaciones) - En busca de la FísicaFernando Salamero
 
Programación de Videojuegos con Python y Pilas (III)
Programación de Videojuegos con Python y Pilas (III)Programación de Videojuegos con Python y Pilas (III)
Programación de Videojuegos con Python y Pilas (III)Fernando Salamero
 
Curso Programacion de Juego Introducion IA
Curso Programacion de Juego Introducion IACurso Programacion de Juego Introducion IA
Curso Programacion de Juego Introducion IARicardo Daniel Quiroga
 
Programación de Videojuegos con Python y Pilas (I)
Programación de Videojuegos con Python y Pilas (I)Programación de Videojuegos con Python y Pilas (I)
Programación de Videojuegos con Python y Pilas (I)Fernando Salamero
 
Programación de Videojuegos con Python y Pilas (V)
Programación de Videojuegos con Python y Pilas (V)Programación de Videojuegos con Python y Pilas (V)
Programación de Videojuegos con Python y Pilas (V)Fernando Salamero
 
Programación de Videojuegos con Python y Pilas (II)
Programación de Videojuegos con Python y Pilas (II)Programación de Videojuegos con Python y Pilas (II)
Programación de Videojuegos con Python y Pilas (II)Fernando Salamero
 
Programación de Videojuegos con Python y Pilas (VI)
Programación de Videojuegos con Python y Pilas (VI)Programación de Videojuegos con Python y Pilas (VI)
Programación de Videojuegos con Python y Pilas (VI)Fernando Salamero
 

Viewers also liked (19)

Programación con Pygame (II)
Programación con Pygame (II)Programación con Pygame (II)
Programación con Pygame (II)
 
Programación con Pygame I
Programación con Pygame IProgramación con Pygame I
Programación con Pygame I
 
Programación con Pygame IX
Programación con Pygame IXProgramación con Pygame IX
Programación con Pygame IX
 
Programación con Pygame IV
Programación con Pygame IVProgramación con Pygame IV
Programación con Pygame IV
 
Python básico II
Python básico IIPython básico II
Python básico II
 
Intro Pygame Capitulo 6
Intro Pygame Capitulo 6Intro Pygame Capitulo 6
Intro Pygame Capitulo 6
 
Pythonic Math
Pythonic MathPythonic Math
Pythonic Math
 
Intro PyGame Capitulo 0
Intro PyGame Capitulo 0Intro PyGame Capitulo 0
Intro PyGame Capitulo 0
 
Intro PyGame Capitulo 1
Intro PyGame Capitulo 1Intro PyGame Capitulo 1
Intro PyGame Capitulo 1
 
Taller de Pilas Engine, un motor de juegos en Python - PyConES 2014
Taller de Pilas Engine, un motor de juegos en Python - PyConES 2014Taller de Pilas Engine, un motor de juegos en Python - PyConES 2014
Taller de Pilas Engine, un motor de juegos en Python - PyConES 2014
 
(Sin anotaciones) - En busca de la Física
(Sin anotaciones) - En busca de la Física(Sin anotaciones) - En busca de la Física
(Sin anotaciones) - En busca de la Física
 
Programación de Videojuegos con Python y Pilas (III)
Programación de Videojuegos con Python y Pilas (III)Programación de Videojuegos con Python y Pilas (III)
Programación de Videojuegos con Python y Pilas (III)
 
Curso Programacion de Juego Introducion IA
Curso Programacion de Juego Introducion IACurso Programacion de Juego Introducion IA
Curso Programacion de Juego Introducion IA
 
Programación de Videojuegos con Python y Pilas (I)
Programación de Videojuegos con Python y Pilas (I)Programación de Videojuegos con Python y Pilas (I)
Programación de Videojuegos con Python y Pilas (I)
 
Programación de Videojuegos con Python y Pilas (V)
Programación de Videojuegos con Python y Pilas (V)Programación de Videojuegos con Python y Pilas (V)
Programación de Videojuegos con Python y Pilas (V)
 
Intro PyGame Capitulo 5
Intro PyGame Capitulo 5Intro PyGame Capitulo 5
Intro PyGame Capitulo 5
 
Programación de Videojuegos con Python y Pilas (II)
Programación de Videojuegos con Python y Pilas (II)Programación de Videojuegos con Python y Pilas (II)
Programación de Videojuegos con Python y Pilas (II)
 
Python (práctica 1)
Python (práctica 1)Python (práctica 1)
Python (práctica 1)
 
Programación de Videojuegos con Python y Pilas (VI)
Programación de Videojuegos con Python y Pilas (VI)Programación de Videojuegos con Python y Pilas (VI)
Programación de Videojuegos con Python y Pilas (VI)
 

Similar to Programación con Pygame III

Xna game studio presentación 02
Xna game studio   presentación 02Xna game studio   presentación 02
Xna game studio presentación 02Juan Cardona
 
Programación de Videojuegos con Python y Pilas (VII)
Programación de Videojuegos con Python y Pilas (VII)Programación de Videojuegos con Python y Pilas (VII)
Programación de Videojuegos con Python y Pilas (VII)Fernando Salamero
 
Programación de Videojuegos con Python y Pilas (IX)
Programación de Videojuegos con Python y Pilas (IX)Programación de Videojuegos con Python y Pilas (IX)
Programación de Videojuegos con Python y Pilas (IX)Fernando Salamero
 
Programación con Pygame VIII
Programación con Pygame VIIIProgramación con Pygame VIII
Programación con Pygame VIIIFernando Salamero
 
Explicacion de pygame para python de la UTN de Argentina
Explicacion de pygame para python de la UTN de ArgentinaExplicacion de pygame para python de la UTN de Argentina
Explicacion de pygame para python de la UTN de Argentinaalvarogabrielmedici
 
Programación de Videojuegos con Python y Pilas (VIII)
Programación de Videojuegos con Python y Pilas (VIII)Programación de Videojuegos con Python y Pilas (VIII)
Programación de Videojuegos con Python y Pilas (VIII)Fernando Salamero
 
Programación de Videojuegos con Python y Pilas (X)
Programación de Videojuegos con Python y Pilas (X)Programación de Videojuegos con Python y Pilas (X)
Programación de Videojuegos con Python y Pilas (X)Fernando Salamero
 
Xna game studio presentación 05
Xna game studio   presentación 05Xna game studio   presentación 05
Xna game studio presentación 05Juan Cardona
 
Como instalar Python y librerias
Como instalar Python y libreriasComo instalar Python y librerias
Como instalar Python y libreriasDaniel Iba
 
Utp 2015-2_pdi_lab2
 Utp 2015-2_pdi_lab2 Utp 2015-2_pdi_lab2
Utp 2015-2_pdi_lab2jcbp_peru
 
66 Php. Encuadre Y Redimensionado De Imagenes
66 Php. Encuadre Y Redimensionado De Imagenes66 Php. Encuadre Y Redimensionado De Imagenes
66 Php. Encuadre Y Redimensionado De ImagenesJosé M. Padilla
 

Similar to Programación con Pygame III (20)

Intro pygamev2
Intro pygamev2Intro pygamev2
Intro pygamev2
 
Xna game studio presentación 02
Xna game studio   presentación 02Xna game studio   presentación 02
Xna game studio presentación 02
 
Programación de Videojuegos con Python y Pilas (VII)
Programación de Videojuegos con Python y Pilas (VII)Programación de Videojuegos con Python y Pilas (VII)
Programación de Videojuegos con Python y Pilas (VII)
 
Programación de Videojuegos con Python y Pilas (IX)
Programación de Videojuegos con Python y Pilas (IX)Programación de Videojuegos con Python y Pilas (IX)
Programación de Videojuegos con Python y Pilas (IX)
 
Programación con Pygame VI
Programación con Pygame VIProgramación con Pygame VI
Programación con Pygame VI
 
Programación con Pygame VIII
Programación con Pygame VIIIProgramación con Pygame VIII
Programación con Pygame VIII
 
Explicacion de pygame para python de la UTN de Argentina
Explicacion de pygame para python de la UTN de ArgentinaExplicacion de pygame para python de la UTN de Argentina
Explicacion de pygame para python de la UTN de Argentina
 
Programación con Pygame V
Programación con Pygame VProgramación con Pygame V
Programación con Pygame V
 
Programación de Videojuegos con Python y Pilas (VIII)
Programación de Videojuegos con Python y Pilas (VIII)Programación de Videojuegos con Python y Pilas (VIII)
Programación de Videojuegos con Python y Pilas (VIII)
 
Programación de Videojuegos con Python y Pilas (X)
Programación de Videojuegos con Python y Pilas (X)Programación de Videojuegos con Python y Pilas (X)
Programación de Videojuegos con Python y Pilas (X)
 
Xna game studio presentación 05
Xna game studio   presentación 05Xna game studio   presentación 05
Xna game studio presentación 05
 
Como instalar Python y librerias
Como instalar Python y libreriasComo instalar Python y librerias
Como instalar Python y librerias
 
Presentacion420
Presentacion420Presentacion420
Presentacion420
 
Presentacion420
Presentacion420Presentacion420
Presentacion420
 
Lab2-POO
Lab2-POOLab2-POO
Lab2-POO
 
Utp 2015-2_pdi_lab2
 Utp 2015-2_pdi_lab2 Utp 2015-2_pdi_lab2
Utp 2015-2_pdi_lab2
 
Adobe flash-cs5
Adobe flash-cs5Adobe flash-cs5
Adobe flash-cs5
 
Entorno visual p2
Entorno visual p2Entorno visual p2
Entorno visual p2
 
66 Php. Encuadre Y Redimensionado De Imagenes
66 Php. Encuadre Y Redimensionado De Imagenes66 Php. Encuadre Y Redimensionado De Imagenes
66 Php. Encuadre Y Redimensionado De Imagenes
 
Intro Pygame Capitulo 2
Intro Pygame Capitulo 2Intro Pygame Capitulo 2
Intro Pygame Capitulo 2
 

More from Fernando Salamero

More from Fernando Salamero (13)

(Anotaciones) Ciencia (Cuestiones) que la tiza no propone
(Anotaciones) Ciencia (Cuestiones) que la tiza no propone(Anotaciones) Ciencia (Cuestiones) que la tiza no propone
(Anotaciones) Ciencia (Cuestiones) que la tiza no propone
 
Ciencia (Cuestiones) que la tiza no propone
Ciencia (Cuestiones) que la tiza no proponeCiencia (Cuestiones) que la tiza no propone
Ciencia (Cuestiones) que la tiza no propone
 
(Con anotaciones) En busca de la Física
(Con anotaciones) En busca de la Física(Con anotaciones) En busca de la Física
(Con anotaciones) En busca de la Física
 
Timeline - En busca de la Física
Timeline - En busca de la FísicaTimeline - En busca de la Física
Timeline - En busca de la Física
 
Jovenes físicos
Jovenes físicosJovenes físicos
Jovenes físicos
 
Python básico I
Python básico IPython básico I
Python básico I
 
Python (ejercicios)
Python (ejercicios)Python (ejercicios)
Python (ejercicios)
 
Python (práctica 4)
Python (práctica 4)Python (práctica 4)
Python (práctica 4)
 
Python (práctica 3)
Python (práctica 3)Python (práctica 3)
Python (práctica 3)
 
Python (práctica 2)
Python (práctica 2)Python (práctica 2)
Python (práctica 2)
 
Iniciación a python
Iniciación a pythonIniciación a python
Iniciación a python
 
Programación con Pygame VII
Programación con Pygame VIIProgramación con Pygame VII
Programación con Pygame VII
 
Aventura
AventuraAventura
Aventura
 

Recently uploaded

c3.hu3.p1.p2.El ser humano y el sentido de su existencia.pptx
c3.hu3.p1.p2.El ser humano y el sentido de su existencia.pptxc3.hu3.p1.p2.El ser humano y el sentido de su existencia.pptx
c3.hu3.p1.p2.El ser humano y el sentido de su existencia.pptxMartín Ramírez
 
Día de la Madre Tierra-1.pdf día mundial
Día de la Madre Tierra-1.pdf día mundialDía de la Madre Tierra-1.pdf día mundial
Día de la Madre Tierra-1.pdf día mundialpatriciaines1993
 
libro para colorear de Peppa pig, ideal para educación inicial
libro para colorear de Peppa pig, ideal para educación iniciallibro para colorear de Peppa pig, ideal para educación inicial
libro para colorear de Peppa pig, ideal para educación inicialLorenaSanchez350426
 
PPT_Formación integral y educación CRESE (1).pdf
PPT_Formación integral y educación CRESE (1).pdfPPT_Formación integral y educación CRESE (1).pdf
PPT_Formación integral y educación CRESE (1).pdfEDILIAGAMBOA
 
Uses of simple past and time expressions
Uses of simple past and time expressionsUses of simple past and time expressions
Uses of simple past and time expressionsConsueloSantana3
 
PROGRAMACION ANUAL DE MATEMATICA 2024.docx
PROGRAMACION ANUAL DE MATEMATICA 2024.docxPROGRAMACION ANUAL DE MATEMATICA 2024.docx
PROGRAMACION ANUAL DE MATEMATICA 2024.docxEribertoPerezRamirez
 
PLANIFICACION ANUAL 2024 - INICIAL UNIDOCENTE.docx
PLANIFICACION ANUAL 2024 - INICIAL UNIDOCENTE.docxPLANIFICACION ANUAL 2024 - INICIAL UNIDOCENTE.docx
PLANIFICACION ANUAL 2024 - INICIAL UNIDOCENTE.docxJUANSIMONPACHIN
 
Fundamentos y Principios de Psicopedagogía..pdf
Fundamentos y Principios de Psicopedagogía..pdfFundamentos y Principios de Psicopedagogía..pdf
Fundamentos y Principios de Psicopedagogía..pdfsamyarrocha1
 
PPT GESTIÓN ESCOLAR 2024 Comités y Compromisos.pptx
PPT GESTIÓN ESCOLAR 2024 Comités y Compromisos.pptxPPT GESTIÓN ESCOLAR 2024 Comités y Compromisos.pptx
PPT GESTIÓN ESCOLAR 2024 Comités y Compromisos.pptxOscarEduardoSanchezC
 
Fisiologia.Articular. 3 Kapandji.6a.Ed.pdf
Fisiologia.Articular. 3 Kapandji.6a.Ed.pdfFisiologia.Articular. 3 Kapandji.6a.Ed.pdf
Fisiologia.Articular. 3 Kapandji.6a.Ed.pdfcoloncopias5
 
Metabolismo 3: Anabolismo y Fotosíntesis 2024
Metabolismo 3: Anabolismo y Fotosíntesis 2024Metabolismo 3: Anabolismo y Fotosíntesis 2024
Metabolismo 3: Anabolismo y Fotosíntesis 2024IES Vicent Andres Estelles
 
Tarea 5_ Foro _Selección de herramientas digitales_Manuel.pdf
Tarea 5_ Foro _Selección de herramientas digitales_Manuel.pdfTarea 5_ Foro _Selección de herramientas digitales_Manuel.pdf
Tarea 5_ Foro _Selección de herramientas digitales_Manuel.pdfManuel Molina
 
Estas son las escuelas y colegios que tendrán modalidad no presencial este lu...
Estas son las escuelas y colegios que tendrán modalidad no presencial este lu...Estas son las escuelas y colegios que tendrán modalidad no presencial este lu...
Estas son las escuelas y colegios que tendrán modalidad no presencial este lu...fcastellanos3
 
LA OVEJITA QUE VINO A CENAR CUENTO INFANTIL.pdf
LA OVEJITA QUE VINO A CENAR CUENTO INFANTIL.pdfLA OVEJITA QUE VINO A CENAR CUENTO INFANTIL.pdf
LA OVEJITA QUE VINO A CENAR CUENTO INFANTIL.pdfNataliaMalky1
 
La Función tecnológica del tutor.pptx
La  Función  tecnológica  del tutor.pptxLa  Función  tecnológica  del tutor.pptx
La Función tecnológica del tutor.pptxJunkotantik
 

Recently uploaded (20)

c3.hu3.p1.p2.El ser humano y el sentido de su existencia.pptx
c3.hu3.p1.p2.El ser humano y el sentido de su existencia.pptxc3.hu3.p1.p2.El ser humano y el sentido de su existencia.pptx
c3.hu3.p1.p2.El ser humano y el sentido de su existencia.pptx
 
Día de la Madre Tierra-1.pdf día mundial
Día de la Madre Tierra-1.pdf día mundialDía de la Madre Tierra-1.pdf día mundial
Día de la Madre Tierra-1.pdf día mundial
 
libro para colorear de Peppa pig, ideal para educación inicial
libro para colorear de Peppa pig, ideal para educación iniciallibro para colorear de Peppa pig, ideal para educación inicial
libro para colorear de Peppa pig, ideal para educación inicial
 
Sesión La luz brilla en la oscuridad.pdf
Sesión  La luz brilla en la oscuridad.pdfSesión  La luz brilla en la oscuridad.pdf
Sesión La luz brilla en la oscuridad.pdf
 
PPT_Formación integral y educación CRESE (1).pdf
PPT_Formación integral y educación CRESE (1).pdfPPT_Formación integral y educación CRESE (1).pdf
PPT_Formación integral y educación CRESE (1).pdf
 
Uses of simple past and time expressions
Uses of simple past and time expressionsUses of simple past and time expressions
Uses of simple past and time expressions
 
PROGRAMACION ANUAL DE MATEMATICA 2024.docx
PROGRAMACION ANUAL DE MATEMATICA 2024.docxPROGRAMACION ANUAL DE MATEMATICA 2024.docx
PROGRAMACION ANUAL DE MATEMATICA 2024.docx
 
DIA INTERNACIONAL DAS FLORESTAS .
DIA INTERNACIONAL DAS FLORESTAS         .DIA INTERNACIONAL DAS FLORESTAS         .
DIA INTERNACIONAL DAS FLORESTAS .
 
PLANIFICACION ANUAL 2024 - INICIAL UNIDOCENTE.docx
PLANIFICACION ANUAL 2024 - INICIAL UNIDOCENTE.docxPLANIFICACION ANUAL 2024 - INICIAL UNIDOCENTE.docx
PLANIFICACION ANUAL 2024 - INICIAL UNIDOCENTE.docx
 
Fundamentos y Principios de Psicopedagogía..pdf
Fundamentos y Principios de Psicopedagogía..pdfFundamentos y Principios de Psicopedagogía..pdf
Fundamentos y Principios de Psicopedagogía..pdf
 
PPT GESTIÓN ESCOLAR 2024 Comités y Compromisos.pptx
PPT GESTIÓN ESCOLAR 2024 Comités y Compromisos.pptxPPT GESTIÓN ESCOLAR 2024 Comités y Compromisos.pptx
PPT GESTIÓN ESCOLAR 2024 Comités y Compromisos.pptx
 
Fisiologia.Articular. 3 Kapandji.6a.Ed.pdf
Fisiologia.Articular. 3 Kapandji.6a.Ed.pdfFisiologia.Articular. 3 Kapandji.6a.Ed.pdf
Fisiologia.Articular. 3 Kapandji.6a.Ed.pdf
 
Tema 7.- E-COMMERCE SISTEMAS DE INFORMACION.pdf
Tema 7.- E-COMMERCE SISTEMAS DE INFORMACION.pdfTema 7.- E-COMMERCE SISTEMAS DE INFORMACION.pdf
Tema 7.- E-COMMERCE SISTEMAS DE INFORMACION.pdf
 
Aedes aegypti + Intro to Coquies EE.pptx
Aedes aegypti + Intro to Coquies EE.pptxAedes aegypti + Intro to Coquies EE.pptx
Aedes aegypti + Intro to Coquies EE.pptx
 
Metabolismo 3: Anabolismo y Fotosíntesis 2024
Metabolismo 3: Anabolismo y Fotosíntesis 2024Metabolismo 3: Anabolismo y Fotosíntesis 2024
Metabolismo 3: Anabolismo y Fotosíntesis 2024
 
TL/CNL – 2.ª FASE .
TL/CNL – 2.ª FASE                       .TL/CNL – 2.ª FASE                       .
TL/CNL – 2.ª FASE .
 
Tarea 5_ Foro _Selección de herramientas digitales_Manuel.pdf
Tarea 5_ Foro _Selección de herramientas digitales_Manuel.pdfTarea 5_ Foro _Selección de herramientas digitales_Manuel.pdf
Tarea 5_ Foro _Selección de herramientas digitales_Manuel.pdf
 
Estas son las escuelas y colegios que tendrán modalidad no presencial este lu...
Estas son las escuelas y colegios que tendrán modalidad no presencial este lu...Estas son las escuelas y colegios que tendrán modalidad no presencial este lu...
Estas son las escuelas y colegios que tendrán modalidad no presencial este lu...
 
LA OVEJITA QUE VINO A CENAR CUENTO INFANTIL.pdf
LA OVEJITA QUE VINO A CENAR CUENTO INFANTIL.pdfLA OVEJITA QUE VINO A CENAR CUENTO INFANTIL.pdf
LA OVEJITA QUE VINO A CENAR CUENTO INFANTIL.pdf
 
La Función tecnológica del tutor.pptx
La  Función  tecnológica  del tutor.pptxLa  Función  tecnológica  del tutor.pptx
La Función tecnológica del tutor.pptx
 

Programación con Pygame III

  • 1. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO Animaciones Realistas Guy se pone a andar La animación es algo más que volcar una imagen en pantalla y moverla por ella. En realidad, para que las animaciones parezcan realistas, necesitamos mucho más; necesitamos que la propia imagen varíe a medida que la desplazamos. Para ilustrar la forma de hacerlo, vamos a usar un personaje famoso; Guybrush Threepwood, el protagonista de la saga de videojuegos Monkey Island (por cierto, si no la conoces te la aconsejo, es una de las sagas más famosas y entretenidas de la historia de los videojuegos). Conseguiremos algunas imágenes de nuestro personaje por Internet y trabajaremos hasta que la animación sea aceptable (no perfecta, pues las imágenes disponibles son limitadas; en un juego real, el ilustrador que trabaja con el programador dibuja cada una de las posiciones y los movimientos para que produzca un movimiento suave) ¡Escribamos código! PÁGINA 1 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 2. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO guy01.py El primer paso es, partiendo de una imagen de nuestro personaje, cargarla en memoria y hacer que se desplace por la pantalla. Sería algo así: # -*- coding: utf-8 -*- # En este primer ejemplo, ponemos la imagen de Guy en pantalla, # desplazándolo con las teclas 'a' y 's'. import pygame, sys from pygame.locals import * # Inicializar pygame pygame.init() # Crear la surface visor = pygame.display.set_mode((600, 600), 0, 32) # Poner el título de la ventana pygame.display.set_caption('Guy') # Cargar la imagen del hombre guy = pygame.image.load('guy.jpg').convert() # Variable que controla la posición de Guy pos = 100 # El bucle de eventos while True: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() # Modificar posición en función de la tecla pulsada teclasPulsadas = pygame.key.get_pressed() if teclasPulsadas[K_a]: pos = pos - 1 if teclasPulsadas[K_s]: pos = pos + 1 # Dibujar el fondo de color visor.fill((233,233,233)) # Dibujar a Guy visor.blit(guy, (pos,100)) # Volcar la surface en la ventana de pygame pygame.display.update() PÁGINA 2 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 3. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO Ya conocemos las técnicas necesarias para entender el código anterior. Sabemos cargar imágenes en memoria, comprobar si se ha pulsado una determinada tecla y desplazar objetos por la pantalla modificando sus coordenadas. Lo único matizable es que usamos una imagen sin transparencias. Si tuviera un fondo transparente, se nos movería por la pantalla sin problemas. Como no es el caso, para disimularlo, hemos elegido un color de fondo para la ventana similar al de la propia imagen (hay otros métodos, se puede indicar a PyGame que use determinado color como color transparente, pero entonces nos hemos asegurar que el propio fondo de la imagen es exactamente de ese color y no varía ningún pixel que se notaría con el movimiento; éste, por desgracia, es nuestro caso). PÁGINA 3 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 4. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO guy02.py Lo anterior queda muy artificial. ¿Acaso alguien va por la calle completamente rígido y deslizándose? Si queremos animaciones realistas, necesitamos que la imagen del protagonista vaya cambiando a medida que va andando; pies juntos, avanza el pie derecho, lo apoya, hace lo propio con el pie izquierdo, etc. Hay varias maneras de hacer esto, pero todas pasan por cargar diferentes imágenes del personaje que queremos animar y dibujarlas en los momentos apropiados. Pero antes de ello, ¿cómo conseguimos esas imágenes y cómo disponemos de ellas? Tanto si eres un buen dibujante como si buscas por Internet tus recursos (libres), una forma típica de tener archivadas las diferentes imágenes es en un solo archivo de sprite. Para que te hagas una idea, éste es el que vamos a usar: Esta única imagen contiene todos los pasos intermedios que va a dar nuestro protagonista (de paso puedes ver cómo era en la versión original del juego y cómo quedó en la nueva versión). Un aviso; como este trabajo es sólo con intención pedagógica, la animación no va a quedar del todo bien. En realidad necesitaríamos más fotogramas del movimiento o gestionar mejor la posición de como lo vamos a hacer (fíjate que el tamaño que ocupa cada fotograma es distinto). En cualquier caso, para aprender la técnica nos bastará. El código que simplemente extrae uno de los fotogramas de la imagen anterior es el siguiente: PÁGINA 4 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 5. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO # -*- coding: utf-8 -*- # En este segundo ejemplo, ponemos la imagen de Guy cargándola # desde el archivo de sprites que contiene todas las imágenes. import pygame, sys from pygame.locals import * # Inicializar pygame pygame.init() # Crear la surface visor = pygame.display.set_mode((600, 600), 0, 32) # Poner el título de la ventana pygame.display.set_caption('Guy') # Cargar la imagen de Guy guy = pygame.image.load('sprites.jpg').convert() # Variable que controla la posición de Guy pos = 100 # Posición de la parte de la imagen que se visualiza x = 130 y = 10 w = 120 h = 340 # El bucle de eventos while True: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() # Modificar posición en función de la tecla pulsada teclasPulsadas = pygame.key.get_pressed() if teclasPulsadas[K_a]: pos = pos - 1 if teclasPulsadas[K_s]: pos = pos + 1 # Dibujar el fondo de color visor.fill((233,233,233)) # Dibujar a Guy visor.blit(guy, (pos,100), (x,y,w,h)) # Volcar la surface en la ventana de pygame pygame.display.update() PÁGINA 5 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 6. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO La primera modificación, obviamente, es que al archivo de imagen que hemos de cargar en memoria es distinto: guy = pygame.image.load('sprites.jpg').convert() En la variable guy, por tanto, se almacenan todos los fotogramas de la animación del personaje. Para indicar cuál es el fotograma que queremos usar, necesitamos indicárselo con las coordenadas de un rect de PyGame (con cualquier programa de dibujo o retoque, como GIMP, podemos ver cuáles son). x = 130 y = 10 w = 120 h = 340 El significado, aunque debiera ser evidente, lo tenemos en la siguiente imagen: x y h w El resto es simplemente usar la función blit para indicar que se quiere volcar en pantalla sólo esta parte de la imagen: visor.blit(guy, (pos,100), (x,y,w,h)) En efecto, la última tupla (x,y,w,h), como puede verse en el documento de referencia de PyGame, indica que sólo debe dibujarse parte de una imagen. PÁGINA 6 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 7. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO guy03.py Aunque en las dos versiones anteriores el resultado es el mismo, hemos visto que el código hace cosas muy distintas. En la primera versión se carga una imagen que se mueve por la pantalla. En la segunda, se carga otra imagen y se mueve por la pantalla parte de esta. El resultado de este tercer paso va a ser el mismo también, pero de camino habremos cargado en memoria todos los fotogramas que forman la animación del personaje aunque sólo mostremos una. Éste es el código: # -*- coding: utf-8 -*- # En este tercer ejemplo, cargamos todas las imágenes de Guy desde # el archivo de sprites aunque solo mostramos una. import pygame, sys from pygame.locals import * # Inicializar pygame pygame.init() # Crear la surface visor = pygame.display.set_mode((600, 600), 0, 32) # Poner el título de la ventana pygame.display.set_caption('Guy') # Cargar la imagen de Guy fotogramas = pygame.image.load('sprites.jpg').convert() # Variable que controla la posición de Guy pos = 100 # Almacenamos las diferentes imágenes en un diccionario guy = {} guy[0] = (0, 10, 120, 340) guy[1] = (130, 10, 120, 340) guy[2] = (260, 10, 120, 340) guy[3] = (405, 10, 140, 340) guy[4] = (600, 10, 120, 340) guy[5] = (730, 10, 130, 340) guy[6] = (870, 10, 170, 340) # El bucle de eventos while True: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() PÁGINA 7 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 8. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO # Modificar posición en función de la tecla pulsada teclasPulsadas = pygame.key.get_pressed() if teclasPulsadas[K_a]: pos = pos - 1 if teclasPulsadas[K_s]: pos = pos + 1 # Dibujar el fondo de color visor.fill((233,233,233)) # Dibujar una imagen del hombre visor.blit(fotogramas, (pos,100), guy[1]) # Volcar la surface en la ventana de pygame pygame.display.update() Para empezar, hemos cambiado el nombre de la variable que contiene a la imagen de sprites, pues ahora es simplemente una variable intermedia. fotogramas = pygame.image.load('sprites.jpg').convert() El nombre de guy lo reservamos para la variable que contendrá todos los fotogramas. ¿Qué tipo de variable usar? ¿Una lista? Lo más flexible es, quizá, usar un diccionario: guy = {} guy[0] = (0, 10, 120, 340) guy[1] = (130, 10, 120, 340) guy[2] = (260, 10, 120, 340) guy[3] = (405, 10, 140, 340) guy[4] = (600, 10, 120, 340) guy[5] = (730, 10, 130, 340) guy[6] = (870, 10, 170, 340) Las claves del diccionario son, simplemente, números enteros que indican el orden del fotograma. Para cada una de ellas, almacenamos un rect que indica la posición del fotograma en la imagen de sprites (lo que antes poníamos como x, y,w y h). Observa que, de nuevo, debemos usar un programa de dibujo o retoque para mirar cuáles son las coordenadas de cada una de esas imágenes. Finalmente, sólo dibujamos una de ellas con visor.blit(fotogramas, (pos,100), guy[1]) PÁGINA 8 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 9. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO guy04.py Tres versiones y Guy aún no da ningún paso... Por fin ha llegado el momento de cambiar esto. En esta versión vamos a conseguir que, al mismo tiempo que nuestro personaje avance, su imagen vaya cambiando. Éste es el código: # -*- coding: utf-8 -*- # Y en el cuarto ejemplo, mostramos una imagen de la animación # distinta en cada paso. import pygame, sys from pygame.locals import * # Inicializar pygame pygame.init() # Crear la surface visor = pygame.display.set_mode((600, 600), 0, 32) # Poner el título de la ventana pygame.display.set_caption('Guy') # Cargar la imagen de Guy fotogramas = pygame.image.load('sprites.jpg').convert() # Variable que controla la posición de Guy pos = 100 # Almacenamos las diferentes imágenes en un diccionario guy = {} guy[0] = (0, 10, 120, 340) guy[1] = (130, 10, 120, 340) guy[2] = (260, 10, 120, 340) guy[3] = (405, 10, 140, 340) guy[4] = (600, 10, 120, 340) guy[5] = (730, 10, 130, 340) guy[6] = (870, 10, 170, 340) # Variable que controla qué imagen del hombre se muestra cual = 0 # El bucle de eventos while True: for event in pygame.event.get(): PÁGINA 9 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 10. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO if event.type == QUIT: pygame.quit() sys.exit() # Modificar posición en función de la tecla pulsada teclasPulsadas = pygame.key.get_pressed() if teclasPulsadas[K_a]: pos = pos - 1 if teclasPulsadas[K_s]: pos = pos + 1 cual = cual + 1 if cual > 6: cual = 0 # Dibujar el fondo de color visor.fill((233,233,233)) # Dibujar a Guy visor.blit(fotogramas, (pos,100), guy[cual]) # Volcar la surface en la ventana de pygame pygame.display.update() Observa que si ejecutas este programa verás que las cosas no salen como uno desea, ya que la imagen cambia excesivamente rápido y no da tiempo a verla. Pero para arreglar esto tendremos que esperar a la próxima versión... Ahora de lo que se trata es de ver cómo cambiar la imagen en cada paso. Vamos a hacerlo, primero, en una sola dirección (pongamos que hacia la derecha). Como es fácil de imaginar, primero necesitamos una variable que almacene cuál es la imagen que toca dibujar en cada momento. De ello se encarga cual: cual = 0 Recuerda que las imágenes (en realidad, la indicación de qué parte de la imagen de sprites hay que dibujar) están almacenadas en el diccionario guy. Como cual vale inicialmente 0, la expresión guy[cual] será en realidad guy[0], es decir, el primer fotograma de la animación del movimiento de nuestro protagonista. Sin más que cambiar el valor de la variable cual, la expresión anterior nos daría otro fotograma. ¿Dónde hacer el cambio de imagen? Acertaste, allí donde se mire si se ha pulsado la tecla s, cuando hay que desplazarse a la derecha y se aumenta la coordenada pos: if teclasPulsadas[K_s]: pos = pos + 1 cual = cual + 1 if cual > 6: cual = 0 PÁGINA 10 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 11. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO Como puedes ver en el if anterior, si se ha pulsado la tecla s primero se aumenta la variable pos (recuerda que allí se almacena la coordenada x del personaje) y luego aumentamos la variable cual para indicar, cuando más adelante se llegue al momento de dibujar, que hay que cambiar el fotograma de la animación. Hay que tener cuidado con el número de fotograma indicado. Fíjate que tenemos 7 imágenes para simular el movimiento, indicadas con las claves 0, 1, 2, 3, 4, 5 y 6. Eso quiere decir que, al aumentar la variable cual no nos debemos pasar de 6. De allí que se compruebe con un if y, en tal caso, la variable cual se ponga de nuevo a 0. Como hemos indicado antes, no todo es tan bonito como parece. Visto en movimiento, ¡Guy parece mover los pies a toda velocidad como alma que lleva el diablo! Hmmm... PÁGINA 11 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 12. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO guy05.py El problema que tenemos en la versión anterior de nuestra animación es que no controlamos la velocidad de ésta, con lo que en cada fotograma se cambia el dibujo de nuestro personaje; si el programa se ejecuta a 60 fotogramas por segundo, por ejemplo, Guy cambia de aspecto 60 veces cada segundo y de ahí la locura del movimiento de sus piernas... La manera de solucionarlo será ésta: # -*- coding: utf-8 -*- # Quinto ejemplo, controlamos la velocidad de la animación. import pygame, sys from pygame.locals import * import time # Inicializar pygame pygame.init() # Crear la surface visor = pygame.display.set_mode((600, 600), 0, 32) # Poner el título de la ventana pygame.display.set_caption('Guy') # Cargar la imagen de Guy fotogramas = pygame.image.load('sprites.jpg').convert() # Variable que controla la posición de Guy pos = 0 # Almacenamos las diferentes imágenes en un diccionario guy = {} guy[0] = (0, 10, 120, 340) guy[1] = (130, 10, 120, 340) guy[2] = (260, 10, 130, 340) guy[3] = (405, 10, 170, 340) guy[4] = (600, 10, 120, 340) guy[5] = (730, 10, 130, 340) guy[6] = (870, 10, 170, 340) # Variable que controla qué imagen de Guy se muestra cual = 0 # Controlando el tiempo cuanto = 100 tiempo = 0 PÁGINA 12 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 13. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO # El bucle de eventos while True: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() # Modificar posición en función de la tecla pulsada teclasPulsadas = pygame.key.get_pressed() if teclasPulsadas[K_a]: pos = pos - 1 if teclasPulsadas[K_s]: pos = pos + 1 if pygame.time.get_ticks()-tiempo > cuanto: tiempo = pygame.time.get_ticks() cual = cual + 1 if cual > 6: cual = 1 # Dibujar el fondo de color visor.fill((233,233,233)) # Dibujar al hombre visor.blit(fotogramas, (pos,100), guy[cual]) # Volcar la surface en la ventana de pygame pygame.display.update() La forma de controlar la velocidad a la que se cambia el aspecto del personaje es muy parecida a la que ya vimos cuando regulamos la velocidad en el juego del Pong. Para empezar, necesitamos dos variables que nos gestionen el tiempo de ejecución y el tiempo que hay que esperar: cuanto = 100 tiempo = 0 cuanto indica el número de milisegundos que hay que esperar para cambiar el dibujo. Los valores concretos que pongamos en esta variable y en otras similares dependerán de nosotros, de la velocidad que queramos y del número de dibujos que tengamos. La variable tiempo, recuerda, se encarga de almacenar el momento en el que se cambia el aspecto del fotograma, para poder comparar con este momento y ver si ha pasado el tiempo suficiente. Por supuesto, no olvides importar la librería que gestiona el tiempo import time ya que allí es donde reside la función pygame.time.get_ticks() que usamos para ver el tiempo que ha pasado: PÁGINA 13 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 14. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO if pygame.time.get_ticks()-tiempo > cuanto: tiempo = pygame.time.get_ticks() cual = cual + 1 if cual > 6: cual = 1 ¿Ves que es casi lo mismo que en el Pong? Aquí se mira si ha pasado el tiempo suficiente, en cuyo caso se cambia el fotograma. Y en caso contrario no se hace nada pues no se ejecuta ninguna de las instrucciones del bloque if. Otro matiz; habrás notado, quizá que hemos cambiado el número de fotograma en el que se vuelve a empezar la animación. Antes era cual = 0 y ahora cual = 1. ¿Adivinas por qué? En efecto, el fotograma número 0 es el que muestra a Guy parado y queda la animación muy rara al pasar el dibujo por allí cuando está en proceso de andar. Pruébalo: cambia el 1 por un 0 y ejecuta el programa. ¿Ves a lo que nos referimos? Claramente, el primer fotograma de la animación andadora ha de ser el 1. PÁGINA 14 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 15. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO guy06.py Hay un defecto evidente en la versión anterior de nuestro programa, y es que cuando dejamos de pulsar la tecla s el movimiento se para allí donde estuviera, incluido a mitad de paso.... Lo deseable es que al dejar de moverse, Guy quede esperando quieto, no en esa postura artificial. Otro ajuste que podemos hacer es con los dos fotogramas que abren el paso, pues las imágenes son más anchas que las demás (no es lo mismo estar con las piernas juntas que con las piernas abiertas). Veamos: # -*- coding: utf-8 -*- # Sexto ejemplo, ajustamos la animación para que tenga # un aspecto más realista. import pygame, sys from pygame.locals import * import time # Inicializar pygame pygame.init() # Crear la surface visor = pygame.display.set_mode((600, 600), 0, 32) # Poner el título de la ventana pygame.display.set_caption('Guy') # Cargar la imagen del hombre fotogramas = pygame.image.load('sprites.jpg').convert() # Variable que controla la posición de Guy pos = 0 # Almacenamos las diferentes imágenes en un diccionario guy = {} guy[0] = (0, 10, 120, 340) guy[1] = (130, 10, 120, 340) guy[2] = (260, 10, 130, 340) guy[3] = (405, 10, 170, 340) guy[4] = (600, 10, 120, 340) guy[5] = (730, 10, 130, 340) guy[6] = (870, 10, 170, 340) # Variable que controla qué imagen de Guy se muestra cual = 0 # Controlando el tiempo cuanto = 100 PÁGINA 15 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 16. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO tiempo = 0 # El bucle de eventos while True: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() # Modificar posición en función de la tecla pulsada teclasPulsadas = pygame.key.get_pressed() if teclasPulsadas[K_a]: pos = pos - 1 elif teclasPulsadas[K_s]: pos = pos + 1 if pygame.time.get_ticks()-tiempo > cuanto: tiempo = pygame.time.get_ticks() cual = cual + 1 if cual == 3 or cual == 6: pos = pos + 5 if cual > 6: cual = 1 else: cual = 0 # Dibujar el fondo de color visor.fill((233,233,233)) # Dibujar a Guy visor.blit(fotogramas, (pos,100), guy[cual]) # Volcar la surface en la ventana de pygame pygame.display.update() Lo primero es implementar la imagen de Guy parado. Ésa es precisamente la imagen 0 de nuestro diccionario. Así que cuando no se pulse ninguna tecla, tenemos que indicar que sea ésta y no otra la imagen que se dibuje cuando toque. Para ello, lo más sencillo es modificar los if que miran que tecla se ha pulsado en uno solo: if teclasPulsadas[K_a]: ... elif teclasPulsadas[K_s]: ... else: cual = 0 PÁGINA 16 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 17. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO Con una estructura de esta forma, se mira si se ha pulsado la tecla a, en caso contrario se mira si se ha pulsado la tecla s y si no se ha pulsado ninguna de las dos es cuando se pone la variable cual a 0 para indicar que se dibujará la imagen de Guy quieto. Lo siguiente es ajustar el desplazamiento con imágenes de diferentes tamaños. Vamos a hacerlo de manera sencilla, simplemente dando más desplazamiento en la posición cuando toca una de los fotogramas más anchos: if cual == 3 or cual == 6: pos = pos + 5 Como habrás notado, los fotogramas que en la imagen del sprite aparecen con las piernas abiertas son la 3 y la 6 (recuerda que la primera es la 0). La cantidad que añadamos a la variable pos dependerá del tamaño de la imagen y de cómo nos quede la animación al probarla. PÁGINA 17 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 18. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO guy07.py Llegamos al último paso. ¿Qué nos queda? El movimiento hacia la derecha está conseguido. Pero si pulsamos la tecla a para mover a Guy hacia la izquierda, veremos que éste se desliza. ¡Claro! No hemos implementado el movimiento en esa dirección. Además lo ideal sería tener otro sprite con los fotogramas del movimiento en la otra dirección, pero este no es nuestro caso... ¿Qué podemos hacer? El código fuente de nuestra versión definitiva será el siguiente: # -*- coding: utf-8 -*- # Séptimo y último ejemplo. Implementamos la animación # en sentido contrario. import pygame, sys from pygame.locals import * import time # Inicializar pygame pygame.init() # Crear la surface visor = pygame.display.set_mode((600, 600), 0, 32) # Poner el título de la ventana pygame.display.set_caption('Guy') # Variable que controla la posición de Guy pos = 0 # Cargar la imagen de Guy y su reflejo fotogramas = pygame.image.load('sprites.jpg').convert() fotogramas2 = pygame.transform.flip(fotogramas,True, False) # Almacenamos las diferentes imágenes en un diccionario guy = {} guy2 = {} guy[0] = (0, 10, 120, 340) guy2[0]= (941, 10, 120, 340) guy[1] = (130, 10, 120, 340) guy2[1]= (811, 10, 120, 340) guy[2] = (260, 10, 130, 340) guy2[2]= (671, 10, 130, 340) guy[3] = (405, 10, 170, 340) guy2[3]= (486, 10, 170, 340) guy[4] = (600, 10, 120, 340) guy2[4]= (341, 10, 120, 340) guy[5] = (730, 10, 130, 340) PÁGINA 18 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 19. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO guy2[5]= (201, 10, 130, 340) guy[6] = (870, 10, 170, 340) guy2[6]= (21, 10, 170, 340) # Controlando la dirección izquierda = True # Variable que controla qué imagen de Guy se muestra cual = 0 # Controlando el tiempo cuanto = 100 tiempo = 0 # Función que actualiza el fotograma def actualizar(): global cual, pos, tiempo if izquierda: pos = pos + 1 else: pos = pos - 1 if pygame.time.get_ticks()-tiempo > cuanto: tiempo = pygame.time.get_ticks() cual = cual + 1 if izquierda: if cual == 3 or cual == 6: pos = pos + 5 if cual > 6: cual = 1 else: if cual == 3 or cual == 6: pos = pos - 5 if cual > 6: cual = 1 # El bucle de eventos while True: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() # Modificar dirección en función de la tecla pulsada teclasPulsadas = pygame.key.get_pressed() if teclasPulsadas[K_a]: izquierda = False actualizar() elif teclasPulsadas[K_s]: izquierda = True actualizar() PÁGINA 19 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 20. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO else: cual = 0 # Dibujar el fondo de color visor.fill((233,233,233)) # Dibujar a Guy if izquierda: visor.blit(fotogramas, (pos,100), guy[cual]) else: visor.blit(fotogramas2, (pos,100), guy2[cual]) # Volcar la surface en la ventana de pygame pygame.display.update() En primer lugar necesitamos la imagen de los fotogramas del movimiento inverso al que hemos tratado. Es cierto, no la tenemos, pero PyGame es estupendo y dispone de una función que hace el trabajo por nosotros: fotogramas2 = pygame.transform.flip(fotogramas,True, False) La función pygame.transform.flip() toma como primer argumento una imagen y nos devuelve una nueva imagen invertida respecto a la anterior. La forma de invertirla depende de los dos argumentos siguientes. Si el primero de ellos es True intercambia izquierda y derecha (es decir, una reflexión respecto al eje vertical); si el segundo es True, hace lo propio con arriba y abajo (reflexión con respecto al eje horizontal). En nuestro caso sólo queremos lo primero y de ahí que pasemos True y False. (Podíamos haber cogido un programa de dibujo o de retoque y haber invertido la imagen, es cierto, pero al hacerlo así hemos aprendido una nueva técnica que a veces es útil). Lo siguiente es almacenar también las imágenes del nuevo sprite. Un nuevo diccionario viene a realizar la tarea: guy = {} guy2 = {} guy[0] = (0, 10, 120, 340) guy2[0]= (941, 10, 120, 340) guy[1] = (130, 10, 120, 340) guy2[1]= (811, 10, 120, 340) guy[2] = (260, 10, 130, 340) guy2[2]= (671, 10, 130, 340) guy[3] = (405, 10, 170, 340) guy2[3]= (486, 10, 170, 340) guy[4] = (600, 10, 120, 340) guy2[4]= (341, 10, 120, 340) guy[5] = (730, 10, 130, 340) guy2[5]= (201, 10, 130, 340) guy[6] = (870, 10, 170, 340) guy2[6]= (21, 10, 170, 340) PÁGINA 20 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 21. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO guy contiene los fotogramas del movimiento hacia la derecha y guy2 los de la izquierda. Los valores concretos que hay que poner, como antes, o los miramos con un programa de dibujo/retoque o hacemos algo de algebra teniendo encuenta el tamaño de la imagen y que los segundos son un reflejo de los primeros. Necesitamos también saber cual de los dos movimientos hay que dibujar, es decir, saber hacia dónde nos estamos moviendo: izquierda = True La variable booleana izquierda indica, si es True (como ocurre al principio de la ejecución del programa), que el movimiento es hacia la izquierda y si es False hacia la derecha. Esto es importante, pues sólo tendremos que modificar el valor de esta variable en el lugar apropiado de nuestro código para indicar qué imagen dibujar, siempre que modifiquemos la parte en la que dibujamos a nuestro protagonista a esto: if izquierda: visor.blit(fotogramas, (pos,100), guy[cual]) else: visor.blit(fotogramas2, (pos,100), guy2[cual]) ¿Entiendes la idea? Con un bloque if miramos el valor de la variable izquierda; cuando sea True dibujará un fotograma de guy y cuando sea False de guy2. Pasemos a seleccionar exactamente de qué fotograma se trata. Fíjate que hay que hacer prácticamente lo mismo en las dos direcciones, así que ¿por qué no definir una función que lo haga y así no repetimos el código? Llamemos a esa función actualizar(), ya que actualiza el dibujo de nuestro personaje. La parte que indica que hemos pulsado una tecla y hay que cambiar el dibujo quedará ahora así: if teclasPulsadas[K_a]: izquierda = False actualizar() elif teclasPulsadas[K_s]: izquierda = True actualizar() else: cual = 0 Observa que si no se ha pulsado ninguna tecla, cual se pone a 0 y, más adelante, gracias a nuestra modificación anterior, el programa dibujará el fotograma de parado correcta (hay dos distintas, una con Guy parado mirando hacia la derecha y otra mirando hacia la izquierda). Respecto al movimiento, si se ha pulsado la tecla a sabemos que hay que mover a Guy hacia la derecha, así que izquierda se pone a False y se llama a nuestra función actualizar() para que cambie el dibujo. Si se ha pulsado la tecla s, por su parte, el movimiento es hacia la izquierda, el valor correcto de la variable izquierda es ahora True y se llama de nuevo a nuestra función. Es el momento de abordar la implementación de la función actualizar(). Su código será el siguiente: PÁGINA 21 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 22. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO def actualizar(): global cual, pos, tiempo if izquierda: pos = pos + 1 else: pos = pos - 1 if pygame.time.get_ticks()-tiempo > cuanto: tiempo = pygame.time.get_ticks() cual = cual + 1 if izquierda: if cual == 3 or cual == 6: pos = pos + 5 if cual > 6: cual = 1 else: if cual == 3 or cual == 6: pos = pos - 5 if cual > 6: cual = 1 Un matiz no muy elegante y que cambiará por completo cuando veamos como trabaja de forma nativa PyGame con los sprites y la orientación a objetos, es la gestión de las variables externas a la función. Una función puede usar sus propias variables, definidas en su interior y también usar el valor de las variables que se han definido fuera de ella. Hasta aquí todo correcto. Pero en cuanto queremos cambiar el valor de una de estas últimas variables externas obtendremos un grosero error; Python protege las externas y piensa que son internas y, como no están definidas, la cosa no funciona. Para solucionarlo, existe la instrucción global. Las variables que pongamos a continuación de dicha instrucción se declaran como externas y Python nos permite modificarlas dentro del cuerpo de la función. En nuestro caso, vamos a modificar las variables cual, pos y tiempo. Lo siguiente que hay que hacer dentro de la función es modificar la posición de Guy. Aquí no hace falta que miremos si se ha pulsado el teclado, puesto que ya se ha hecho y se ha puesto la información en la variable izquierda. Basta poner, como vemos más arriba if izquierda: pos = pos + 1 else: pos = pos - 1 (¿Ves como modificamos la variable externa pos? De ahí el global al comienzo de la función). El resto también es similar a la versión anterior del programa, con las modificaciones correspondientes a las dos direcciones posibles. Simplemente miramos el valor de la variable izquierda y actuamos en consecuencia sumando o restando y cambiando el valor de la variable cual. Por supuesto, el código puede mejorarse, es algo redundante, pero para nuestros efectos, es suficiente: PÁGINA 22 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES
  • 23. ASUNTO: PROGRAMACIÓN CON PYTHON Y PYGAME CURSO: 1º BACHILLERATO if pygame.time.get_ticks()-tiempo > cuanto: tiempo = pygame.time.get_ticks() cual = cual + 1 if izquierda: if cual == 3 or cual == 6: pos = pos + 5 if cual > 6: cual = 1 else: if cual == 3 or cual == 6: pos = pos - 5 if cual > 6: cual = 1 Con todos estos cambios, la animación funciona aceptablemente en las dos direcciones, como podemos comprobar si ejecutamos el programa. PÁGINA 23 DE 23 DURACIÓN: PERÍODOS DE DOS CLASES