SlideShare una empresa de Scribd logo
1 de 10
Descargar para leer sin conexión
PROGRAMA: DRIVE
                            
                        CURSO: 1º BACHILLERATO




Drive: Un juego de Scrolling




                       (Basado en un script original de Mark Ivey)


Importación de Librerías y Definición de Constantes
Se cargan las librerías habituales, incluyendo como en el juego anterior random y os, y
definimos la anchura y la altura de la ventana de juego. También definimos la constante
VELOCIDAD que nos va a indicar la velocidad a la que vamos a movernos por la
carretera (en realidad, la velocidad a la que va a desplazarse la imagen de carretera de
fondo hacia abajo para dar la sensación de movimiento; tal como lo hemos puesto, será a
base de 5 pixeles por fotograma)


Funciones cargarImagen()                 y cargarSonido()
Las funciones cargarImagen() y cargarSonido() vuelven a ser las mismas que en el
juego anterior, sólo hemos modificado ligeramente la primera de ellas. ¿De qué manera?
Hemos asumido que no siempre queremos transparencia. Así que el segundo parámetro de
la función, tieneTrasnparencia lo que va a indicar es si la imagen ya la tiene
incorporada o no (por defecto es no). Comprobando con un if cuál es el caso, llamamos a


 PÁGINA 1 DE 10
                             
                       CC: FERNANDO SALAMERO
PROGRAMA: DRIVE
                              
                        CURSO: 1º BACHILLERATO

la función adecuada para convertir la imagen, ya sea imagen.convert_alpha() o
imagen.convert(), viejas conocidas nuestras.
Excepto la imagen de fondo que vamos a desplazar, las demás imágenes son archivos png
con transparencia, así que en esos casos invocaremos a la función con True.


Clase Coche
Ya sabemos, una vez vistos los tutoriales anteriores, cuál es la estructura de la definición de
un sprite de PyGame, es decir, una clase derivada de pygame.sprite.Sprite. Vamos a
centrarnos en las variaciones propias que nos interesan para este juego. La clase Coche
será la que represente el coche del jugador. Fíjate que, en este juego, lo que se desplaza
verticalmente es la imagen de fondo y no el coche.
1.   En __init__(), aparte de definir los atributos necesarios y situar en pantalla al sprite,
     creamos la variable giro. Para que el movimiento parezca real, necesitamos girar un
     poco el coche cuando el jugador pulse izquierda o derecha. De ello es precisamente de
     lo que se va a encargar esta variable. Hay un detalle importante al respecto; habrás
     notado que nuestra clase posee dos atributos que almacenan una imagen, image (el
     obligatorio de todo sprite) e imagen_base. ¿Por qué?
     Cuando simplemente desplazamos una imagen por pantalla, no la deformamos y todo
     está en orden. Pero cuando se modifica su forma o su tamaño estamos en lo que se
     conoce como transformación destructiva. Si realizas varias de estas
     transformaciones, tu imagen final puede no parecerse en nada a la que tenías
     originalmente. Un ejemplo; tienes una imagen y la conviertes en una que es tres veces
     más pequeña. Luego coges ésta y la amplías tres veces para volver al tamaño original.
     ¡La verás pixelada! Por el camino, has perdido la información de esos pixeles que han
     desaparecido al encoger la imagen. Al ampliarla nuevamente, el ordenador se ha
     tenido que inventar esa información dándote la imagen modificada.
     La forma de solucionar este problema es tener almacenada la imagen original y utilizar
     ésta en cada transformación, sin acumular transformaciones destructivas. Como
     quiera que la rotación de una imagen es destructiva (el número de pixeles de la
     pantalla es limitado y hay que hacer encajar la imagen en éstos), almacenamos en
     imagen_base el dibujo original del coche. Cuando tengamos que modificarlo
     hacemos sobre él las operaciones necesarias y el resultado lo ponemos en el image del
     sprite para que se muestre correctamente.
2.   Lo más importante ocurre en update(). Para empezar, no queremos que el coche gire
     sin parar y pueda darse la vuelta. Sólo queremos permitir el giro para avanzar por la
     carretera y nada más. Teniendo en cuenta que el ángulo de giro al comienzo es 0,
     vamos a dejar que el coche se desvíe un máximo de 45 grados a ambos lados. El
     bloque if que encontramos al comienzo de la función tiene este objetivo.
     Por otra parte, si no hemos llegado a ese límite (entramos en el else) sí que podemos
     girar el coche a la posición deseada. Debes también tener en cuenta que, al girar un
     sprite, PyGame mantiene fija la esquina superior derecha del sprite. Esto tiene
     ventajas e inconvenientes. El inconveniente que nos ocupa ahora es que, como al girar
     la imagen ésta cambia de tamaño, el giro queda artificial (el centro del rect
     desplazado). ¿Cómo solucionarlo? Si piensas un poco darás con la solución; primero
     almacenamos las coordenadas del centro del rect

     x, y = self.rect.center

     y más adelante, una vez hecho el giro, devolvemos el centro a su sitio
 PÁGINA 2 DE 10
                               
                       CC: FERNANDO SALAMERO
PROGRAMA: DRIVE
                            
                       CURSO: 1º BACHILLERATO



  self.rect = self.image.get_rect()
  self.rect.center = x,y

  La primera de las dos líneas anteriores no es gratuita. Recuerda que el rect del dibujo
  ha cambiado de tamaño, así que primero hay que ajustar el rect del sprite al nuevo
  tamaño con get_rect() y luego sí, recolocar su rect.center.
  Fuera de ello, el giro en sí mismo se realiza de la siguiente manera:

  self.image = pygame.transform.rotate(self.imagen_base, self.giro)

  Observa que a la función de PyGame pygame.transform.rotate() hay que pasarle
  dos argumentos; el primero es la imagen y la segunda el ángulo de giro que se quiere
  aplicar. Ese ángulo es como en matemáticas; positivo en sentido antihorario y
  negativo en el sentido de las agujas del reloj. El resultado de la función es la imagen
  girada hasta el ángulo deseado, por lo que pasamos a almacenarla en el atributo
  image del sprite.
  No ha acabado aquí todo lo correspondiente al movimiento del coche. Si se trata de
  una simulación realista, cuando el coche está girado debe desplazarse hacia el lado
  indicado. Y debe hacerlo mientras esté en movimiento. Ese es el sentido de

  if self.giro and scroll:

  scroll es una variable de estado booleana que indica si el coche está en marcha
  (como veremos luego, mientras tengas pulsada la barra espaciadora el coche se
  moverá). Por otra parte, ya hemos visto que si una variable cualquiera se usa en un if
  funciona como False cuando tiene un valor nulo y como True en cualquier otro
  caso. Así que nuestro if se cumplirá cuando se den ambas condiciones a la vez, es
  decir, el coche esté en movimiento y su ángulo de giro sea distinto de cero (que es lo
  que queremos).
  El truco usado para mover el coche en la dirección adecuada es el siguiente:

  self.rect.move_ip(-self.giro/10,0)

  Para entenderlo debes tener en cuenta que, por ejemplo, para moverse hacia la
  izquierda, la coordenada horizontal debe disminuir mientras que el ángulo
  de inclinación del coche será positivo. Lo contrario ocurre en el movimiento hacia
  la derecha. Por ello, en la conocida función move_ip(), el valor que le damos al
  desplazamiento de la primera coordenada tiene el signo cambiado respecto al
  ángulo de giro. ¿Qué valor concreto ponemos? Eso ya depende de lo deprisa que
  quieras que se desplace. Hemos puesto una cantidad en números redondos dividiendo
  por 10 el giro (así, por poner un caso, cuando el ángulo de es 45 grados, el coche se
  desplazará horizontalmente a razón de 4 pixeles por fotograma). Recuerda que no hay
  nada en contra del método de prueba y error; cambia el valor hasta que encuentres
  uno que te parezca razonable.
  El resto es simplemente la comprobación habitual para que el sprite no se salga de los
  límites de la ventana.




PÁGINA 3 DE 10
                             
                      CC: FERNANDO SALAMERO
