sábado, 5 de mayo de 2012

Control del teclado y Colisiones - Pygame

Hola gente, hoy les voy a mostrar como revisar la entrada del teclado para usarla en el juego y tambien estaremos revisando las colisiones.

Continuaremos haciendo nuestro juego Pong, y lo que vamos a controlar por teclado, van a ser las "raquetas" del juego. para ello, crearemos la clase para ella y haremos su sprite:

 class Raqueta(pygame.sprite.Sprite):
     def __init__(self, x):
           pygame.sprite.Sprite.__init__(self)
           self.imagen = cargar_imagen("datos/raqueta.png")
           self.rect = self.imagen.get_rect()
           self.rect.centerx = x
           self.rect.centery = 480 / 2
           self.speed = 0.5

Para la imagen voy a usar esta.
Como vemos en el codigo, es igualito a la de la pelota, pero ahora le pasamos x en vez de 640 / 2 , esto es para que podamos variar la altura de la raqueta, y para que mas tarde coloquemos a que distancia de la pared izquerda este, y el otro cambio, es que solo le pasamos un valor para speed porque solo se movera por el eje x.

Para crear la raqueta, ya saben como es:

 raq_jug = Raqueta(30)
 
Vamos a hacer que se pueda jugar contra la pc, por eso le puse raq_jug, porque despues voy a poner raq_cpu, y le pase el parametro 30 (que va a ir como valor de x), para que este a una distancia de 30 px del borde derecho de la ventana.

Por ultimo, dentro del bucle, lo de siempre, despues de actualizar el fondo y la pelota, actualizamos la raqueta

 pantalla.blit(raq_jug.imagen, raq_jug.rect)


Moviendo la Raqueta

Para controlar la raqueta, definiremos la funcion mover dentro de la clase Raqueta:

 def mover(self, time, teclas):
     if self.rect.top >= 0:
         if teclas[K_UP]:
             self.rect.centery -= self.speed * time
     if self.rect.bottom <= 480:
         if teclas[K_DOWN]:
             self.rect.centery += self.speed * time

Esta funcion, hereda los parametros self y time como la funcion actualizar de la pelota, y tambien recibe el parametro teclas, que luego definiremos, y que sera una lista con el valor de las teclas pulsadas.

La línea 2 y 5 comprueban que la raqueta no se salga de la ventana.

La línea 3 comprueba si la constante K_UP de keys es 1, lo que querría decir que tenemos presionada la tecla de la flecha hacia arriba del teclado.

La línea 5 en caso de tener la tecla presionada disminuye el valor de centery haciendo que la raqueta se mueva hacia arriba.

La línea 6 y 7 hacen lo mismo, pero para abajo y aumentando el valor de centery.

Ahora solo tenemos que saber que teclas se estan pulsando, creando la variable teclas, esto se hace de la siguiente forma (despues de comprobar el tiempo transcurrido con time)

 teclas = pygame.key.get_pressed()

Esto nos devuelve las teclas pulsadas en una lista.

Por ultimo, debemos llamar a la funcion mover en el bucle, justo despues de actualizar la pelota, con la linea:

 raq_jug.mover(time, teclas)

Bien, entonces, si ejecutan su programa ahora, lo que van a tener, es una pala moviendose de arriba a abajo y una pelota que la atravieza, pero no se preocupen, ahora vamos a controlar la colision.

Actualizando la funcion actualizar de la clase Pelota

Para saber si un sprite choca con otro es facil, solo hay que ejecutar la funcion:

 pygame.sprite.collide_rect(objeto1, objeto2)

Esto comprueba si el rectangulo del Sprite objeto1 esta colisionando con el rectangulo de objeto 2,
entonces, solo basta con agregarle una condicional a la funcion actualizar (y tambien le decimos que herede de raq_jug) dentro de la clase pelota:

 if pygame.sprite.collide_rect(self, raq_jug):
     self.speed[0] = -self.speed[0]
     self.rect.centerx += self.speed[0] * time

Como vemos, hacemos que cuando la pelota "choque" con la pala, esta cambie de direccion/
No tenemos que olvidarnos de agregarle el parametro raq_jug cuando llamamos la funcion, raqueta.actualizar(time, raq_jug)
y con esto, ya logramos que la pelota choque contra la raqueta y que valla hacia el otro lado.
El código, nos quedaria asi:

#importamos librerias
import pygame
from pygame.locals import *

#iniciamos pygame
pygame.init()

#definimos constantes
pantalla = pygame.display.set_mode((640, 480))
pygame.display.set_caption('Titulo de ventana')

reloj = pygame.time.Clock()

#definimos clases
class Pelota(pygame.sprite.Sprite):
 def __init__(self):
  pygame.sprite.Sprite.__init__(self)
  self.imagen = cargar_imagen("datos/pelota.png", True)
  self.rect = self.imagen.get_rect()
  self.rect.centerx = 640 / 2
  self.rect.centery = 480 / 2
  self.speed = [0.2, -0.2]
 def actualizar(self, time, raq_jug):
  self.rect.centerx += self.speed[0] * time
  self.rect.centery += self.speed[1] * time
  if self.rect.left <= 0 or self.rect.right >= 640:
   self.speed[0] = -self.speed[0]
   self.rect.centerx += self.speed[0] * time
  if self.rect.top <= 0 or self.rect.bottom >= 480:
   self.speed[1] = -self.speed[1]
   self.rect.centery += self.speed[1] * time
  if pygame.sprite.collide_rect(self, raq_jug):
   self.speed[0] = -self.speed[0]
   self.rect.centerx += self.speed[0] * time


class Raqueta(pygame.sprite.Sprite):
 def __init__(self, x):
  pygame.sprite.Sprite.__init__(self)
  self.imagen = cargar_imagen("datos/raqueta.png")   
                self.rect = self.imagen.get_rect()
  self.rect.centerx = x
  self.rect.centery = 480 / 2
  self.speed = 0.5
 def mover(self, time, teclas):
  if self.rect.top >= 0:
   if teclas[K_UP]:
    self.rect.centery -= self.speed * time
  if self.rect.bottom <= 480:
   if teclas[K_DOWN]:
    self.rect.centery += self.speed * time



#definimos funciones
def cargar_imagen(nombre,transparente=False):
     try: imagen = pygame.image.load(nombre)

     except pygame.error, message:
          raise SystemExit, message
     imagen = imagen.convert()
     if transparente:
          color = imagen.get_at((0,0))
          imagen.set_colorkey(color, RLEACCEL)
     return imagen
  
fondo = cargar_imagen('datos/fondo.png')
pelota = Pelota()
raq_jug = Raqueta(30)
 
#Bucle principal del juego
while 1:
 time = reloj.tick(200)
 pelota.actualizar(time, raq_jug)
 teclas = pygame.key.get_pressed()
 raq_jug.mover(time, teclas)
 
 for event in pygame.event.get():
  if event.type == QUIT:
   pygame.quit()
   sys.exit()
  elif event.type == KEYDOWN:
   if event.type == K_ESCAPE:
    pygame.quit()
    sys.exit()
 pantalla.blit(fondo, (0, 0)) 
 pantalla.blit(pelota.imagen, pelota.rect)
 pantalla.blit(raq_jug.imagen, raq_jug.rect)
 pygame.display.flip()

Mañana le agregaremos raq_cpu para que podamos jugar contra la pc :D

No hay comentarios:

Publicar un comentario