Mostrando entradas con la etiqueta actualizar. Mostrar todas las entradas
Mostrando entradas con la etiqueta actualizar. Mostrar todas las entradas

domingo, 6 de mayo de 2012

Comportamiento de IA y Sistema de Puntuación - Pygame

Hola gente, hoy les voy a mostrar como hacer que podamos jugar contra la PC en nuetro juego de Pong, lo cual, es bastante sencillo.

Crear una pala para la PC

Antes que nada, tenemos que crear otra "raqueta", para esto primeramente debemos colocar en nuestro codigo:
 raq_pc = Raqueta(640 - 30)

En el anterior post le dimos a raq_jug el valor 30 porque, queriamos que estuviera a 30 pixeles de el lado izquierdo de la pantalla, ahora lo que hacemos, es que este a 30 pixeles del lado derecho la pantalla.

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

Con esto, ya tenemos listo nuestro sprite para la pc. Lo siguiente ahora, es hacer tambien detecte las colisiones, para ello debemos volver a actualizar nuestra funcion actualizar.

def actualizar(self, time, raq_jug, raq_pc):
 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
        if pygame.sprite.collide_rect(self, raq_pc):
                self.speed[0] = -self.speed[0]
                self.rect.centerx += self.speed[0] * time

Ahora le agregamos raq_pc y le agregamos la misma condicion que raq_jug para verificar si ha colisionado con la pelota.

Recuerden pasarle el parametro nuevo a la línea que llama a la función actualizar de la pelota en el bucle del juego. Así:

pelota.actualizar(time, raq_jug, raq_pc)

Dandole "inteligencia" a la raqueta de la PC

Ahora viene lo nuevo, vamos a darle un comportamiento a la raqueta de la pc para que podamos jugar contra ella. Para ello, crearemos la funcion ia (inteligencia artificial)

def ia(self, time, pelota):
    if pelota.speed[0] >= 0 and pelota.rect.centerx >= 640/2:
        if self.rect.centery < pelota.rect.centery:
            self.rect.centery += self.speed * time
        if self.rect.centery > pelota.rect.centery:
            self.rect.centery -= self.speed * time

En la línea 1 vemos que recibe como siempre self y time y aparte recibe pelota que es la pelota (duh), pero es necesario porque la funcion necesita conocer donde está la pelota.

En la línea 2 comprobamos que pelota.speed[0] >= 0, es decir, que la velocidad en el eje x de la pelota sea positiva, es decir, que la pelota se este moviendo hacia la derecha (hacia la rqueta de la pc) y tambien comprueba que pelota.rect.centerx >= 640/2 es decir que el centro x de la pelota sea mayor o igual que el centro del tablero, es decir, que la pelota este en el campo de la cpu.
Por tanto la línea 2 es un condicional que comprueba que la pelota vaya hacia donde está la raqueta de la cpu y que este en su campo, sino, que no se mueva. Esto se hace para que la PC no sea invencible y no llegue a todas las pelotas.

La línea 3 comprueba si el centery de la pelota es menor que el centery de la raqueta, es decir si la raqueta está más arriba que que la pelota en cullo caso, ejecuta la línea 4 que mueve la pala de la cpu hacia abajo.

Las líneas 5 y 6 hacen lo mismo, pero a la inversa como se ve a simple vista.

Ahora solo hay que llamar a la ia junto con las llamadas actualizar de la pelota y mover de la raqueta de la cpu.

raq_pc.ia(time, pelota)

Con esto, el juego se vuelve jugable, pero no contamos ni con sistema de puntuacion, ni con sonidos, asi que...

Sistema de Puntuacion


en la proxima entrada ;D







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