PROGRAMA: DRIVE
                               
                       CURSO: 1º BACHILLERATO


Clase Planta
Los obstáculos que van apareciendo en el juego son sprites de tipo Planta. Veamos:
1.   Para empezar, para dar un poco de variedad, usamos dos diseños distintos de arbusto.
     Para que el programa elija al azar entre uno de los dos hemos usado un if asociado a
     random.randint(0,1). Como ya sabes, esta función devuelve un número al azar, en
     este caso un 0 o un 1. Según cuál sea de los dos (recuerda que un valor cero es
     equivalente a un False), se utiliza como imagen del sprite una u otra. Fíjate que
     conseguir que sigan saliendo al azar pero que haya más de un tipo que de otro,
     también es fácil. Por ejemplo, si se hubiera elegido un número del 0 al 2, en promedio,
     habría dos veces más de un tipo que del otro (con el valor 0 tendríamos planta2.png
     y con los valores 1 y 2 planta1.png). Y, por cierto, como ambas imágenes son de tipo
     png con trasnparencia, llamamos a la función cargarImagen() con el valor True.
     El otro detalle de la función __init__() es que usa dos parámetros (a parte del
     obligatorio self). Eso nos permitirá crear la planta en la posición que queramos ya que
     luego los usamos para posicionar el rect del sprite con topleft.
2.   Como las plantas son parte del paisaje, se han de mover con él. En la función
     update() miramos si el coche está en marcha (en cuyo caso scroll será True) y
     desplazamos consecuentemente el sprite en la dirección vertical (hacia abajo) la
     cantidad indicada por VELOCIDAD (exactamente igual que el fondo).
     Queda un detalle importante. Una vez que la planta pase de largo y salga por la parte
     inferior de la pantalla no necesitaremos más el sprite. Para que no gaste recursos del
     ordenador y no se redibuje una y otra vez fuera de la pantalla, conviene eliminarla con
     self.kill().


Clase Fondo
La clase Fondo representa la imagen de la carretera que se va a ir desplazando hacia abajo
para dar la sensación de movimiento. El término técnico inglés que se da a este tipo de
imágenes es Tiles (algo así como cuadrículas, en español). La imagen no es de tamaño
infinito pero debe parecerlo, así que a medida que se termine hay que ir añadiendo a
continuación otra imagen o ella misma, dando así la sensación de que la carretera no se
acaba nunca. Veremos luego como implementar esto; de momento vamos a ver cómo está
definido este tipo especial de objetos (he usado una clase derivada de un sprite, pero hay
otras muchas formas de hacerlo).
1.   La función __init__() es la misma que la de la clase Planta, incluso más sencilla
     puesto que tenemos una sola imagen de carretera (de paso vemos que ampliar la
     definición para tener varias y crear la sensación de que la carretera es siempre distinta
     no es muy complicado entonces).
2.   Respecto a update() hay que adelantar algo. En el juego vamos a usar dos imágenes
     de carretera, una a continuación de la otra. Para simular que la carretera no se acaba, a
     medida que una de ellas sale por completo de la pantalla se cambiará su posición de
     forma que quede justo detrás de la que viene a continuación (como si fuera un rodillo).
     Así que en update() miramos primero si hay movimiento con un bloque if y la
     variable booleana de estado scroll y en tal caso se procede a desplazar el sprite.
     Primero bajamos el sprite el número de pixeles que indica VELOCIDAD. En segundo
     lugar hay que ver cuando poner el sprite detrás del segundo que vayamos a tener.
     Piensa que los dos son iguales y tienen por lo tanto la misma altura. Cuando el borde
     superior del primero llegue abajo el segundo habrá bajado ya esa cantidad, así que hay

 PÁGINA 4 DE 10
                                
                      CC: FERNANDO SALAMERO
PROGRAMA: DRIVE
                              
                       CURSO: 1º BACHILLERATO

     que retroceder el sprite su altura menos la altura de la ventana. Así es como deben
     empalmar:

     if self.rect.top >= ALTO:
        self.rect.bottom = ALTO - self.rect.height



Cuerpo Principal del Juego
Siguiendo el esquema habitual nos encontramos con lo siguiente:

1.   Inicializar y cargar sonidos

     Poco que comentar aquí. El sonido que cargamos en la variable choque lo
     emplearemos luego cuando el coche colisione con algún arbusto.


2.   Crear los Sprites y los Grupos

     Creamos los dos sprites que se encargarán de simular la carretera interminable. El
     primero, carretera1, lo situamos en pantalla ocupándola por completo. El segundo,
     carretera2, lo creamos justo encima. Como en la definición de la clase Carretera los
     parámetros que se usan para posicionar el sprite son los de la esquina superior
     izquierda, en este segundo objeto hemos de poner de coordenada vertical la altura del
     propio sprite (en este caso de carretera1, ya que es igual a carretera2 pero este
     último ¡todavía no está creado!) cambiada de signo:

     carretera2 = Carretera(0, -carretera1.rect.height)

     A continuación creamos el coche del jugador, coche, y añadimos los sprites a los
     grupos apropiados; los tiles a fondoGrupo y el coche a cocheGrupo. Creamos, así
     mismo, un grupo inicialmente vacío pero que contendrá los arbustos que vayan
     apareciendo en el juego al azar, cosasGrupo.


3.   Definición de variables de útiles

     Ha tocado el turno a la definición de las variables de juego (muchas veces también
     llamadas variables de estado). jugando controla si el juego está activo o ha
     terminado, por lo que lo emplearemos el el bucle while típico de la animación. scroll
     ya sabemos que indica si el coche está en marcha o no. intervaloPlantas lo usamos
     de la misma manera que usamos intervaloEnemigos en el juego de Star Wars;
     vigila cada cuánto hay que crear un nuevo obstáculo. Igual que la otra vez, eso se
     realizará cuando llegue a un cierto valor y se ponga a cero la variable para volver a
     empezar. Finalmente, reloj nos permitirá, de la forma habitual, controlar la velocidad
     de la animación.

4.   Bucle del Juego

     En el bucle del juego, después de indicar que se va a ejecutar a 60 fotogramas por

 PÁGINA 5 DE 10
                               
                      CC: FERNANDO SALAMERO
PROGRAMA: DRIVE
                             
                       CURSO: 1º BACHILLERATO

  segundo, entramos directamente el la lista de eventos. Hay dos situaciones en las
  que nos fijamos aquí. La primera es el momento de terminar la partida, ya sea al cerrar
  la ventana o al pulsar la tecla ESC. La segunda es determinar cuando hay que poner el
  coche en marcha o cuando hay que pararlo. La tecla que se encargará de ello es la de la
  barra espaciadora (con ella pulsada el motor está en funcionamiento y cuando la
  dejamos de pulsar el motor se detiene). Nada más sencillo; nos fijamos en los eventos
  KEYDOWN y KEYUP y si la tecla culpable es K_SPACE y asignamos el valor
  conveniente a la variable scroll.
  Para mover el coche sin interferir a la barra espaciadora usamos, también como
  siempre, la función pygame.key.get_pressed(). El diccionario resultante lo
  almacenamos en teclasPulsadas y miramos si las teclas del cursor están
  implicadas, en cuyo caso se procede a girar el coche en la dirección adecuada.
  Recuerda el convenio de signos con los ángulos; al girar hacia la izquierda hay que
  aumentar el ángulo (por eso sumamos VELOCIDAD al atributo giro del coche) y hay
  que restar cuando el giro es hacia la derecha.
  El código que encontramos luego es el mismo que en Star Wars; se incrementa el
  contador y si llega a 200 se crea una nueva Planta. Fíjate cómo se ha hecho:

  cosasGrupo.add( Planta( random.randint(0,ANCHO) , -50 ) )

  Al crear el arbusto lo hacemos fuera de la pantalla (50 pixeles por encima) para que
  aparezca suavemente por el borde superior mientras se mueve. Su coordenada
  horizontal la generamos al azar en cualquier punto comprendido entre los límites de la
  ventana.
  Ya está casi todo hecho. Lo siguiente es llamar a la función update() de todos los
  grupos para que sitúe a todos los sprites en las nuevas posiciones. Y antes de dibujarlos
  en pantalla hay que comprobar si hay colisión entre el coche y algún arbusto. El
  código es casi idéntico que el que usamos en Star Wars. Hay una pequeña diferencia;

  pygame.sprite.groupcollide( cocheGrupo, cosasGrupo, 0, 1)

  En el programa anterior, cuando un rayo láser impactaba en una nave, queríamos que
  desaparecieran los dos sprites. Ahora lo que queremos es que desaparezca el
  arbusto pero no el coche. Es por eso por lo que en los argumentos encargados de
  eliminar a los sprites implicados en la colisión ponemos un 0 en el correspondiente al
  grupo del coche (‘no lo elimines’) y un 1 en el grupo de los arbustos (‘elimínalo’).
  Hecho el trabajo duro, sólo queda usar draw() con todos los grupos para que dibuje
  los sprites en sus nuevas posiciones y pygame.display.update() para que se
  vuelque el fotograma completado en pantalla.
  Una última cosa; ¿te has fijado que esta vez no hemos borrado los sprites de sus
  antiguas posiciones? En este caso no hace falta por que, al ocupar el tile de la carretera
  toda la ventana, cuando se dibuja este primer sprite lo hace por encima de todo lo que
  hubiera antes. Algo que nos ahorramos.




