Pygame V: Moviendo Sprite
En el siguiente tutorial aprenderemos a mover nuestra pelota por la ventana y hacer que rebote contra los bordes, Usaremos física y matemáticas básicas para mover la pelota.
El método actualizar
Para mover la pelota crearemos un metodo llamado actualizar dentro de la clase Bola que controle el movimiento de la pelota y si choca contra los bordes de la ventana, el método es el 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 >= 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
La linea 1 define el método, recibe el parámetro self (como siempre) y el parámetro time que es el tiempo transcurrido, más adelante lo explicamos.
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 (WIDTH), 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.
Creando un reloj
Ahora vamos a crear un reloj que controle el tiempo del juego, esto es importante para el movimiento, pues sabemos cuanto tiempo a pasado desde la ultima actualización de la pelota y con ello poder situarla en el espacio.
clock = pygame.time.Clock()
Esta línea va justo antes de entrar en el bucle del juego y sirve para crear el reloj con el que gestionar el tiempo.
Ahora necesitamos saber cuanto tiempo pasa cada vez que se ejecuta una interección del bucle, para ello dentro del bucle ponemos como primera línea:
time = clock.tick(60)
El 60 que se le pasa como parámetro es el framerate, con él nos aseguramos de que el juego no va a más de la velocidad estipulada. Con ello conseguimos que el juego corra igual en todos los ordenadores. Aquí más inftomación.
Por último debemos actualizar la posición de la bola antes de actualizarla en la ventana, es decir antes de los screen.blit.
bola.actualizar(time)
Como ves le pasamos el parametro time que es el tiempo que ha pasado desde la última vez que se ejecuto.
El juego 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]
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 >= 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
# ---------------------------------------------------------------------
# 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()
clock = pygame.time.Clock()
while True:
time = clock.tick(60)
for eventos in pygame.event.get():
if eventos.type == QUIT:
sys.exit(0)
bola.actualizar(time)
screen.blit(background_image, (0, 0))
screen.blit(bola.image, bola.rect)
pygame.display.flip()
return 0
if __name__ == '__main__':
pygame.init()
main()
Ya nuestra pelota se mueve y rebota contra las paredes. En el próximo tutorial crearemos el Sprite pala y aprenderemos a moverlo con el teclado.
5 Comentarios
Primero de todo felicitarte por el gran trabajo. Yo ya soy un “veterano” de la informática y creo recordar que en los tiempos del ZXspectrum, cuando se trabajaba con Sprites, en lugar de dibujar el fondo (sería muy lento) y a continuación el “personaje”, lo que se hacía era:
1- se guardaba la zona del fondo donde se va a “machacar” encima el personaje. Por ejemplo en la variable “temp”.
2- se colocaba el personaje. Si este se movía:
3- se colocaba “temp” en su lugar, borrando el personaje y dejando el fondo como estaba. Y se volvía a guardar en “temp” la siguiente zona donde se iba a colocar el personaje.
4- se colocaba el personaje y así repetidamente.
¿Se puede hacer esto mismo en pygame o sería más lento?
Miguel, en esencia ahora es lo mismo, tu tienes el fondo guardado en un array y metes el personaje encima en una posición, luego si mueves el personaje, vuelves a recolocar el fondo y pintas al personaje encima.
De hecho estoy haciendo ahora un motor de un rpg en pygame con ese estilo, pronto publicaré algo del tema en el blog.
Muy agradecido por tu excelente tutorial. He aprendido en horas lo que no pude en días. Gracias por tu esfuerzo.
Kike
Heres grande !! xD
bueno dejando las bromas se agradece mucho el esfuerzo, la verdad tengo unos pocos dias que empece a programar con python (pyton para los cuates xD) y ya medio lo voy entendiendo.
por sierto, yo quiero trabajar tambien en un RPG pero tactico.
Saludos
PD: olvide mecionar, ya tengo unos añitos programando con C#, visual Net, Gambas y quiero aprender C o C++ para luego ahi hacer mis Engines
Saludos