Razón Artificial

La ciencia y el arte de crear videojuegos

Pygame IV: Creando Sprites

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

La parte 1, parte 2 y parte 3 nos sirvieron como introducción a Pygame, aprendimos a iniciar pygame, crear ventanas y poner imágenes. con ello creamos una plantilla básica desde la que trabajar con Pygame.

Ahora empieza lo divertido, vamos a crear nuestro primer juego, y como no será un clon del clásico Pong. Lo primero que necesitamos es hacer una copia de nuestra plantilla creada en los anteriores tutoriales y guardarla con el nombre pong.py que será sobre el archivo que trabajaremos. Lo primero que haremos será descargar este fondo, mucho más apropiado y guardarlo en la carpeta images de nuestro directorio base.

Recordad cambiar el nombre de la imagen en el programa.

background_image = load_image('images/fondo_pong.png')

La clase Bola

Para crear la pelota de nuestro Pong lo primero que necesitamos es la imagen de la pelota, descargar esta y guardarla como siempre en el directorio images.

Ahora vamos a crear una clase para la pelota, que será el Sprite de nuestra pelota, un Sprite es más que una imagen, es una superficie que puede interactuar, moverse y demás.

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]

La línea 1 crea la clase Bola 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 el método __init__ que inicializa la clase.

La línea 3 invoca al método init de la clase heredada, muy importante también y difícil de explicar para comenzar.

La línea 4 ya nos suena más y lo que hace es cargar con nuestra función load_image() 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

Aquí hago un inciso para comentar que get_rect() tiene unos parámetros muy útiles que podemos modificar para posicionar y redimensionar nuestra imagen, 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. Aquí lo tenéis mejor expliado.

En la línea 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. (aquí vemos porque pusimos WIDTH y HEIGHT como constantes globales).

La línea 8 define la velocidad que queremos para la pelota, separamos la velocidad en dos, la velocidad en el eje x y la velocidad en el eje y, luego veremos porqué.

Poniendo una Bola en nuestro juego

Bien una vez creada la clase Bola vamos a crear una bola, para ello como cuando cargamos el fondo, debemos cargarla antes del bucle del juego, con la siguiente línea:

bola = Bola()

Ahora solo debemos “ponerla” en nuestra ventana, ejecutando la siguiente sentencia, después de la sentencia idéntica a la del fondo.

screen.blit(bola.image, bola.rect)

Como puedes ver ahora no le pasamos la imagen y en vez de unas coordenadas como en el fondo (entonces le pasamos (0, 0)) le pasamos el rect de la bola, con esto conseguiremos más tarde que cada vez que movamos el rect, moveremos la pelota de sitio.

Es muy importante “ponerla en pantalla después y no antes que el fondo porque si pones la pelota y luego pones el fondo encima esta no se verá, como es lógico.

El programa nos queda así:

#!/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]

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

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

	while True:
		for eventos in pygame.event.get():
			if eventos.type == QUIT:
				sys.exit(0)

		screen.blit(background_image, (0, 0))
		screen.blit(bola.image, bola.rect)
		pygame.display.flip()
	return 0

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

Ahora tenemos una pelota en el centro de nuestra pantalla lo siguiente es conseguir que se mueva e interactúe con los bordes. Todo eso en el próximo tutorial.