PÁGINA 6 DE 10
                              
                      CC: FERNANDO SALAMERO
PROGRAMA: DRIVE
                                
              CURSO: 1º BACHILLERATO



   # -*- coding: utf-8 -*-
   #-------------------------------------------------------------------
   # Clon de Drive
   # (Basado en un script original de Mark Ivey)
   #-------------------------------------------------------------------

   import random
   import os, pygame
   from pygame.locals import *

   ANCHO = 800
   ALTO = 600
   VELOCIDAD = 5

   #-------------------------------------------------------------------
   # Función cargarImagen()
   # ( Carga una imagen desde un archivo, devolviendo el objeto apropiado)
   #-------------------------------------------------------------------

   def cargarImagen( archivo, tieneTransparencia = False ):

      lugar = os.path.join( "data", archivo )

      try:
         imagen = pygame.image.load( lugar )
      except pygame.error, mensaje:
         print "No puedo cargar la imagen:", lugar
         raise SystemExit, mensaje

      if tieneTransparencia:
          imagen = imagen.convert_alpha()
      else:
          imagen = imagen.convert()

      return imagen

   #-------------------------------------------------------------------
   # Función cargarSonido()
   # ( Carga un sonido desde un archivo, devolviendo el objeto apropiado)
   #-------------------------------------------------------------------

   def cargarSonido( archivo ):

      class sinSonido:
         def play( self ):
           pass

      if not pygame.mixer or not pygame.mixer.get_init():
         return sinSonido()




PÁGINA 7 DE 10
                                 
             CC: FERNANDO SALAMERO
PROGRAMA: DRIVE
                                
                  CURSO: 1º BACHILLERATO




      lugar = os.path.join( "data", archivo )

      try:
         sound = pygame.mixer.Sound( lugar )
      except pygame.error, message:
         print "No puedo cargar el sonido:", lugar
         raise SystemExit, message

      return sound

   #-------------------------------------------------------------------
   # Sprite Coche
   # (Coche del Jugador)
   #-------------------------------------------------------------------

   class Coche( pygame.sprite.Sprite ):

      def __init__( self ):
        pygame.sprite.Sprite.__init__( self )
        self.imagen_base = cargarImagen( "coche.png", True )
        self.image = self.imagen_base
        self.rect = self.image.get_rect()
        self.giro = 0
        self.rect.center = (550,500)

      def update( self ):
        if self.giro >= 45:
            self.giro = 45
        elif self.giro <= -45:
            self.giro = -45
        else:
            x, y = self.rect.center
            self.image = pygame.transform.rotate(self.imagen_base, self.giro)
            self.rect = self.image.get_rect()
            self.rect.center = x,y

         if self.giro and scroll:
             self.rect.move_ip(-self.giro/10,0)
             if self.rect.left <= 0:
                 self.rect.left = 0
             elif self.rect.right >= ANCHO:
                 self.rect.right = ANCHO

   #-------------------------------------------------------------------
   # Sprite Planta
   # (Palntas de la carretera)
   #-------------------------------------------------------------------

   class Planta( pygame.sprite.Sprite ):




PÁGINA 8 DE 10
                                 
                 CC: FERNANDO SALAMERO
PROGRAMA: DRIVE
                              
                      CURSO: 1º BACHILLERATO



      def __init__( self, posx, posy ):
        pygame.sprite.Sprite.__init__( self )
        if random.randint(0,1):
            self.image = cargarImagen( "planta1.png", True )
        else:
            self.image = cargarImagen( "planta2.png", True )
        self.rect = self.image.get_rect()
        self.rect.topleft = (posx,posy)

      def update( self ):
        if scroll:
            self.rect.move_ip( 0,VELOCIDAD )
        if self.rect.top > ANCHO:
            self.kill()

   #-------------------------------------------------------------------
   # Sprite Fondo
   # (Carretera)
   #-------------------------------------------------------------------

   class Carretera( pygame.sprite.Sprite ):

      def __init__( self, posx, posy ):
        pygame.sprite.Sprite.__init__( self )
        self.imagen_base = cargarImagen( "carretera.png", False )
        self.image = self.imagen_base
        self.rect = self.image.get_rect()
        self.rect.topleft = (posx,posy)


      def update( self ):
        if scroll:
            self.rect.move_ip( 0,VELOCIDAD )
            if self.rect.top >= ALTO:
                self.rect.bottom = ALTO - self.rect.height

   #-------------------------------------------------------------------
   # Cuerpo Principal del Juego
   #-------------------------------------------------------------------

   pygame.init()
   visor = pygame.display.set_mode( (ANCHO, ALTO) )
   pygame.display.set_caption( "Drive" )

   choque = cargarSonido( "choque.wav" )

   carretera1 = Carretera(0,0)
   carretera2 = Carretera(0, -carretera1.rect.height)
   coche = Coche()




PÁGINA 9 DE 10
                               
                     CC: FERNANDO SALAMERO
PROGRAMA: DRIVE
                           
                      CURSO: 1º BACHILLERATO



   fondoGrupo = pygame.sprite.RenderUpdates(carretera1)
   fondoGrupo.add(carretera2)
   cocheGrupo = pygame.sprite.RenderUpdates(coche)
   cosasGrupo = pygame.sprite.RenderUpdates()

   jugando = True
   scroll = False
   intervaloPlantas = 0
   reloj = pygame.time.Clock()

   while jugando:
     reloj.tick( 60 )

      for event in pygame.event.get():
         if event.type == QUIT:
             jugando = False
         elif event.type == KEYDOWN:
             if event.key == K_ESCAPE:
                 jugando = False
             elif event.key == K_SPACE:
                 scroll = True
         elif event.type == KEYUP:
             if event.key == K_SPACE:
                 scroll = False

      teclasPulsadas = pygame.key.get_pressed()
      if teclasPulsadas[K_LEFT]:
          coche.giro += VELOCIDAD
      if teclasPulsadas[K_RIGHT]:
          coche.giro -= VELOCIDAD

      intervaloPlantas += 1
      if intervaloPlantas >= 100 and scroll:
          cosasGrupo.add( Planta( random.randint(0,ANCHO) , -50 ) )
          intervaloPlantas = 0

      fondoGrupo.update()
      cocheGrupo.update()
      cosasGrupo.update()

      for pum in pygame.sprite.groupcollide( cocheGrupo, cosasGrupo, 0, 1):
         choque.play()

      fondoGrupo.draw( visor )
      cocheGrupo.draw( visor )
      cosasGrupo.draw( visor )

      pygame.display.update()




PÁGINA 10 DE 10
                           
                     CC: FERNANDO SALAMERO

Más contenido relacionado

La actualidad más candente

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
 
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
 
