Esta es una introducción a Pygame para personas que ya conocen Python. Este artículo le enseñará los pasos para construir un juego simple en el que el jugador esquiva pelotas que rebotan.
Pasos
Parte 1 de 8: Instalación de Pygame
Paso 1. Descarga Pygame
Encuéntrelo para su plataforma en
Paso 2. Ejecute el instalador
Paso 3. Verifique que la instalación haya funcionado
Abra una terminal de Python. Escribe "importar pygame". Si no ve ningún error, Pygame se instaló correctamente.
importar pygame
Parte 2 de 8: Configuración de una ventana básica
Paso 1. Abra un archivo nuevo
Paso 2. Importa Pygame
Pygame es una biblioteca que brinda acceso a funciones gráficas. Si desea obtener más información sobre cómo funcionan estas funciones, puede buscarlas en el sitio web de Pygame.
importar pygame desde pygame.locals import *
Paso 3. Configure la resolución de la ventana
Harás una variable global para la resolución de la pantalla, de modo que se pueda hacer referencia a ella en varias partes del juego. También es fácil de encontrar en la parte superior del archivo para poder cambiarlo más tarde. Para proyectos avanzados, poner esta información en un archivo separado sería una mejor idea.
resolución = (400, 300)
Paso 4. Defina algunos colores
Los colores en pygame son (RBGA que varían en valores entre 0 y 255. El valor alfa (A) es opcional pero los otros colores (rojo, azul y verde son obligatorios).
blanco = (255, 255, 255) negro = (0, 0, 0) rojo = (255, 0, 0)
Paso 5. Inicialice la pantalla
Utilice la variable de resolución que se definió anteriormente.
screen = pygame.display.set_mode (resolución)
Paso 6. Haz un bucle de juego
Repite ciertas acciones en cada fotograma de nuestro juego. Haga un bucle que siempre se repetirá para recorrer todas estas acciones.
mientras que es cierto:
Paso 7. Colorea la pantalla
screen.fill (blanco)
Paso 8. Visualice la pantalla
Si ejecuta el programa, la pantalla se volverá blanca y luego el programa se bloqueará. Esto se debe a que el sistema operativo envía eventos al juego y el juego no hace nada con ellos. Una vez que el juego recibe demasiados eventos sin controlar, se bloqueará.
while True: … pygame.display.flip ()
Paso 9. Manejar eventos
Obtenga una lista de todos los eventos que han ocurrido en cada cuadro. Solo te va a importar un evento, el evento de dejar de fumar. Esto ocurre cuando el usuario cierra la ventana del juego. Esto también evitará que nuestro programa se bloquee debido a demasiados eventos.
while True: … para el evento en pygame.event.get (): si event.type == SALIR: pygame.quit ()
Paso 10. ¡Pruébelo
Así es como debería verse el código ahora:
importar pygame desde pygame.locals importar * resolución = (400, 300) blanco = (255, 255, 255) negro = (0, 0, 0) rojo = (255, 0, 0) pantalla = pygame.display.set_mode (resolución) mientras que True: screen.fill (blanco) pygame.display.flip () para el evento en pygame.event.get (): if event.type == QUIT: pygame.quit ()
Parte 3 de 8: Crear un objeto de juego
Paso 1. Cree una nueva clase y constructor
Establezca todas las propiedades del objeto. También está proporcionando valores predeterminados para todas las propiedades.
class Ball: def _init _ (self, xPos = resolution [0] / 2, yPos = resolution [1] / 2, xVel = 1, yVel = 1, rad = 15): self.x = xPos self.y = yPos self.dx = xVel self.dy = yVel self.radius = rad self.type = "bola"
Paso 2. Defina cómo dibujar el objeto
Utilice las propiedades que se definieron en el constructor para dibujar la bola como un círculo, así como para pasar una superficie a la función para dibujar el objeto. La superficie será el objeto de pantalla que se creó con la resolución anterior.
def draw (self, surface): pygame.draw.circle (superficie, negro, (self.x, self.y), self.radius)
Paso 3. Haga una instancia de la clase y dígale al bucle del juego que saque la pelota en cada bucle
ball = Ball () while True:… ball.draw (pantalla)
Paso 4. Haz que el objeto se mueva
Cree una función que actualice la posición del objeto. Llame a esta función en cada bucle de juego.
class Ball:… def update (self): self.x + = self.dx self.y + = self.dy
Paso 5. Limite la velocidad de fotogramas
La pelota se moverá muy rápido porque el bucle del juego se ejecuta cientos de veces por segundo. Utilice el reloj de Pygame para limitar la velocidad de fotogramas a 60 fps.
clock = pygame.time. Clock () while True:… clock.tick (60)
Paso 6. Mantenga la pelota en la pantalla
Agregue cheques en la función de actualización para invertir la dirección de la bola si golpea uno de los bordes de la pantalla.
class Ball:… def update (self):… if (self.x <= 0 o self.x> = resolution [0]): self.dx * = -1 if (self.y <= 0 o self.y > = resolución [1]): self.dy * = -1
Paso 7. ¡Pruébelo
Así es como debería verse el código ahora:
importar pygame desde pygame.locals importar * resolución = (400, 300) blanco = (255, 255, 255) negro = (0, 0, 0) rojo = (255, 0, 0) pantalla = pygame.display.set_mode (resolución) clase Bola: def _init _ (self, xPos = resolución [0] / 2, yPos = resolución [1] / 2, xVel = 1, yVel = 1, rad = 15): self.x = xPos self.y = yPos self.dx = xVel self.dy = yVel self.radius = rad self.type = "ball" def draw (self, surface): pygame.draw.circle (surface, black, (self.x, self.y), self.radius) def update (self): self.x + = self.dx self.y + = self.dy if (self.x <= 0 o self.x> = resolución [0]): self.dx * = -1 if (self.y <= 0 o self.y> = resolución [1]): self.dy * = -1 ball = Ball () clock = pygame.time. Clock () while True: screen. fill (blanco) ball.draw (pantalla) ball.update () pygame.display.flip () clock.tick (60) para el evento en pygame.event.get (): si event.type == SALIR: pygame.quit ()
Parte 4 de 8: Organizar el juego
Paso 1. Utilice las clases para organizar todo
El juego se va a complicar más. Utilice técnicas orientadas a objetos para organizar su código.
Paso 2. Convierta el bucle del juego en una clase
Dado que nuestro juego ahora tiene datos que incluyen los objetos y funciones de su juego, tiene sentido convertir su ciclo de juego en una clase.
juego de clase ():
Paso 3. Agregue un constructor
Aquí crearás una instancia de algunos objetos del juego, crearás nuestra pantalla y reloj e inicializarás Pygame. Pygame debe inicializarse para usar ciertas funciones como texto o sonido.
class game (): def _init _ (self): pygame.init () self.screen = pygame.display.set_mode (resolución) self.clock = pygame.time. Clock ()
Paso 4. Manejar eventos en una función
class game ():… def handleEvents (self): para evento en pygame.event.get (): if event.type == QUIT: pygame.quit ()
Paso 5. Haga que el bucle del juego sea una función
Llame a la función de manejo de eventos en cada bucle.
class game ():… def run (self): while True: self.handleEvents () self.screen.fill (blanco) self.clock.tick (60) pygame.display.flip ()
Paso 6. Maneja varios objetos del juego
En este momento, este código tiene que llamar a dibujar y actualizar en nuestro objeto cada cuadro. Esto se complicaría si tuviera muchos objetos. Agreguemos nuestro objeto a una matriz y luego actualicemos y dibujemos todos los objetos de la matriz en cada ciclo. Ahora puede agregar fácilmente otro objeto y darle una posición inicial diferente.
class game (): def _init _ (self):… self.gameObjects = self.gameObjects.append (Ball ()) self.gameObjects.append (Ball (100))… def run (self): while True: self.handleEvents () para gameObj en self.gameObjects: gameObj.update () self.screen.fill (blanco) para gameObj en self.gameObjects: gameObj.draw (self.screen) self.clock.tick (60) pygame.display.voltear()
Paso 7. ¡Pruébelo
Así es como debería verse el código ahora:
importar pygame desde pygame.locals importar * resolución = (400, 300) blanco = (255, 255, 255) negro = (0, 0, 0) rojo = (255, 0, 0) pantalla = pygame.display.set_mode (resolución) clase Bola: def _init _ (self, xPos = resolución [0] / 2, yPos = resolución [1] / 2, xVel = 1, yVel = 1, rad = 15): self.x = xPos self.y = yPos self.dx = xVel self.dy = yVel self.radius = rad self.type = "ball" def draw (self, surface): pygame.draw.circle (surface, black, (self.x, self.y), self.radius) def update (self): self.x + = self.dx self.y + = self.dy if (self.x <= 0 o self.x> = resolución [0]): self.dx * = -1 if (self.y <= 0 o self.y> = resolución [1]): self.dy * = -1 class game (): def _init _ (self): pygame.init () self.screen = pygame.display.set_mode (resolución) self.clock = pygame.time. Clock () self.gameObjects = self.gameObjects.append (Ball ()) self.gameObjects.append (Ball (100)) def handleEvents (self): para el evento en pygame.event.get (): if event.type == SALIR: pygame.quit () def run (self): while True: self.handleEvent s () para gameObj en self.gameObjects: gameObj.update () self.screen.fill (blanco) para gameObj en self.gameObjects: gameObj.draw (self.screen) self.clock.tick (60) pygame.display. flip () juego (). ejecutar ()
Parte 5 de 8: Agregar un objeto de jugador
Paso 1. Crea una clase de jugador y un constructor
Vas a hacer otro círculo controlado por el ratón. Inicializa los valores en el constructor. El radio es el único valor importante.
class Player: def _init _ (self, rad = 20): self.x = 0 self.y = 0 self.radius = rad
Paso 2. Defina cómo dibujar el objeto del jugador
Va a ser de la misma manera que dibujaste los otros objetos del juego.
class Player:… def draw (self, surface): pygame.draw.circle (surface, red, (self.x, self.y), self.radius)
Paso 3. Agregue el control del mouse para el objeto del jugador
En cada cuadro, verifique la ubicación del mouse y establezca la ubicación de los objetos de los jugadores en ese punto.
class Player:… def update (self): cord = pygame.mouse.get_pos () self.x = cord [0] self.y = cord [1]
Paso 4. Agrega un objeto de jugador a gameObjects
Crea una nueva instancia de jugador y agrégala a la lista.
class game (): def _init _ (self):… self.gameObjects.append (Player ())
Paso 5. ¡Pruébelo
Así es como debería verse el código ahora:
importar pygame de pygame.locals importar * resolución = (400, 300) blanco = (255, 255, 255) negro = (0, 0, 0) rojo = (255, 0, 0) pantalla = pygame.display.set_mode (resolución) clase Bola: def _init _ (self, xPos = resolución [0] / 2, yPos = resolución [1] / 2, xVel = 1, yVel = 1, rad = 15): self.x = xPos self.y = yPos self.dx = xVel self.dy = yVel self.radius = rad self.type = "ball" def draw (self, surface): pygame.draw.circle (surface, black, (self.x, self.y), self.radius) def update (self): self.x + = self.dx self.y + = self.dy if (self.x <= 0 o self.x> = resolución [0]): self.dx * = -1 if (self.y <= 0 o self.y> = resolución [1]): self.dy * = -1 clase Jugador: def _init _ (self, rad = 20): self.x = 0 self.y = 0 self.radius = rad self.type = "player" def draw (self, surface): pygame.draw.circle (surface, red, (self.x, self.y), self.radius) def update (self): cord = pygame.mouse.get_pos () self.x = cord [0] self.y = cord [1] class game (): def _init _ (self): pygame.init () self.screen = pygame.display.set_ modo (resolución) self.clock = pygame.time. Clock () self.gameObjects = self.gameObjects.append (Player ()) self.gameObjects.append (Ball ()) self.gameObjects.append (Ball (100)) def handleEvents (self): para evento en pygame.event.get (): if event.type == QUIT: pygame.quit () def run (self): while True: self.handleEvents () para gameObj en self.gameObjects: gameObj.update () self.screen.fill (blanco) para gameObj en self.gameObjects: gameObj.draw (self.screen) self.clock.tick (60) pygame.display.flip () game (). correr()
Parte 6 de 8: Hacer que los objetos interactúen con el jugador
Paso 1. Cambie las funciones de actualización
Para que los objetos interactúen, deberán tener acceso entre sí. Agreguemos otro parámetro a Update para pasar a la lista de gameObjects. Tendrás que agregarlo tanto al objeto del jugador como a los objetos Bola. Si tiene muchos objetos de juego, la herencia podría ayudarlo a mantener iguales todas las firmas de sus métodos.
class Ball: … def update (self, gameObjects): … class Player: … def update (self, gameObjects):
Paso 2. Compruebe si hay colisiones entre el jugador y las bolas
Revisa todos los objetos del juego y comprueba si el tipo de los objetos es bola. Luego, use los radios de los dos objetos y la fórmula de la distancia para verificar si están colisionando. Los círculos son muy fáciles de controlar en caso de colisiones. Esta es la razón principal por la que no usaste otra forma para este juego.
class Player:… def update (self, gameObjects):… para gameObj en gameObjects: if gameObj.type == "ball": if (gameObj.x - self.x) ** 2 + (gameObj.y - self.y) ** 2 <= (gameObj.radius + self.radius) ** 2:
Paso 3. Termina el juego si el jugador es "golpeado"
Salgamos del juego por ahora.
if (gameObj.x - self.x) ** 2 + (gameObj.y - self.y) ** 2 <= (gameObj.radius + self.radius) ** 2: pygame.quit ()
Paso 4. ¡Pruébelo
Así es como debería verse el código ahora:
importar pygame desde pygame.locals importar * resolución = (400, 300) blanco = (255, 255, 255) negro = (0, 0, 0) rojo = (255, 0, 0) pantalla = pygame.display.set_mode (resolución) clase Bola: def _init _ (self, xPos = resolución [0] / 2, yPos = resolución [1] / 2, xVel = 1, yVel = 1, rad = 15): self.x = xPos self.y = yPos self.dx = xVel self.dy = yVel self.radius = rad self.type = "ball" def draw (self, surface): pygame.draw.circle (surface, black, (self.x, self.y), self.radius) def update (self, gameObjects): self.x + = self.dx self.y + = self.dy if (self.x <= 0 o self.x> = resolución [0]): self.dx * = -1 if (self.y <= 0 o self.y> = resolución [1]): self.dy * = -1 clase Jugador: def _init _ (self, rad = 20): self.x = 0 self.y = 0 self.radius = rad self.type = "player" def draw (self, surface): pygame.draw.circle (surface, red, (self.x, self.y), self.radius) def update (self, gameObjects): cord = pygame.mouse.get_pos () self.x = cord [0] self.y = cord [1] para gameObj en gameObjects: if gameObj.type == "ball": if (gameObj.x - self.x) ** 2 + (gameObj.y - self.y) ** 2 <= (gameObj.radius + self.radius) ** 2: pygame.quit () class game (): def _init _ (self): pygame.init () self.screen = pygame.display.set_mode (resolución) self.clock = pygame.time. Clock () self.gameObjects = self.gameObjects.append (Player ()) self.gameObjects.append (Ball ()) self.gameObjects.append (Ball (100)) def handleEvents (self): para el evento en pygame.event.get (): si event.type == SALIR: pygame.quit () def run (self): while True: self.handleEvents () para gameObj en self.gameObjects: gameObj.update (self.gameObjects) self.screen.fill (blanco) para gameObj en self.gameObjects: gameObj.draw (self.screen) self.clock.tick (60) pygame.display.flip () juego (). ejecutar ()
Parte 7 de 8: Agregar un controlador de juego para crear objetos
Paso 1. Cree una clase de controlador de juego
Los controladores del juego son responsables de "ejecutar" el juego. Es diferente a nuestra clase de juego que se encarga de dibujar y actualizar todos nuestros objetos. El controlador agregará periódicamente otra bola a la pantalla para hacer el juego más difícil. Agregue un constructor e inicialice algunos valores básicos. El intervalo será el tiempo antes de que se agregue otra bola.
clase GameController: def _init _ (self, interval = 5): self.inter = intervalo self.next = pygame.time.get_ticks () + (2 * 1000) self.type = "controlador de juego"
Paso 2. Agregue la función de actualización
Esto comprobará cuánto tiempo ha pasado desde el momento en que se agregó una bola o desde el inicio del juego. Si el tiempo es mayor que el intervalo, restablecerá el tiempo y agregará una pelota.
class GameController:… def update (self, gameObjects): if self.next <pygame.time.get_ticks (): self.next = pygame.time.get_ticks () + (self.inter * 1000) gameObjects.append (Ball ())
Paso 3. Dale a las bolas velocidades aleatorias
Necesitarás usar números aleatorios para que el juego sea diferente cada vez. Sin embargo, las velocidades de las bolas ahora son un número de punto flotante en lugar de un entero.
class GameController:… def update (self, gameObjects): if self.next <pygame.time.get_ticks (): self.next = pygame.time.get_ticks () + (self.inter * 1000) gameObjects.append (Ball (xVel = aleatorio () * 2, yVel = aleatorio () * 2))
Paso 4. Corrija la función de dibujo
La función de dibujo no acepta flotantes. Convirtamos la posición de la bola en números enteros antes de que se saquen las bolas.
class Ball: … def draw (self, surface): pygame.draw.circle (surface, black, (int (self.x), int (self.y)), self.radius)
Paso 5. Defina un método de dibujo para el dispositivo de juego
Dado que es un objeto de juego, el bucle principal intentará dibujarlo. Necesitarás definir una función de dibujo que no haga nada para que el juego no se bloquee.
clase GameController:… def draw (self, screen): pass
Paso 6. Agrega el dispositivo de juego a gameObjects y quita las 2 bolas
El juego ahora debería generar una bola cada cinco segundos.
class game (): def _init _ (self):… self.gameObjects = self.gameObjects.append (GameController ()) self.gameObjects.append (Player ())
Paso 7. ¡Pruébelo
Así es como debería verse el código ahora:
importar pygame desde aleatorio importar aleatorio desde pygame.locals importar * resolución = (400, 300) blanco = (255, 255, 255) negro = (0, 0, 0) rojo = (255, 0, 0) pantalla = pygame. display.set_mode (resolución) class Ball: def _init _ (self, xPos = resolution [0] / 2, yPos = resolution [1] / 2, xVel = 1, yVel = 1, rad = 15): self.x = xPos self.y = yPos self.dx = xVel self.dy = yVel self.radius = rad self.type = "ball" def draw (self, surface): pygame.draw.circle (surface, black, (int (self. x), int (self.y)), self.radius) def update (self, gameObjects): self.x + = self.dx self.y + = self.dy if (self.x <= 0 o self. x> = resolución [0]): self.dx * = -1 if (self.y <= 0 o self.y> = resolución [1]): self.dy * = -1 clase Jugador: def _init _ (self, rad = 20): self.x = 0 self.y = 0 self.radius = rad self.type = "jugador" def draw (self, surface): pygame.draw.circle (surface, red, (self.x, self.y), self.radius) def update (self, gameObjects): cord = pygame.mouse.get_pos () self.x = cord [0] self.y = cord [1] para gameObj en el juego Objetos: if gameObj.type == "ball": if (gameObj.x - self.x) ** 2 + (gameObj.y - self.y) ** 2 <= (gameObj.radius + self.radius) * * 2: pygame.quit () class GameController: def _init _ (self, interval = 5): self.inter = intervalo self.next = pygame.time.get_ticks () + (2 * 1000) self.type = "controlador de juego "def update (self, gameObjects): if self.next <pygame.time.get_ticks (): self.next = pygame.time.get_ticks () + (self.inter * 1000) gameObjects.append (Ball (xVel = random () * 2, yVel = random () * 2)) def draw (self, screen): pass class game (): def _init _ (self): pygame.init () self.screen = pygame.display.set_mode (resolución) self.clock = pygame.time. Clock () self.gameObjects = self.gameObjects.append (GameController ()) self.gameObjects.append (Player ()) def handleEvents (self): para evento en pygame.event.get (): if event.type == QUIT: pygame.quit () def run (self): while True: self.handleEvents () para gameObj en self.gameObjects: gameObj.update (self.gameObjects) self.screen.fill (blanco) para gameObj en self.gameO bjects: gameObj.draw (self.screen) self.clock.tick (60) pygame.display.flip () game (). run ()
Parte 8 de 8: Agregar una puntuación y terminar el juego
Paso 1. Agregue una puntuación a la clase de dispositivo de juego
Cree un objeto de fuente y una variable de puntuación. Dibujará la fuente en cada fotograma para mostrar la puntuación y aumentar la puntuación en cada fotograma en la actualización.
class GameController: def _init _ (self, interval = 5):… self.score = 0 self.scoreText = pygame.font. Font (None, 12) def update (self, gameObjects):… self.score + = 1 def draw (self, screen): screen.blit (self.scoreText.render (str (self.score), True, black), (5, 5))
Paso 2. Modifica cómo termina el juego
Eliminemos el abandono cuando el jugador detecte una colisión. En su lugar, establecerá una variable en el jugador que el juego puede verificar. Cuando se establece gameOver, deja de actualizar objetos. Esto congelará todo en su lugar para que el jugador pueda ver lo que sucedió y verificar su puntaje. Tenga en cuenta que los objetos todavía se están dibujando, pero no se actualizan.
class Player: def _init _ (self, rad = 20):… self.gameOver = False def update (self, gameObjects):… para gameObj en gameObjects: if gameObj.type == "ball": if (gameObj.x - self.x) ** 2 + (gameObj.y - self.y) ** 2 <= (gameObj.radius + self.radius) ** 2: self.gameOver = True class game (): def _init _ (self): … Self.gameOver = False def run (self): while True: self.handleEvents () si no self.gameOver: para gameObj en self.gameObjects: gameObj.update (self.gameObjects) if gameObj.type == "player": self.gameOver = gameObj.gameOver
Paso 3. ¡Pruébelo
Así es como debería verse el código terminado ahora:
importar pygame desde aleatorio importar aleatorio desde pygame.locals importar * resolución = (400, 300) blanco = (255, 255, 255) negro = (0, 0, 0) rojo = (255, 0, 0) pantalla = pygame. display.set_mode (resolución) class Ball: def _init _ (self, xPos = resolution [0] / 2, yPos = resolution [1] / 2, xVel = 1, yVel = 1, rad = 15): self.x = xPos self.y = yPos self.dx = xVel self.dy = yVel self.radius = rad self.type = "ball" def draw (self, surface): pygame.draw.circle (surface, black, (int (self. x), int (self.y)), self.radius) def update (self, gameObjects): self.x + = self.dx self.y + = self.dy if (self.x <= 0 o self. x> = resolución [0]): self.dx * = -1 if (self.y <= 0 o self.y> = resolución [1]): self.dy * = -1 clase Jugador: def _init _ (self, rad = 20): self.x = 0 self.y = 0 self.radius = rad self.type = "jugador" self.gameOver = False def draw (self, surface): pygame.draw.circle (surface, red, (self.x, self.y), self.radius) def update (self, gameObjects): cord = pygame.mouse.get_pos () self.x = cord [0] self.y = cord [1] para gameObj en gameObjects: if gameObj.type == "ball": if (gameObj.x - self.x) ** 2 + (gameObj.y - self.y) ** 2 <= (gameObj.radius + self.radius) ** 2: self.gameOver = True class GameController: def _init _ (self, interval = 5): self.inter = intervalo self.next = pygame.time.get_ticks () + (2 * 1000) self. type = "game controller" self.score = 0 self.scoreText = pygame.font. Font (None, 12) def update (self, gameObjects): if self.next <pygame.time.get_ticks (): self.next = pygame.time.get_ticks () + (self.inter * 1000) gameObjects.append (Ball (xVel = random () * 2, yVel = random () * 2)) self.score + = 1 def draw (self, screen): screen.blit (self.scoreText.render (str (self.score), True, black), (5, 5)) class game (): def _init _ (self): pygame.init () self.screen = pygame.display.set_mode (resolución) self.clock = pygame.time. Clock () self.gameObjects = self.gameObjects.append (GameController ()) self.gameObjects.append (Player ()) self.gameOver = False def handleEvents (self): para evento en pygame.event.get (): if ev ent.type == QUIT: pygame.quit () def run (self): while True: self.handleEvents () si no self.gameOver: para gameObj en self.gameObjects: gameObj.update (self.gameObjects) if gameObj. type == "player": self.gameOver = gameObj.gameOver self.screen.fill (blanco) para gameObj en self.gameObjects: gameObj.draw (self.screen) self.clock.tick (60) pygame.display.flip () juego (). ejecutar ()