Razón Artificial

La ciencia y el arte de crear videojuegos

Pygame VII: Colisiones

Escrito por adrigm el 14 de febrero de 2010 en Desarrollo Videojuegos, Noticias, Programación | 8 Comentarios.

Tenemos una pelota que se mueve como loca y una pala que va para arriba y para abajo a nuestra voluntad, es hora de que se den cuenta que están en el mismo mundo. Vamos a crear colisiones entre los dos sprites.

Actualizando el método actualizar de la clase Bola

Saber si un Sprite colisiona con otro es muy fácil en Python, basta con ejecutar el siguiente método:

pygame.sprite.collide_rect(objeto1, objeto2)

Esto comprueba si el rectángulo del Sprite objeto1 está en contacto con el rectángulo de objeto2, por lo que es tan fácil como mejorar el método actualizar de la clase Bola para que lo tenga en cuenta:

def actualizar(self, time, pala_jug):
	self.rect.centerx += self.speed[0] * time
	self.rect.centery += self.speed[1] * time
	if self.rect.left <= 0 or self.rect.right >= WIDTH:
		self.speed[0] = -self.speed[0]
		self.rect.centerx += self.speed[0] * time
	if self.rect.top <= 0 or self.rect.bottom >= HEIGHT:
		self.speed[1] = -self.speed[1]
		self.rect.centery += self.speed[1] * time

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

Como vemos todo igual, salvo que ahora recibe un parámetro más que es pala_jug por el que pasaremos el Sprite con el que queremos comprobar si colisiona, en este caso pala_jug.

Luego al final añadimos 3 líneas con un nuevo condicional con el que comprobamos si la pelota choca contra la pala, en caso afirmativo cambiamos la dirección de la bola como cuando choca con el borde izquierdo de la ventana.

Por último solo actualizamos la llamada a la función actualizar que hacemos desde el bucle para pasarle la pala_jug.

bola.actualizar(time, pala_jug)

Y con esto ya hemos logrado que nuestra bola detecte si ha chocado contra la pala del jugador en caso afirmativo “rebota”.

Asi nos queda el código:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Módulos
import sys, pygame
from pygame.locals import *

# Constantes
WIDTH = 640
HEIGHT = 480

# Clases
# ---------------------------------------------------------------------

class Bola(pygame.sprite.Sprite):
	def __init__(self):
		pygame.sprite.Sprite.__init__(self)
		self.image = load_image("images/ball.png", True)
		self.rect = self.image.get_rect()
		self.rect.centerx = WIDTH / 2
		self.rect.centery = HEIGHT / 2
		self.speed = [0.5, -0.5]

	def actualizar(self, time, pala_jug):
		self.rect.centerx += self.speed[0] * time
		self.rect.centery += self.speed[1] * time
		if self.rect.left <= 0 or self.rect.right >= WIDTH:
			self.speed[0] = -self.speed[0]
			self.rect.centerx += self.speed[0] * time
		if self.rect.top <= 0 or self.rect.bottom >= HEIGHT:
			self.speed[1] = -self.speed[1]
			self.rect.centery += self.speed[1] * time

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

class Pala(pygame.sprite.Sprite):
	def __init__(self, x):
		pygame.sprite.Sprite.__init__(self)
		self.image = load_image("images/pala.png")
		self.rect = self.image.get_rect()
		self.rect.centerx = x
		self.rect.centery = HEIGHT / 2
		self.speed = 0.5

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

# ---------------------------------------------------------------------

# Funciones
# ---------------------------------------------------------------------

def load_image(filename, transparent=False):
        try: image = pygame.image.load(filename)
        except pygame.error, message:
                raise SystemExit, message
        image = image.convert()
        if transparent:
                color = image.get_at((0,0))
                image.set_colorkey(color, RLEACCEL)
        return image

# ---------------------------------------------------------------------

def main():
	screen = pygame.display.set_mode((WIDTH, HEIGHT))
	pygame.display.set_caption("Pruebas Pygame")

	background_image = load_image('images/fondo_pong.png')
	bola = Bola()
	pala_jug = Pala(30)

	clock = pygame.time.Clock()

	while True:
		time = clock.tick(60)
		keys = pygame.key.get_pressed()
		for eventos in pygame.event.get():
			if eventos.type == QUIT:
				sys.exit(0)

		bola.actualizar(time, pala_jug)
		pala_jug.mover(time, keys)
		screen.blit(background_image, (0, 0))
		screen.blit(bola.image, bola.rect)
		screen.blit(pala_jug.image, pala_jug.rect)
		pygame.display.flip()
	return 0

if __name__ == '__main__':
	pygame.init()
	main()

En el siguiente tutorial crearemos la pala del jugador de la CPU y la dotaremos de Inteligencia Artificial para que golpee la pelota.

8 Comentarios en "Pygame VII: Colisiones"

  1. jonykalavera dice:

    y donde está el link a pala.png ?? O_o

  2. javier dice:

    Hola Adrian, el tutorial es excelente. Tengo una duda con las colisiones, en el caso de la bola lo que colisiona es todo el rectangulo o solo la parte “no transparente”. No se si me explico, en este caso la bola es pequeña y casi no hay diferencia pero si la bola fuera muy grande se apreciaria la diferencia si la colisión fuera sólo con la bola o con todo el rectangulo del dibujo “bola.png” (por ejemplo para un juego de billar) gracias

  3. Fernando dice:

    ¿A nadie le ha salido este error:
    AttributeError: ‘Bola’ object has no attribute ‘rect’
    justo al llegar a este punto?

    Si es posible, explicarlo.
    A parte de esto, excelente y claro tutorial. da gusto seguirlo.

  4. Javi dice:

    Hola Fernado,
    Creo que ese error puede ser debido a que la clase Bola no esta bien declarada. Mirate que dicha clase herede de pygame.sprite.Sprite ;) Espero que al autor no le moleste :)

    Por cierto, para el autor del blog, que opinas de agregar un parametro al metodo actualizar de la clase bola para no tener que nombrar la variable pala_jug dentro del la clase bola??

    Excelente pagina por cierto, la estoy siguiendo tras terminar un curso de prgramacion en coursera y es justo lo que necesitaba! Gracias!

  5. Ezequiel Canseco dice:

    porque la pala se atora justo al tocar la parte superior de la pantalla y la pelota se queda rebotando solo de arriba para abajo ?

Deja un comentario