Introducción a las librerías PyGame y PyOpenGL
Introducción a las librerías PyGame y PyOpenGLIntroducción a las librerías PyGame y PyOpenGL
Introducción a las librerías PyGame y PyOpenGLkdeespana
 
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 (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
 
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
 
Xna game studio presentación 02
Xna game studio   presentación 02Xna game studio   presentación 02
Xna game studio presentación 02Juan Cardona
 
Xna game studio presentación 01
Xna game studio   presentación 01Xna game studio   presentación 01
Xna game studio presentación 01Juan Cardona
 
Taller de introduccion a python con turtle
Taller de  introduccion a python  con  turtleTaller de  introduccion a python  con  turtle
Taller de introduccion a python con turtleAlbert Page
 
Ejemplo 18 animación usando gamecanvas
Ejemplo 18 animación usando gamecanvasEjemplo 18 animación usando gamecanvas
Ejemplo 18 animación usando gamecanvasMercedes Reyes Carrion
 
Vray manual para interiores
Vray manual para interioresVray manual para interiores
Vray manual para interioresAdrian M.
 
Scratchmini manual 1_
Scratchmini manual 1_Scratchmini manual 1_
Scratchmini manual 1_luz deluna
 

La actualidad más candente (20)

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)
 
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)
 
Introducción a las librerías PyGame y PyOpenGL
Introducción a las librerías PyGame y PyOpenGLIntroducción a las librerías PyGame y PyOpenGL
Introducción a las librerías PyGame y PyOpenGL
 
Aventura
AventuraAventura
Aventura
 
Intro pygamev2
Intro pygamev2Intro pygamev2
Intro pygamev2
 
Intro PyGame Capitulo 5
Intro PyGame Capitulo 5Intro PyGame Capitulo 5
Intro PyGame Capitulo 5
 
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)
 
Intro Pygame Capitulo 2
Intro Pygame Capitulo 2Intro Pygame Capitulo 2
Intro Pygame Capitulo 2
 
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)
 
Intro PygameCapitulo 3
Intro PygameCapitulo 3Intro PygameCapitulo 3
Intro PygameCapitulo 3
 
Intro PyGame Capitulo 1
Intro PyGame Capitulo 1Intro PyGame Capitulo 1
Intro PyGame Capitulo 1
 
Capitulo 4
Capitulo 4Capitulo 4
Capitulo 4
 
Intro PyGame Capitulo 0
Intro PyGame Capitulo 0Intro PyGame Capitulo 0
Intro PyGame Capitulo 0
 
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)
 
Xna game studio presentación 02
Xna game studio   presentación 02Xna game studio   presentación 02
Xna game studio presentación 02
 
Xna game studio presentación 01
Xna game studio   presentación 01Xna game studio   presentación 01
Xna game studio presentación 01
 
Taller de introduccion a python con turtle
Taller de  introduccion a python  con  turtleTaller de  introduccion a python  con  turtle
Taller de introduccion a python con turtle
 
Ejemplo 18 animación usando gamecanvas
Ejemplo 18 animación usando gamecanvasEjemplo 18 animación usando gamecanvas
Ejemplo 18 animación usando gamecanvas
 
Vray manual para interiores
Vray manual para interioresVray manual para interiores
Vray manual para interiores
 
Scratchmini manual 1_
Scratchmini manual 1_Scratchmini manual 1_
Scratchmini manual 1_
 

Similar a Drive: Un juego de Scrolling

Similar a Drive: Un juego de Scrolling (20)

Carrito de carreras flash copia
Carrito de carreras flash   copiaCarrito de carreras flash   copia
Carrito de carreras flash copia
 
Guia 5 para 10 y 11
Guia 5 para 10 y 11Guia 5 para 10 y 11
Guia 5 para 10 y 11
 
ANIMACIÓN AUTOCAD
ANIMACIÓN AUTOCADANIMACIÓN AUTOCAD
ANIMACIÓN AUTOCAD
 
Vray14520
Vray14520Vray14520
Vray14520
 
logo a logo
logo a logologo a logo
logo a logo
 
Tutorial para escaneo 3 d usando scanner projector
Tutorial para escaneo 3 d usando scanner projectorTutorial para escaneo 3 d usando scanner projector
Tutorial para escaneo 3 d usando scanner projector
 
Blender digital sculpting - Pierre Schiler
Blender digital sculpting - Pierre SchilerBlender digital sculpting - Pierre Schiler
Blender digital sculpting - Pierre Schiler
 
Camaras y Espacio 3D en After effects
Camaras y Espacio 3D en After effectsCamaras y Espacio 3D en After effects
Camaras y Espacio 3D en After effects
 
Utp 2015-2_pdi_lab2
 Utp 2015-2_pdi_lab2 Utp 2015-2_pdi_lab2
Utp 2015-2_pdi_lab2
 
Modelado Y AnimacióN De Objetos 2 D Y 3 D
Modelado Y AnimacióN De Objetos 2 D Y 3 DModelado Y AnimacióN De Objetos 2 D Y 3 D
Modelado Y AnimacióN De Objetos 2 D Y 3 D
 
Flash conceptos basicos
Flash conceptos basicosFlash conceptos basicos
Flash conceptos basicos
 
Analisis fotografico
Analisis fotograficoAnalisis fotografico
Analisis fotografico
 
Unidad 2
Unidad 2Unidad 2
Unidad 2
 
Modelado y animación de objetos 2 d y 3d
Modelado y animación de objetos 2 d y 3dModelado y animación de objetos 2 d y 3d
Modelado y animación de objetos 2 d y 3d
 
Logo a logo
Logo a logoLogo a logo
Logo a logo
 
Inkscape logo a logo (1) (1)
Inkscape logo a logo (1) (1)Inkscape logo a logo (1) (1)
Inkscape logo a logo (1) (1)
 
Manual Inkscape
Manual InkscapeManual Inkscape
Manual Inkscape
 
Unidad 2
Unidad 2Unidad 2
Unidad 2
 
Unidad 2
Unidad 2Unidad 2
Unidad 2
 
Unidad 2
Unidad 2Unidad 2
Unidad 2
 

Más de Fernando Salamero