26 Comentarios en "Pygame IV: Creando Sprites"

  1. Chihau dice:

    Tengo una corrección,

    En la línea que indicas que hay que agregar

    ball = Ball()

    debería ser

    bola = Bola()

    lo mismo en

    screen.blit(ball.image, ball.rect)

    debería ser

    screen.blit(bola.image, bola.rect)

    en el código del programa completo está bien.

  2. admin dice:

    Chihau, cierto muchas gracias, en seguida corrijo.

    La razón de eso es que el juego primero lo programe yo entero con las variables en inglés y luego lo fui montando poco a poco en otro archivo para hacer el tutorial y en este decidí poner las variables en español para mayos compresión, pero a la hora de pones el código se me paso por lo que veo.

  3. isbelys dice:

    hola como estas soy de venezuela, es muy bueno el tutorial, pero apenas comienzo a entender y no se como realizar un funcion en donde las imagenes de los jugadores chuteen la pelota y esta pase a otro jugador si es posible que me expliques te agradeceria

  4. Triff dice:

    Muchas gracias por tu trabajo!! No sabría como empezar a meterle mano a esto si no fuera por este magnifico tutorial!!

  5. nax dice:

    algo a lo que haces mucho incapié es en el orden de los blit.
    Sin embargo estoy creando un juego de pruebas y lo hago en este orden:
    1. fondo 2. fichas 3. recuadro
    el recuadro es un cuadrado rojo simple que se pone en la casilla donde ahcemos clic…

    el code es este:

        fondo = load_image("img/tablero.png")
        cuadro = load_image("img/cuadro.png", True)
        fichas = (Ficha(plot((4,4)), BLANCA), Ficha(plot((4,5)), NEGRA),
                  Ficha(plot((5,4)), NEGRA), Ficha(plot((5,5)), BLANCA))
        while True:
            
            screen.blit(fondo, (0,0))
            #mostramos la matriz de fichas:
            for ficha in fichas:
                screen.blit(ficha.image, ficha.rect)
            
            for eventos in pygame.event.get():
                if eventos.type == QUIT:
                    sys.exit(0)
                if eventos.type == MOUSEBUTTONDOWN:
                    screen.blit(cuadro, plot(mouseMap(pygame.mouse.get_pos()))) #esto no va :|
            pygame.display.flip()
        return 0
    

    y el problema es que la capa del blit cuadro se hace debajo de la capa del fondo y las fichas, que razón hay para ello si he puesto la sentencia en la última posición?

    plot y mouseMap son las funciones para el plottering y el mouse mapping, ficha es una clase.

    Si te ayuda a situarte.. el juego es el reversi (u Othello) la cuestión no está tanto en que esté mal programado sino que no me situa la capa donde (bajo mi teoria) debería que es arriba de todo.

    grácias de antemano por la respuesta ;)

  6. nax dice:

    bueno.. me respondo a mi mismo…

    nose porque es el error pero me cree una clase para evitarme el problema de borrar la imagen y volverla a crear..

    saludos y gracias por los grandes tutoriales

  7. Ale dice:

    Va genial….sigo a pie los ejerc. No soy programador exper… :(. Mas diseñador gráfico (dcv-unlP). Felicitaciones por el trabajo
    saludos

  8. Hes dice:

    Hola! En Primer lugar gracias por tu tutorial, ¡És muy útil!

    Aún así me sale un problema cuando lo ejecuto:

    Traceback (most recent call last):
    File “C:\Documents and Settings\Josh\Escritorio\Scripts\Pygame\Pong\pong.py”, line 53, in
    main()
    File “C:\Documents and Settings\Josh\Escritorio\Scripts\Pygame\Pong\pong.py”, line 40, in main
    bola = Bola()
    File “C:\Documents and Settings\Josh\Escritorio\Scripts\Pygame\Pong\pong.py”, line 17, in __init__
    self.image = load_image(‘ball.png’, True)
    File “C:\Documents and Settings\Josh\Escritorio\Scripts\Pygame\Pong\pong.py”, line 33, in load_image
    image.set_colorkey(color, RLEACCEL)
    NameError: global name ‘RLEACCEL’ is not defined

    Creo que se debe a la variable “bola” o és un problema de identación? ¿Podéis ayudarme en ello porfavor?

  9. Fernando dice:

    Saludos y agradecimientos Adrian, por compartir tus tutoriales. Estoy comenzando con python y googleando en la sección de juegos para python encontré tu web, que por cierto, me ha sido muy útil, ya que como estoy empezando solo quería ver algo básico, pero la verdad es que en español cuesta más encontrar información que sea realmente buena(bien explicada, detallada y con una escritura clara). Ojalá la red estuviera llena de tutos así….. Saludos nuevamente desde Córdoba.

  10. Isaac dice:

    Saludos y gracias, tus tutoriales ayudan mucho.He hecho varios scripts de Python, pero los scripts con las librerias de Pygame son muy utiles.Gracias
    visita mi web http://code.google.com/p/l-full/

  11. andres dice:

    a mi me sale este error porque sera ?
    Traceback (most recent call last):
    File “C:\Users\ andres\Desktop\ proyecto\pong pygame\pong.py”, line 55, in
    main()
    File “C:\Users\ andres\Desktop\ proyecto\pong pygame\pong.py”, line 41, in main
    bola = Bola ()
    File “C:\Users\andres\Desktop\ proyecto\pong pygame\pong.py”, line 14, in __init__
    self.image = load_image(“images/pelotica.png”, True)
    File “C:\Users\andres\Desktop\proyecto\pong pygame\pong.py”, line 26, in load_image
    except (pygame.error, message):
    NameError: global name ‘message’ is not defined

  12. Tincho dice:

    Me aparece “no subprocess”. Alguna sugerencia? Uso Python 2.5

  13. […] Pygame IV: Creando Sprites […]

  14. Matias dice:

    Una pregunta :3
    ¿PyGame tiene algún limite de resolución que aplique a los sprites?

    ¡Saludos!

  15. Neider Puentes dice:

    hay un problema con el codigo no se si solo es mio pero cuando intento meter la segunda imagen me la coloca con un coo grisaceo tube que cambiar la lectura de la imagen con esta linea
    pygame.image.load(“Image/Bloo.png”)
    tal vez sea solo mio de todas formas gracias!! buen codigo

  16. willyrex dice:

    Ah vale vale, gracias

  17. willyrex2 dice:

    Estas?

  18. willyrex2 dice:

    sal de tu perfil

  19. rfe4r dice:

    he salido de atne

  20. rfe4r dice:

    fast que esto se avcaba en 4

  21. rfe4r dice:

    tell something if ok

  22. La verdad, esplicas muy claro todo, ojalá puedas hacer mas tutos de pygame saludos!

Deja un comentario