SlideShare una empresa de Scribd logo
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

PDF
Programación con Pygame V
PDF
Programación con Pygame IV
PDF
Programación con Pygame IX
PDF
Programación con Pygame III
PDF
Programación con Pygame (II)
PDF
Programación con Pygame VIII
PDF
Programación con Pygame I
PDF
Programación de Videojuegos con Python y Pilas (IX)
Programación con Pygame V
Programación con Pygame IV
Programación con Pygame IX
Programación con Pygame III
Programación con Pygame (II)
Programación con Pygame VIII
Programación con Pygame I
Programación de Videojuegos con Python y Pilas (IX)

La actualidad más candente (20)

PDF
Programación de Videojuegos con Python y Pilas (X)
PDF
Programación de Videojuegos con Python y Pilas (VII)
PDF
Introducción a las librerías PyGame y PyOpenGL
PDF
PPT
Intro pygamev2
PDF
Intro PyGame Capitulo 5
PDF
Programación de Videojuegos con Python y Pilas (VIII)
PDF
Intro Pygame Capitulo 2
PDF
Programación de Videojuegos con Python y Pilas (VI)
PDF
Intro PygameCapitulo 3
PDF
Intro PyGame Capitulo 1
PDF
PDF
Intro PyGame Capitulo 0
PDF
Programación de Videojuegos con Python y Pilas (II)
PPTX
Xna game studio presentación 02
PPTX
Xna game studio presentación 01
PDF
Taller de introduccion a python con turtle
DOCX
Ejemplo 18 animación usando gamecanvas
DOC
Vray manual para interiores
PDF
Scratchmini manual 1_
Programación de Videojuegos con Python y Pilas (X)
Programación de Videojuegos con Python y Pilas (VII)
Introducción a las librerías PyGame y PyOpenGL
Intro pygamev2
Intro PyGame Capitulo 5
Programación de Videojuegos con Python y Pilas (VIII)
Intro Pygame Capitulo 2
Programación de Videojuegos con Python y Pilas (VI)
Intro PygameCapitulo 3
Intro PyGame Capitulo 1
Intro PyGame Capitulo 0
Programación de Videojuegos con Python y Pilas (II)
Xna game studio presentación 02
Xna game studio presentación 01
Taller de introduccion a python con turtle
Ejemplo 18 animación usando gamecanvas
Vray manual para interiores
Scratchmini manual 1_
Publicidad

Similar a Programación con Pygame VI (20)

ODP
Desarrollo de videojuegos con software libre
PPT
EXPOSICION PYGAME
DOCX
Carrito de carreras flash copia
PPT
Programas
PPT
Programas
PDF
Manual scratch
PPT
Programas
PPT
TUTORIAL DE ACTIVIDADES EN XO
PDF
Programación con Pygame VII
PPT
TUTORIAL DE ACTIVIDADES EN XO
DOCX
3 sprite
PPTX
Segunda entrega de proyecto
PPTX
Segunda entrega de proyecto
PDF
Scratch bloque por siempre prof. carlos montiel renteria elbragao69
PDF
Guía de programación de videojuegos i
DOCX
Sprite lcelly
ODP
Presentación inicio de scratch
DOCX
PPTX
HTML Tour - Programación de Videojuegos HTML5
PDF
Ejercicio6 videojuego
Desarrollo de videojuegos con software libre
EXPOSICION PYGAME
Carrito de carreras flash copia
Programas
Programas
Manual scratch
Programas
TUTORIAL DE ACTIVIDADES EN XO
Programación con Pygame VII
TUTORIAL DE ACTIVIDADES EN XO
3 sprite
Segunda entrega de proyecto
Segunda entrega de proyecto
Scratch bloque por siempre prof. carlos montiel renteria elbragao69
Guía de programación de videojuegos i
Sprite lcelly
Presentación inicio de scratch
HTML Tour - Programación de Videojuegos HTML5
Ejercicio6 videojuego
Publicidad

Más de Fernando Salamero (20)