(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 proponeFernando Salamero
 
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 proponeFernando 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
 
(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ísicaFernando Salamero
 
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ísicaFernando 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
 
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 (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
 
Programación con Pygame VII
Programación con Pygame VIIProgramación con Pygame VII
Programación con Pygame VIIFernando Salamero
 

Más de Fernando Salamero (19)

(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
 
(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
 
(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
 
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
 
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)
 
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)
 
Python básico II
Python básico IIPython básico II
Python básico II
 
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)
 
Python (práctica 1)
Python (práctica 1)Python (práctica 1)
Python (práctica 1)
 
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
 

Último

30-de-abril-plebiscito-1902_240420_104511.pdf
30-de-abril-plebiscito-1902_240420_104511.pdf30-de-abril-plebiscito-1902_240420_104511.pdf
30-de-abril-plebiscito-1902_240420_104511.pdfgimenanahuel
 
DE LAS OLIMPIADAS GRIEGAS A LAS DEL MUNDO MODERNO.ppt
DE LAS OLIMPIADAS GRIEGAS A LAS DEL MUNDO MODERNO.pptDE LAS OLIMPIADAS GRIEGAS A LAS DEL MUNDO MODERNO.ppt
DE LAS OLIMPIADAS GRIEGAS A LAS DEL MUNDO MODERNO.pptELENA GALLARDO PAÚLS
 
Neurociencias para Educadores NE24 Ccesa007.pdf
Neurociencias para Educadores  NE24  Ccesa007.pdfNeurociencias para Educadores  NE24  Ccesa007.pdf
Neurociencias para Educadores NE24 Ccesa007.pdfDemetrio Ccesa Rayme
 
NARRACIONES SOBRE LA VIDA DEL GENERAL ELOY ALFARO
NARRACIONES SOBRE LA VIDA DEL GENERAL ELOY ALFARONARRACIONES SOBRE LA VIDA DEL GENERAL ELOY ALFARO
NARRACIONES SOBRE LA VIDA DEL GENERAL ELOY ALFAROJosé Luis Palma
 
la unidad de s sesion edussssssssssssssscacio fisca
la unidad de s sesion edussssssssssssssscacio fiscala unidad de s sesion edussssssssssssssscacio fisca
la unidad de s sesion edussssssssssssssscacio fiscaeliseo91
 
Planificacion Anual 4to Grado Educacion Primaria 2024 Ccesa007.pdf
Planificacion Anual 4to Grado Educacion Primaria   2024   Ccesa007.pdfPlanificacion Anual 4to Grado Educacion Primaria   2024   Ccesa007.pdf
Planificacion Anual 4to Grado Educacion Primaria 2024 Ccesa007.pdfDemetrio Ccesa Rayme
 
SINTAXIS DE LA ORACIÓN SIMPLE 2023-2024.pptx
SINTAXIS DE LA ORACIÓN SIMPLE 2023-2024.pptxSINTAXIS DE LA ORACIÓN SIMPLE 2023-2024.pptx
SINTAXIS DE LA ORACIÓN SIMPLE 2023-2024.pptxlclcarmen
 
EXPANSIÓN ECONÓMICA DE OCCIDENTE LEÓN.pptx
EXPANSIÓN ECONÓMICA DE OCCIDENTE LEÓN.pptxEXPANSIÓN ECONÓMICA DE OCCIDENTE LEÓN.pptx
EXPANSIÓN ECONÓMICA DE OCCIDENTE LEÓN.pptxPryhaSalam
 
Registro Auxiliar - Primaria 2024 (1).pptx
Registro Auxiliar - Primaria  2024 (1).pptxRegistro Auxiliar - Primaria  2024 (1).pptx
Registro Auxiliar - Primaria 2024 (1).pptxFelicitasAsuncionDia
 
celula, tipos, teoria celular, energia y dinamica
celula, tipos, teoria celular, energia y dinamicacelula, tipos, teoria celular, energia y dinamica
celula, tipos, teoria celular, energia y dinamicaFlor Idalia Espinoza Ortega
 
La empresa sostenible: Principales Características, Barreras para su Avance y...
La empresa sostenible: Principales Características, Barreras para su Avance y...La empresa sostenible: Principales Características, Barreras para su Avance y...
La empresa sostenible: Principales Características, Barreras para su Avance y...JonathanCovena1
 
RAIZ CUADRADA Y CUBICA PARA NIÑOS DE PRIMARIA
RAIZ CUADRADA Y CUBICA PARA NIÑOS DE PRIMARIARAIZ CUADRADA Y CUBICA PARA NIÑOS DE PRIMARIA
RAIZ CUADRADA Y CUBICA PARA NIÑOS DE PRIMARIACarlos Campaña Montenegro
 
TECNOLOGÍA FARMACEUTICA OPERACIONES UNITARIAS.pptx
TECNOLOGÍA FARMACEUTICA OPERACIONES UNITARIAS.pptxTECNOLOGÍA FARMACEUTICA OPERACIONES UNITARIAS.pptx
TECNOLOGÍA FARMACEUTICA OPERACIONES UNITARIAS.pptxKarlaMassielMartinez
 
Caja de herramientas de inteligencia artificial para la academia y la investi...
Caja de herramientas de inteligencia artificial para la academia y la investi...Caja de herramientas de inteligencia artificial para la academia y la investi...
Caja de herramientas de inteligencia artificial para la academia y la investi...Lourdes Feria
 
Planificacion Anual 2do Grado Educacion Primaria 2024 Ccesa007.pdf
Planificacion Anual 2do Grado Educacion Primaria   2024   Ccesa007.pdfPlanificacion Anual 2do Grado Educacion Primaria   2024   Ccesa007.pdf
Planificacion Anual 2do Grado Educacion Primaria 2024 Ccesa007.pdfDemetrio Ccesa Rayme
 
Identificación de componentes Hardware del PC
Identificación de componentes Hardware del PCIdentificación de componentes Hardware del PC
Identificación de componentes Hardware del PCCesarFernandez937857
 
Manual - ABAS II completo 263 hojas .pdf
Manual - ABAS II completo 263 hojas .pdfManual - ABAS II completo 263 hojas .pdf
Manual - ABAS II completo 263 hojas .pdfMaryRotonda1
 
MAYO 1 PROYECTO día de la madre el amor más grande
MAYO 1 PROYECTO día de la madre el amor más grandeMAYO 1 PROYECTO día de la madre el amor más grande
MAYO 1 PROYECTO día de la madre el amor más grandeMarjorie Burga
 

Último (20)

30-de-abril-plebiscito-1902_240420_104511.pdf
30-de-abril-plebiscito-1902_240420_104511.pdf30-de-abril-plebiscito-1902_240420_104511.pdf
30-de-abril-plebiscito-1902_240420_104511.pdf
 
DE LAS OLIMPIADAS GRIEGAS A LAS DEL MUNDO MODERNO.ppt
DE LAS OLIMPIADAS GRIEGAS A LAS DEL MUNDO MODERNO.pptDE LAS OLIMPIADAS GRIEGAS A LAS DEL MUNDO MODERNO.ppt
DE LAS OLIMPIADAS GRIEGAS A LAS DEL MUNDO MODERNO.ppt
 
Neurociencias para Educadores NE24 Ccesa007.pdf
Neurociencias para Educadores  NE24  Ccesa007.pdfNeurociencias para Educadores  NE24  Ccesa007.pdf
Neurociencias para Educadores NE24 Ccesa007.pdf
 
NARRACIONES SOBRE LA VIDA DEL GENERAL ELOY ALFARO
NARRACIONES SOBRE LA VIDA DEL GENERAL ELOY ALFARONARRACIONES SOBRE LA VIDA DEL GENERAL ELOY ALFARO
NARRACIONES SOBRE LA VIDA DEL GENERAL ELOY ALFARO
 
la unidad de s sesion edussssssssssssssscacio fisca
la unidad de s sesion edussssssssssssssscacio fiscala unidad de s sesion edussssssssssssssscacio fisca
la unidad de s sesion edussssssssssssssscacio fisca
 
Planificacion Anual 4to Grado Educacion Primaria 2024 Ccesa007.pdf
Planificacion Anual 4to Grado Educacion Primaria   2024   Ccesa007.pdfPlanificacion Anual 4to Grado Educacion Primaria   2024   Ccesa007.pdf
Planificacion Anual 4to Grado Educacion Primaria 2024 Ccesa007.pdf
 
SINTAXIS DE LA ORACIÓN SIMPLE 2023-2024.pptx
SINTAXIS DE LA ORACIÓN SIMPLE 2023-2024.pptxSINTAXIS DE LA ORACIÓN SIMPLE 2023-2024.pptx
SINTAXIS DE LA ORACIÓN SIMPLE 2023-2024.pptx
 
EXPANSIÓN ECONÓMICA DE OCCIDENTE LEÓN.pptx
EXPANSIÓN ECONÓMICA DE OCCIDENTE LEÓN.pptxEXPANSIÓN ECONÓMICA DE OCCIDENTE LEÓN.pptx
EXPANSIÓN ECONÓMICA DE OCCIDENTE LEÓN.pptx
 
Registro Auxiliar - Primaria 2024 (1).pptx
Registro Auxiliar - Primaria  2024 (1).pptxRegistro Auxiliar - Primaria  2024 (1).pptx
Registro Auxiliar - Primaria 2024 (1).pptx
 
celula, tipos, teoria celular, energia y dinamica
celula, tipos, teoria celular, energia y dinamicacelula, tipos, teoria celular, energia y dinamica
celula, tipos, teoria celular, energia y dinamica
 
La empresa sostenible: Principales Características, Barreras para su Avance y...
La empresa sostenible: Principales Características, Barreras para su Avance y...La empresa sostenible: Principales Características, Barreras para su Avance y...
La empresa sostenible: Principales Características, Barreras para su Avance y...
 
Medición del Movimiento Online 2024.pptx
Medición del Movimiento Online 2024.pptxMedición del Movimiento Online 2024.pptx
Medición del Movimiento Online 2024.pptx
 
RAIZ CUADRADA Y CUBICA PARA NIÑOS DE PRIMARIA
RAIZ CUADRADA Y CUBICA PARA NIÑOS DE PRIMARIARAIZ CUADRADA Y CUBICA PARA NIÑOS DE PRIMARIA
RAIZ CUADRADA Y CUBICA PARA NIÑOS DE PRIMARIA
 
TECNOLOGÍA FARMACEUTICA OPERACIONES UNITARIAS.pptx
TECNOLOGÍA FARMACEUTICA OPERACIONES UNITARIAS.pptxTECNOLOGÍA FARMACEUTICA OPERACIONES UNITARIAS.pptx
TECNOLOGÍA FARMACEUTICA OPERACIONES UNITARIAS.pptx
 
Caja de herramientas de inteligencia artificial para la academia y la investi...
Caja de herramientas de inteligencia artificial para la academia y la investi...Caja de herramientas de inteligencia artificial para la academia y la investi...
Caja de herramientas de inteligencia artificial para la academia y la investi...
 
Planificacion Anual 2do Grado Educacion Primaria 2024 Ccesa007.pdf
Planificacion Anual 2do Grado Educacion Primaria   2024   Ccesa007.pdfPlanificacion Anual 2do Grado Educacion Primaria   2024   Ccesa007.pdf
Planificacion Anual 2do Grado Educacion Primaria 2024 Ccesa007.pdf
 
Identificación de componentes Hardware del PC
Identificación de componentes Hardware del PCIdentificación de componentes Hardware del PC
Identificación de componentes Hardware del PC
 
Power Point: "Defendamos la verdad".pptx
Power Point: "Defendamos la verdad".pptxPower Point: "Defendamos la verdad".pptx
Power Point: "Defendamos la verdad".pptx
 
Manual - ABAS II completo 263 hojas .pdf
Manual - ABAS II completo 263 hojas .pdfManual - ABAS II completo 263 hojas .pdf
Manual - ABAS II completo 263 hojas .pdf
 
MAYO 1 PROYECTO día de la madre el amor más grande
MAYO 1 PROYECTO día de la madre el amor más grandeMAYO 1 PROYECTO día de la madre el amor más grande
MAYO 1 PROYECTO día de la madre el amor más grande
 

Drive: Un juego de Scrolling

  • 1. PROGRAMA: DRIVE CURSO: 1º BACHILLERATO Drive: Un juego de Scrolling (Basado en un script original de Mark Ivey) Importación de Librerías y Definición de Constantes Se cargan las librerías habituales, incluyendo como en el juego anterior random y os, y definimos la anchura y la altura de la ventana de juego. También definimos la constante VELOCIDAD que nos va a indicar la velocidad a la que vamos a movernos por la carretera (en realidad, la velocidad a la que va a desplazarse la imagen de carretera de fondo hacia abajo para dar la sensación de movimiento; tal como lo hemos puesto, será a base de 5 pixeles por fotograma) Funciones cargarImagen() y cargarSonido() Las funciones cargarImagen() y cargarSonido() vuelven a ser las mismas que en el juego anterior, sólo hemos modificado ligeramente la primera de ellas. ¿De qué manera? Hemos asumido que no siempre queremos transparencia. Así que el segundo parámetro de la función, tieneTrasnparencia lo que va a indicar es si la imagen ya la tiene incorporada o no (por defecto es no). Comprobando con un if cuál es el caso, llamamos a PÁGINA 1 DE 10 CC: FERNANDO SALAMERO
  • 2. PROGRAMA: DRIVE CURSO: 1º BACHILLERATO la función adecuada para convertir la imagen, ya sea imagen.convert_alpha() o imagen.convert(), viejas conocidas nuestras. Excepto la imagen de fondo que vamos a desplazar, las demás imágenes son archivos png con transparencia, así que en esos casos invocaremos a la función con True. Clase Coche Ya sabemos, una vez vistos los tutoriales anteriores, cuál es la estructura de la definición de un sprite de PyGame, es decir, una clase derivada de pygame.sprite.Sprite. Vamos a centrarnos en las variaciones propias que nos interesan para este juego. La clase Coche será la que represente el coche del jugador. Fíjate que, en este juego, lo que se desplaza verticalmente es la imagen de fondo y no el coche. 1. En __init__(), aparte de definir los atributos necesarios y situar en pantalla al sprite, creamos la variable giro. Para que el movimiento parezca real, necesitamos girar un poco el coche cuando el jugador pulse izquierda o derecha. De ello es precisamente de lo que se va a encargar esta variable. Hay un detalle importante al respecto; habrás notado que nuestra clase posee dos atributos que almacenan una imagen, image (el obligatorio de todo sprite) e imagen_base. ¿Por qué? Cuando simplemente desplazamos una imagen por pantalla, no la deformamos y todo está en orden. Pero cuando se modifica su forma o su tamaño estamos en lo que se conoce como transformación destructiva. Si realizas varias de estas transformaciones, tu imagen final puede no parecerse en nada a la que tenías originalmente. Un ejemplo; tienes una imagen y la conviertes en una que es tres veces más pequeña. Luego coges ésta y la amplías tres veces para volver al tamaño original. ¡La verás pixelada! Por el camino, has perdido la información de esos pixeles que han desaparecido al encoger la imagen. Al ampliarla nuevamente, el ordenador se ha tenido que inventar esa información dándote la imagen modificada. La forma de solucionar este problema es tener almacenada la imagen original y utilizar ésta en cada transformación, sin acumular transformaciones destructivas. Como quiera que la rotación de una imagen es destructiva (el número de pixeles de la pantalla es limitado y hay que hacer encajar la imagen en éstos), almacenamos en imagen_base el dibujo original del coche. Cuando tengamos que modificarlo hacemos sobre él las operaciones necesarias y el resultado lo ponemos en el image del sprite para que se muestre correctamente. 2. Lo más importante ocurre en update(). Para empezar, no queremos que el coche gire sin parar y pueda darse la vuelta. Sólo queremos permitir el giro para avanzar por la carretera y nada más. Teniendo en cuenta que el ángulo de giro al comienzo es 0, vamos a dejar que el coche se desvíe un máximo de 45 grados a ambos lados. El bloque if que encontramos al comienzo de la función tiene este objetivo. Por otra parte, si no hemos llegado a ese límite (entramos en el else) sí que podemos girar el coche a la posición deseada. Debes también tener en cuenta que, al girar un sprite, PyGame mantiene fija la esquina superior derecha del sprite. Esto tiene ventajas e inconvenientes. El inconveniente que nos ocupa ahora es que, como al girar la imagen ésta cambia de tamaño, el giro queda artificial (el centro del rect desplazado). ¿Cómo solucionarlo? Si piensas un poco darás con la solución; primero almacenamos las coordenadas del centro del rect x, y = self.rect.center y más adelante, una vez hecho el giro, devolvemos el centro a su sitio PÁGINA 2 DE 10 CC: FERNANDO SALAMERO
  • 3. PROGRAMA: DRIVE CURSO: 1º BACHILLERATO self.rect = self.image.get_rect() self.rect.center = x,y La primera de las dos líneas anteriores no es gratuita. Recuerda que el rect del dibujo ha cambiado de tamaño, así que primero hay que ajustar el rect del sprite al nuevo tamaño con get_rect() y luego sí, recolocar su rect.center. Fuera de ello, el giro en sí mismo se realiza de la siguiente manera: self.image = pygame.transform.rotate(self.imagen_base, self.giro) Observa que a la función de PyGame pygame.transform.rotate() hay que pasarle dos argumentos; el primero es la imagen y la segunda el ángulo de giro que se quiere aplicar. Ese ángulo es como en matemáticas; positivo en sentido antihorario y negativo en el sentido de las agujas del reloj. El resultado de la función es la imagen girada hasta el ángulo deseado, por lo que pasamos a almacenarla en el atributo image del sprite. No ha acabado aquí todo lo correspondiente al movimiento del coche. Si se trata de una simulación realista, cuando el coche está girado debe desplazarse hacia el lado indicado. Y debe hacerlo mientras esté en movimiento. Ese es el sentido de if self.giro and scroll: scroll es una variable de estado booleana que indica si el coche está en marcha (como veremos luego, mientras tengas pulsada la barra espaciadora el coche se moverá). Por otra parte, ya hemos visto que si una variable cualquiera se usa en un if funciona como False cuando tiene un valor nulo y como True en cualquier otro caso. Así que nuestro if se cumplirá cuando se den ambas condiciones a la vez, es decir, el coche esté en movimiento y su ángulo de giro sea distinto de cero (que es lo que queremos). El truco usado para mover el coche en la dirección adecuada es el siguiente: self.rect.move_ip(-self.giro/10,0) Para entenderlo debes tener en cuenta que, por ejemplo, para moverse hacia la izquierda, la coordenada horizontal debe disminuir mientras que el ángulo de inclinación del coche será positivo. Lo contrario ocurre en el movimiento hacia la derecha. Por ello, en la conocida función move_ip(), el valor que le damos al desplazamiento de la primera coordenada tiene el signo cambiado respecto al ángulo de giro. ¿Qué valor concreto ponemos? Eso ya depende de lo deprisa que quieras que se desplace. Hemos puesto una cantidad en números redondos dividiendo por 10 el giro (así, por poner un caso, cuando el ángulo de es 45 grados, el coche se desplazará horizontalmente a razón de 4 pixeles por fotograma). Recuerda que no hay nada en contra del método de prueba y error; cambia el valor hasta que encuentres uno que te parezca razonable. El resto es simplemente la comprobación habitual para que el sprite no se salga de los límites de la ventana. PÁGINA 3 DE 10 CC: FERNANDO SALAMERO
  • 4. PROGRAMA: DRIVE CURSO: 1º BACHILLERATO Clase Planta Los obstáculos que van apareciendo en el juego son sprites de tipo Planta. Veamos: 1. Para empezar, para dar un poco de variedad, usamos dos diseños distintos de arbusto. Para que el programa elija al azar entre uno de los dos hemos usado un if asociado a random.randint(0,1). Como ya sabes, esta función devuelve un número al azar, en este caso un 0 o un 1. Según cuál sea de los dos (recuerda que un valor cero es equivalente a un False), se utiliza como imagen del sprite una u otra. Fíjate que conseguir que sigan saliendo al azar pero que haya más de un tipo que de otro, también es fácil. Por ejemplo, si se hubiera elegido un número del 0 al 2, en promedio, habría dos veces más de un tipo que del otro (con el valor 0 tendríamos planta2.png y con los valores 1 y 2 planta1.png). Y, por cierto, como ambas imágenes son de tipo png con trasnparencia, llamamos a la función cargarImagen() con el valor True. El otro detalle de la función __init__() es que usa dos parámetros (a parte del obligatorio self). Eso nos permitirá crear la planta en la posición que queramos ya que luego los usamos para posicionar el rect del sprite con topleft. 2. Como las plantas son parte del paisaje, se han de mover con él. En la función update() miramos si el coche está en marcha (en cuyo caso scroll será True) y desplazamos consecuentemente el sprite en la dirección vertical (hacia abajo) la cantidad indicada por VELOCIDAD (exactamente igual que el fondo). Queda un detalle importante. Una vez que la planta pase de largo y salga por la parte inferior de la pantalla no necesitaremos más el sprite. Para que no gaste recursos del ordenador y no se redibuje una y otra vez fuera de la pantalla, conviene eliminarla con self.kill(). Clase Fondo La clase Fondo representa la imagen de la carretera que se va a ir desplazando hacia abajo para dar la sensación de movimiento. El término técnico inglés que se da a este tipo de imágenes es Tiles (algo así como cuadrículas, en español). La imagen no es de tamaño infinito pero debe parecerlo, así que a medida que se termine hay que ir añadiendo a continuación otra imagen o ella misma, dando así la sensación de que la carretera no se acaba nunca. Veremos luego como implementar esto; de momento vamos a ver cómo está definido este tipo especial de objetos (he usado una clase derivada de un sprite, pero hay otras muchas formas de hacerlo). 1. La función __init__() es la misma que la de la clase Planta, incluso más sencilla puesto que tenemos una sola imagen de carretera (de paso vemos que ampliar la definición para tener varias y crear la sensación de que la carretera es siempre distinta no es muy complicado entonces). 2. Respecto a update() hay que adelantar algo. En el juego vamos a usar dos imágenes de carretera, una a continuación de la otra. Para simular que la carretera no se acaba, a medida que una de ellas sale por completo de la pantalla se cambiará su posición de forma que quede justo detrás de la que viene a continuación (como si fuera un rodillo). Así que en update() miramos primero si hay movimiento con un bloque if y la variable booleana de estado scroll y en tal caso se procede a desplazar el sprite. Primero bajamos el sprite el número de pixeles que indica VELOCIDAD. En segundo lugar hay que ver cuando poner el sprite detrás del segundo que vayamos a tener. Piensa que los dos son iguales y tienen por lo tanto la misma altura. Cuando el borde superior del primero llegue abajo el segundo habrá bajado ya esa cantidad, así que hay PÁGINA 4 DE 10 CC: FERNANDO SALAMERO
  • 5. PROGRAMA: DRIVE CURSO: 1º BACHILLERATO que retroceder el sprite su altura menos la altura de la ventana. Así es como deben empalmar: if self.rect.top >= ALTO: self.rect.bottom = ALTO - self.rect.height Cuerpo Principal del Juego Siguiendo el esquema habitual nos encontramos con lo siguiente: 1. Inicializar y cargar sonidos Poco que comentar aquí. El sonido que cargamos en la variable choque lo emplearemos luego cuando el coche colisione con algún arbusto. 2. Crear los Sprites y los Grupos Creamos los dos sprites que se encargarán de simular la carretera interminable. El primero, carretera1, lo situamos en pantalla ocupándola por completo. El segundo, carretera2, lo creamos justo encima. Como en la definición de la clase Carretera los parámetros que se usan para posicionar el sprite son los de la esquina superior izquierda, en este segundo objeto hemos de poner de coordenada vertical la altura del propio sprite (en este caso de carretera1, ya que es igual a carretera2 pero este último ¡todavía no está creado!) cambiada de signo: carretera2 = Carretera(0, -carretera1.rect.height) A continuación creamos el coche del jugador, coche, y añadimos los sprites a los grupos apropiados; los tiles a fondoGrupo y el coche a cocheGrupo. Creamos, así mismo, un grupo inicialmente vacío pero que contendrá los arbustos que vayan apareciendo en el juego al azar, cosasGrupo. 3. Definición de variables de útiles Ha tocado el turno a la definición de las variables de juego (muchas veces también llamadas variables de estado). jugando controla si el juego está activo o ha terminado, por lo que lo emplearemos el el bucle while típico de la animación. scroll ya sabemos que indica si el coche está en marcha o no. intervaloPlantas lo usamos de la misma manera que usamos intervaloEnemigos en el juego de Star Wars; vigila cada cuánto hay que crear un nuevo obstáculo. Igual que la otra vez, eso se realizará cuando llegue a un cierto valor y se ponga a cero la variable para volver a empezar. Finalmente, reloj nos permitirá, de la forma habitual, controlar la velocidad de la animación. 4. Bucle del Juego En el bucle del juego, después de indicar que se va a ejecutar a 60 fotogramas por PÁGINA 5 DE 10 CC: FERNANDO SALAMERO
  • 6. PROGRAMA: DRIVE CURSO: 1º BACHILLERATO segundo, entramos directamente el la lista de eventos. Hay dos situaciones en las que nos fijamos aquí. La primera es el momento de terminar la partida, ya sea al cerrar la ventana o al pulsar la tecla ESC. La segunda es determinar cuando hay que poner el coche en marcha o cuando hay que pararlo. La tecla que se encargará de ello es la de la barra espaciadora (con ella pulsada el motor está en funcionamiento y cuando la dejamos de pulsar el motor se detiene). Nada más sencillo; nos fijamos en los eventos KEYDOWN y KEYUP y si la tecla culpable es K_SPACE y asignamos el valor conveniente a la variable scroll. Para mover el coche sin interferir a la barra espaciadora usamos, también como siempre, la función pygame.key.get_pressed(). El diccionario resultante lo almacenamos en teclasPulsadas y miramos si las teclas del cursor están implicadas, en cuyo caso se procede a girar el coche en la dirección adecuada. Recuerda el convenio de signos con los ángulos; al girar hacia la izquierda hay que aumentar el ángulo (por eso sumamos VELOCIDAD al atributo giro del coche) y hay que restar cuando el giro es hacia la derecha. El código que encontramos luego es el mismo que en Star Wars; se incrementa el contador y si llega a 200 se crea una nueva Planta. Fíjate cómo se ha hecho: cosasGrupo.add( Planta( random.randint(0,ANCHO) , -50 ) ) Al crear el arbusto lo hacemos fuera de la pantalla (50 pixeles por encima) para que aparezca suavemente por el borde superior mientras se mueve. Su coordenada horizontal la generamos al azar en cualquier punto comprendido entre los límites de la ventana. Ya está casi todo hecho. Lo siguiente es llamar a la función update() de todos los grupos para que sitúe a todos los sprites en las nuevas posiciones. Y antes de dibujarlos en pantalla hay que comprobar si hay colisión entre el coche y algún arbusto. El código es casi idéntico que el que usamos en Star Wars. Hay una pequeña diferencia; pygame.sprite.groupcollide( cocheGrupo, cosasGrupo, 0, 1) En el programa anterior, cuando un rayo láser impactaba en una nave, queríamos que desaparecieran los dos sprites. Ahora lo que queremos es que desaparezca el arbusto pero no el coche. Es por eso por lo que en los argumentos encargados de eliminar a los sprites implicados en la colisión ponemos un 0 en el correspondiente al grupo del coche (‘no lo elimines’) y un 1 en el grupo de los arbustos (‘elimínalo’). Hecho el trabajo duro, sólo queda usar draw() con todos los grupos para que dibuje los sprites en sus nuevas posiciones y pygame.display.update() para que se vuelque el fotograma completado en pantalla. Una última cosa; ¿te has fijado que esta vez no hemos borrado los sprites de sus antiguas posiciones? En este caso no hace falta por que, al ocupar el tile de la carretera toda la ventana, cuando se dibuja este primer sprite lo hace por encima de todo lo que hubiera antes. Algo que nos ahorramos. PÁGINA 6 DE 10 CC: FERNANDO SALAMERO
  • 7. PROGRAMA: DRIVE CURSO: 1º BACHILLERATO # -*- coding: utf-8 -*- #------------------------------------------------------------------- # Clon de Drive # (Basado en un script original de Mark Ivey) #------------------------------------------------------------------- import random import os, pygame from pygame.locals import * ANCHO = 800 ALTO = 600 VELOCIDAD = 5 #------------------------------------------------------------------- # Función cargarImagen() # ( Carga una imagen desde un archivo, devolviendo el objeto apropiado) #------------------------------------------------------------------- def cargarImagen( archivo, tieneTransparencia = False ): lugar = os.path.join( "data", archivo ) try: imagen = pygame.image.load( lugar ) except pygame.error, mensaje: print "No puedo cargar la imagen:", lugar raise SystemExit, mensaje if tieneTransparencia: imagen = imagen.convert_alpha() else: imagen = imagen.convert() return imagen #------------------------------------------------------------------- # Función cargarSonido() # ( Carga un sonido desde un archivo, devolviendo el objeto apropiado) #------------------------------------------------------------------- def cargarSonido( archivo ): class sinSonido: def play( self ): pass if not pygame.mixer or not pygame.mixer.get_init(): return sinSonido() PÁGINA 7 DE 10 CC: FERNANDO SALAMERO
  • 8. PROGRAMA: DRIVE CURSO: 1º BACHILLERATO lugar = os.path.join( "data", archivo ) try: sound = pygame.mixer.Sound( lugar ) except pygame.error, message: print "No puedo cargar el sonido:", lugar raise SystemExit, message return sound #------------------------------------------------------------------- # Sprite Coche # (Coche del Jugador) #------------------------------------------------------------------- class Coche( pygame.sprite.Sprite ): def __init__( self ): pygame.sprite.Sprite.__init__( self ) self.imagen_base = cargarImagen( "coche.png", True ) self.image = self.imagen_base self.rect = self.image.get_rect() self.giro = 0 self.rect.center = (550,500) def update( self ): if self.giro >= 45: self.giro = 45 elif self.giro <= -45: self.giro = -45 else: x, y = self.rect.center self.image = pygame.transform.rotate(self.imagen_base, self.giro) self.rect = self.image.get_rect() self.rect.center = x,y if self.giro and scroll: self.rect.move_ip(-self.giro/10,0) if self.rect.left <= 0: self.rect.left = 0 elif self.rect.right >= ANCHO: self.rect.right = ANCHO #------------------------------------------------------------------- # Sprite Planta # (Palntas de la carretera) #------------------------------------------------------------------- class Planta( pygame.sprite.Sprite ): PÁGINA 8 DE 10 CC: FERNANDO SALAMERO
  • 9. PROGRAMA: DRIVE CURSO: 1º BACHILLERATO def __init__( self, posx, posy ): pygame.sprite.Sprite.__init__( self ) if random.randint(0,1): self.image = cargarImagen( "planta1.png", True ) else: self.image = cargarImagen( "planta2.png", True ) self.rect = self.image.get_rect() self.rect.topleft = (posx,posy) def update( self ): if scroll: self.rect.move_ip( 0,VELOCIDAD ) if self.rect.top > ANCHO: self.kill() #------------------------------------------------------------------- # Sprite Fondo # (Carretera) #------------------------------------------------------------------- class Carretera( pygame.sprite.Sprite ): def __init__( self, posx, posy ): pygame.sprite.Sprite.__init__( self ) self.imagen_base = cargarImagen( "carretera.png", False ) self.image = self.imagen_base self.rect = self.image.get_rect() self.rect.topleft = (posx,posy) def update( self ): if scroll: self.rect.move_ip( 0,VELOCIDAD ) if self.rect.top >= ALTO: self.rect.bottom = ALTO - self.rect.height #------------------------------------------------------------------- # Cuerpo Principal del Juego #------------------------------------------------------------------- pygame.init() visor = pygame.display.set_mode( (ANCHO, ALTO) ) pygame.display.set_caption( "Drive" ) choque = cargarSonido( "choque.wav" ) carretera1 = Carretera(0,0) carretera2 = Carretera(0, -carretera1.rect.height) coche = Coche() PÁGINA 9 DE 10 CC: FERNANDO SALAMERO
  • 10. PROGRAMA: DRIVE CURSO: 1º BACHILLERATO fondoGrupo = pygame.sprite.RenderUpdates(carretera1) fondoGrupo.add(carretera2) cocheGrupo = pygame.sprite.RenderUpdates(coche) cosasGrupo = pygame.sprite.RenderUpdates() jugando = True scroll = False intervaloPlantas = 0 reloj = pygame.time.Clock() while jugando: reloj.tick( 60 ) for event in pygame.event.get(): if event.type == QUIT: jugando = False elif event.type == KEYDOWN: if event.key == K_ESCAPE: jugando = False elif event.key == K_SPACE: scroll = True elif event.type == KEYUP: if event.key == K_SPACE: scroll = False teclasPulsadas = pygame.key.get_pressed() if teclasPulsadas[K_LEFT]: coche.giro += VELOCIDAD if teclasPulsadas[K_RIGHT]: coche.giro -= VELOCIDAD intervaloPlantas += 1 if intervaloPlantas >= 100 and scroll: cosasGrupo.add( Planta( random.randint(0,ANCHO) , -50 ) ) intervaloPlantas = 0 fondoGrupo.update() cocheGrupo.update() cosasGrupo.update() for pum in pygame.sprite.groupcollide( cocheGrupo, cosasGrupo, 0, 1): choque.play() fondoGrupo.draw( visor ) cocheGrupo.draw( visor ) cosasGrupo.draw( visor ) pygame.display.update() PÁGINA 10 DE 10 CC: FERNANDO SALAMERO