Mostrando entradas con la etiqueta clase. Mostrar todas las entradas
Mostrando entradas con la etiqueta clase. 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







viernes, 4 de mayo de 2012

Colocando sprites y darles movimiento - Pygame

Hola gente, hoy les voy a mostrar como colocar un sprite en la pantalla, posicionarlo, y darle movimiento.

Vamos a apuntar hacia hacer un juego simple, el clasico pong, y utilizaremos el codigo de mi anterior post, pero cambiaremos el fondo, colocandole uno mas apropiado, yo utilizare la siguiente imagen:


y para la pelota esta imagen:




ok, entonces tenemos nuestras imagenes (no se olviden de ponerlas en la carpeta del juego y cambiarle el nombre al fondo en el codigo).

La clase pelota

Lo siguiente es crear una clase que contenga la pelota y sus propiedades de sprite:

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.5, -0.5]

La línea 1 crea la clase pelota que hereda los métodos de la clase pygame.sprite.Sprite, esto es muy importante debido a que contiene métodos necesarios para el manejo de Sprites.

La línea 2 crea la funcion (o metodo)  __init__ que inicializa la clase.

La línea 3 invoca a la funcion init de la clase heredada, muy importante también y difícil de explicar.

La línea 4 ya nos suena más y lo que hace es cargar con nuestra función cargar_imagen() la imagen de la pelota, como vemos tenemos puesto True porque la pelota si tiene zonas transparentes.

La línea 5 es de las cosas más útiles de pygame, la función self.image.get_rect() obtiene un rectangulo con las dimensiones y posición de la imagen (en este caso self.image) y se lo asignamos a self.rect

Aqui quiero comentar sobre los parametros utiles con los que cuenta get_rect(), ellos son los siguientes:
  • top, left, bottom, right
  • topleft, bottomleft, topright, bottomright
  • midtop, midleft, midbottom, midright
  • center, centerx, centery
  • size, width, height
  • w, h
Así que podemos acceder a los diferentes valores como self.rect.centerx que nos devuelve la posición central de la pelota respecto al ancho de la pantalla, y así con todos es cuestión de probarlos, pero más o menos se entiende lo que devuelve cada uno. Lo mejor de todos ellos es que si cambias el valor de alguno el resto se actualiza.

Volviendo al codigo, en la linea 6 y 7 usamos las propiedades de rect y con centerx y centery definimos el centro de la pelota en el centro de la pantalla.

La linea 8 define la velocidad que queremos para la pelota, separamos la velocidad en dos, para los ejes x y, luego veremos porque.


Colocando la pelota en la ventana

Ya que tenemos una clase creada para la pelota, vamos a crear la pelota

pelota = Pelota()
Ahora solo tenemos que "pegarla" en nuestra ventana con el siguiente comando

pantalla.blit(pelota.imagen, pelota.rect)
Como se puede ver no le pasamos la imagen ahora, y en vez de unas coordenadas como con el fondo, le pasamos el rect de la pelota, con esto conseguiremos que cada vez que movamos el rect, moveremos la pelota.

Es muy importante "ponerla en pantalla despues que el fondo" porque si primero colocamos la pelota y luego el fondo, esta no se veria porque quedaria detras del fondo.

Con esto, ya tenemos a nuestra pelota colocada encima de nuestro fondo, pero todo esta estatico.
Para cambiar eso, le agregaremos movimiento

El metodo actualizar

Para mover la pelota, crearemos un metodo llamado actualizar dentro de la clase Pelota, y esto controlara el movimiento de la pelota, y si choca contra los bordes de la ventana.
La funcion es la siguiente:
def actualizar(self, time):
 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

La linea 1 define el método, recibe el parámetro self (como siempre) y el parámetro time que es el tiempo transcurrido.

La línea 2 y 3 usa la física básica de espacio es igual a la velocidad por el tiempo (e = v*t), por tanto establecemos que el centro de nuestro rectangulo en x es el valor que tenía (self.rect.centerx) más (+=) la valocidad a la que se mueve en el eje x (self.speed[0]) por (*) el tiempo transcurrido (time). Lo mismo se aplica al eje y en la línea 3.

La linea 4, 5 y 6 establece que si la parte izquierda del rectángulo de la bola es menor o igual a 0 ó mayor o igual a el ancho de la pantalla, es decir,  que este en el extremo izquierdo o derecho, la velocidad de x (self.speed[0]) cambie de signo (-self.speed[0]) con esto conseguiremos que vaya hacia el otro lado.

Las líneas 7, 8 y 9 es lo mismo pero en el eje y como se puede ver.

Debemos actualizar la posicion de la pelota a medida que transcurre el juego, esto es simple, solo basta con poner

pelota.actualizar(time)

Entonces, ahora nuestro codigo 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.5, -0.5]
 def actualizar(self, time):
  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



#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()

#Bucle principal del juego
while 1:
 time = reloj.tick(60)
 pelota.actualizar(time)
 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)
 pygame.display.flip()

Y listo!  ahora ya tenemos una pelota que se mueve por la pantalla :) , en los proximos tutoriales iremos completando este juego.