PDF
En la orilla del océano cósmico. Siglo XX.
PDF
El tejido del cosmos. Ciclo Estival de Astronomía.
PDF
Astronomía y Matemáticas para Principiantes .pdf
PDF
Ciencia y Revolución .Pensando las revoluciones.
PDF
Gravedad y Ondas Gravitacionales - Fernando Salamero
PDF
(Anotaciones) Ciencia (Cuestiones) que la tiza no propone
PDF
Ciencia (Cuestiones) que la tiza no propone
PDF
(Sin anotaciones) - En busca de la Física
PDF
(Con anotaciones) En busca de la Física
PDF
Timeline - En busca de la Física
PDF
Jovenes físicos
PDF
Taller de Pilas Engine, un motor de juegos en Python - PyConES 2014
PDF
Programación de Videojuegos con Python y Pilas (I)
PDF
Programación de Videojuegos con Python y Pilas (V)
PDF
Programación de Videojuegos con Python y Pilas (III)
PDF
Python básico II
PDF
Python básico I
PDF
Python (ejercicios)
PDF
Python (práctica 4)
PDF
Python (práctica 3)
En la orilla del océano cósmico. Siglo XX.
El tejido del cosmos. Ciclo Estival de Astronomía.
Astronomía y Matemáticas para Principiantes .pdf
Ciencia y Revolución .Pensando las revoluciones.
Gravedad y Ondas Gravitacionales - Fernando Salamero
(Anotaciones) Ciencia (Cuestiones) que la tiza no propone
Ciencia (Cuestiones) que la tiza no propone
(Sin anotaciones) - En busca de la Física
(Con anotaciones) En busca de la Física
Timeline - En busca de la Física
Jovenes físicos
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 (V)
Programación de Videojuegos con Python y Pilas (III)
Python básico II
Python básico I
Python (ejercicios)
Python (práctica 4)
Python (práctica 3)

Último (20)

PDF
ACERTIJO Súper Círculo y la clave contra el Malvado Señor de las Formas. Por ...
PDF
el - LIBRO-PACTO-EDUCATIVO-GLOBAL-OIEC.pdf
PDF
Romper el Circulo de la Creatividad - Colleen Hoover Ccesa007.pdf
PDF
Integrando la Inteligencia Artificial Generativa (IAG) en el Aula
DOCX
2 GRADO UNIDAD 5 - 2025.docx para primaria
DOCX
III Ciclo _ Plan Anual 2025.docx PARA ESTUDIANTES DE PRIMARIA
PDF
Híper Mega Repaso Histológico Bloque 3.pdf
PDF
COMPLETO__PROYECTO_VIVAN LOS NIÑOS Y SUS DERECHOS_EDUCADORASSOS.pdf
DOCX
PROYECTO DE APRENDIZAJE para la semana de fiestas patrias
PDF
Atencion prenatal. Ginecologia y obsetricia
DOCX
V UNIDAD - PRIMER GRADO. del mes de agosto
PPTX
Presentación de la Cetoacidosis diabetica.pptx
PDF
Fundamentos_Educacion_a_Distancia_ABC.pdf
PDF
TOMO II - LITERATURA.pd plusenmas ultras
PDF
ciencias-1.pdf libro cuarto basico niños
PDF
Escuela de Negocios - Robert kiyosaki Ccesa007.pdf
DOCX
V UNIDAD - SEGUNDO GRADO. del mes de agosto
PDF
Educación Artística y Desarrollo Humano - Howard Gardner Ccesa007.pdf
PDF
Unidad de Aprendizaje 5 de Educacion para el Trabajo EPT Ccesa007.pdf
PDF
Punto Critico - Brian Tracy Ccesa007.pdf
ACERTIJO Súper Círculo y la clave contra el Malvado Señor de las Formas. Por ...
el - LIBRO-PACTO-EDUCATIVO-GLOBAL-OIEC.pdf
Romper el Circulo de la Creatividad - Colleen Hoover Ccesa007.pdf
Integrando la Inteligencia Artificial Generativa (IAG) en el Aula
2 GRADO UNIDAD 5 - 2025.docx para primaria
III Ciclo _ Plan Anual 2025.docx PARA ESTUDIANTES DE PRIMARIA
Híper Mega Repaso Histológico Bloque 3.pdf
COMPLETO__PROYECTO_VIVAN LOS NIÑOS Y SUS DERECHOS_EDUCADORASSOS.pdf
PROYECTO DE APRENDIZAJE para la semana de fiestas patrias
Atencion prenatal. Ginecologia y obsetricia
V UNIDAD - PRIMER GRADO. del mes de agosto
Presentación de la Cetoacidosis diabetica.pptx
Fundamentos_Educacion_a_Distancia_ABC.pdf
TOMO II - LITERATURA.pd plusenmas ultras
ciencias-1.pdf libro cuarto basico niños
Escuela de Negocios - Robert kiyosaki Ccesa007.pdf
V UNIDAD - SEGUNDO GRADO. del mes de agosto
Educación Artística y Desarrollo Humano - Howard Gardner Ccesa007.pdf
Unidad de Aprendizaje 5 de Educacion para el Trabajo EPT Ccesa007.pdf
Punto Critico - Brian Tracy Ccesa007.pdf

Programación con Pygame VI

  • 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