Pygame é uma biblioteca escrita em Python e baseada em SDL (Simple DirectMedia Layer), utilizada para o desenvolvimento de games e interfaces gráficas para criar jogos em 2D, o Pygame fornece acesso a áudios, teclados, controles, mouses e hardwares gráficos via OpenGL e Direct3D.
Por serem multi plataformas, tanto a SDL quanto o Pygame, podem rodar em quaisquer sistemas operacionais com alterações mínimas de código no funcionamento de um ou outro.
Alguns conceitos importantes no pygame:
➡ Surface: superfícies em 2D (ou 3D utilizando OpenGL) onde se desenha o jogo. Podemos considerar que surface é tipo um "canvas" onde todo o conteúdo visual do jogo é renderizado.
➡ Display: é o evento para manipulação da tela do jogo, responsável pela janela do jogo. A função pygame.display.set_mode() inicializa a janela.
➡ Sprite: Imagens bidimensionais, como personagens e objetos, que podem se mover e interagir no jogo.
➡ Eventos e Controle de Input: Captura inputs do teclado, mouse ou joystick, essenciais para a interação do jogador.
➡ Módulo Mixer: Controla a música e efeitos sonoros dentro do jogo.
Instalação do Pygame
Estou utilizando o Vscode mas você pode utilizar qualquer IDE que desejar.
No VsCode, no canto suprior na barra de opções, clique em Terminal, Novo Terminal, e copie e cole o script abaixo e pressione enter:
python -m pip install -U pygame --user
Após a biblioteca ter sido instalada, podemos começar a criar jogos, veja um exemplo abaixo que o chatGpt criou:
import pygame
import sys
# Inicializa o pygame
pygame.init()
# Configura a tela
screen = pygame.display.set_mode((800, 600))
# Define a cor
WHITE = (255, 255, 255)
BALL_COLOR = (50, 100, 255)
# Define a posição e velocidade da bola
ball_pos = [400, 300]
ball_speed = [3, 3]
ball_radius = 20
# Controla o FPS
clock = pygame.time.Clock()
# Loop principal do jogo
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# Atualiza a posição da bola
ball_pos[0] += ball_speed[0]
ball_pos[1] += ball_speed[1]
# Rebater nas bordas
if ball_pos[0] - ball_radius <= 0 or ball_pos[0] + ball_radius >= 800:
ball_speed[0] = -ball_speed[0]
if ball_pos[1] - ball_radius <= 0 or ball_pos[1] + ball_radius >= 600:
ball_speed[1] = -ball_speed[1]
# Preenche a tela com branco
screen.fill(WHITE)
# Desenha a bola
pygame.draw.circle(screen, BALL_COLOR, ball_pos, ball_radius)
# Atualiza a tela
pygame.display.flip()
# Limita a 60 FPS
clock.tick(60)
Para obter mais ajuda sobre os primeiros passos, clique aqui
Para obter exemplos disponíveis, clique aqui
Inicialização e Módulos
Para usar os métodos da biblioteca Pygame, faça a importação do módulo:
import pygame
A instrução import grava a versão do pygame e um link para o site do Pygame no console:
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
A instrução de importação do Pygame é sempre colocada no início do programa. Ela importa as classes, métodos e atributos do Pygame para o espaço de nomes atual. Agora, esses novos métodos podem ser chamados via pygame.metodo().
Por exemplo, agora podemos inicializar ou sair do pygame com os comandos:
pygame.init()
pygame.quit()
➡ pygame.init(): Inicializa todos os módulos de Pygame importados. Podemos sempre inicializar módulos individuais manualmente, mas pygame.init() inicializa todos os módulos Pygame importados, é uma maneira conveniente de começar tudo.
➡ pygame.quit(): Desinicializa todos os módulos do Pygame que foram inicializados anteriormente. Quando o interpretador Python é encerrado, este método é chamado independentemente, portanto, seu programa não deve precisar dele, exceto quando desejar encerrar seus recursos de Pygame.
Se eventualmente precisarmos obter ajuda sobre algum método ou classe do Pygame, podemos utilizar a função help() do Python, por exemplo:
help(pygame)
help(pygame.draw)
help(pygame.event)
help(pygame.image)
Para acessar todos os exemplos utilizados neste tutorial e outros adicionais, você pode visitar o repositório do GitHub: PyGameDev.
Coordenadas
O sistema de coordenadas cartesianas é o sistema ao qual a maioria das pessoas está acostumada ao traçar gráficos. Este é o sistema normalmente ensinado nas escolas. O Pygame usa um sistema de coordenadas semelhante, mas um pouco diferente.
Pygame usa um sistema de coordenadas x e y onde a posição (0,0) é definida como o canto superior esquerdo da tela. Mover para baixo significa ter um valor de y mais alto, mover para a direita significa ter um valor de x mais alto.
Imagens e Rects
Podemos desenhar formas(shapes) diretamente na superfície da tela, além disso também podemos trabalhar com imagens no disco. O módulo de imagem permite carregar e salvar imagens em uma variedade de formatos populares. As imagens são carregadas em objetos Surface, que podem ser manipulados e exibidos de várias maneiras.
Os objetos Surface são representados por retângulos, assim como muitos outros objetos no Pygame, como imagens e janelas. Retângulos são tão usados que existe uma classe especial Rect apenas para manipulá-los. Usaremos objetos e imagens Rect em nossos jogos para desenhar personagens e obstáculos e para gerenciar colisões entre eles.
Um objeto Rect pode ser criado fornecendo:
Os 4 parâmetros left, top, width e height
A posição e tamanho
Um objeto que tem um atributo rect
Rect(left, top, width, height)
Rect(posicao, tamanho)
Rect(objeto)
A figura a seguir nos ajuda a compreender a criação do retângulo e seu posicionamento:
Atributos Virtuais
O objeto Rect tem vários atributos virtuais que podem ser usados para mover e alinhar o Rect. A atribuição a esses atributos apenas move o retângulo sem alterar seu tamanho:
x, y
top, left, bottom, right
topleft, bottomleft, topright, bottomright
midtop, midleft, midbottom, midright
center, centerx, centery
A atribuição desses 5 atributos a seguir altera o tamanho do retângulo, mantendo sua posição superior esquerda:
size, width, height, w, h
Como podemos observar, a classe Rect define 4 pontos de canto, 4 pontos médios e 1 ponto central.
A tabela a seguir apresenta uma lista dos atributos mais importantes que os objetos pygame.Rect fornecem (neste exemplo, a variável onde o objeto Rect é armazenado é chamada de meuRet):
Nome do Atributo | Descrição |
meuRet.left | O valor int da coordenada X do lado esquerdo do retângulo. |
meuRet.right | O valor int da coordenada X do lado direito do retângulo. |
O valor int da coordenada Y do lado superior do retângulo. | |
meuRet.bottom | O valor int da coordenada Y do lado inferior. |
meuRet.centerx | O valor int da coordenada X do centro do retângulo. |
meuRet.centery | O valor int da coordenada Y do centro do retângulo. |
meuRet.width | O valor int da largura do retângulo. |
meuRet.height | O valor int da altura do retângulo. |
meuRet.size | Uma tupla de dois ints: (width, height) |
meuRet.topleft | Uma tupla de dois ints: (left, top) |
meuRet.topright | Uma tupla de dois ints: (right, top) |
meuRet.bottomleft | Uma tupla de dois ints: (left, bottom) |
meuRet.bottomright | Uma tupla de dois ints: (right, bottom) |
meuRet.midleft | Uma tupla de dois ints: (left, centery) |
meuRet.midright | Uma tupla de dois ints: (right, centery) |
meuRet.midtop | Uma tupla de dois ints: (centerx, top) |
meuRet.midbottom | Uma tupla de dois ints: (centerx, bottom) |
Cores
As cores são definidas como tuplas das cores básicas vermelho, verde e azul. Isso é chamado de modelo RGB. Cada cor de base é representada como um número entre 0 (mínimo) e 255 (máximo) que ocupa 1 byte na memória. Uma cor RGB é então representada como um valor de 3 bytes. A mistura de duas ou mais cores resulta em novas cores. Um total aproximado de 16 milhões (255³) de cores diferentes podem ser representadas dessa forma.
Definimos então as cores básicas como tuplas dos três valores base. Como as cores são constantes, vamos escrevê-las em maiúsculas. A ausência de todas as cores resulta em preto. O valor máximo para todos os três componentes resulta em branco. Três valores intermediários idênticos resultam em cinza:
PRETO = (0, 0, 0)
CINZA = (128, 128, 128)
BRANCO = (255, 255, 255)
As três cores base são definidas como:
VERMELHO = (255, 0, 0)
VERDE = (0, 255, 0)
AZUL = (0, 0, 255)
O método screen.fill(COR) preenche toda a tela com a cor especificada. Para mostrar qualquer coisa na tela, devemos sempre lembrar de chamar a função pygame.display.update().
É importante lembrarmos que Pygame também conta com cores já definidas, para vermos todas elas podemos usar o seguinte script:
from pprint import pprint
import pygame
pprint(pygame.color.THECOLORS)
Neste caso, podemos por exemplo definir a cor preta da seguinte forma:
BLACK = pygame.Color("black")
Game Loop
O Game Loop possui quatro elementos muito importantes:
Processar o Input do Usuário
Atualizar o estado de todos os objetos do Game
Atualizar o display e o output de áudio
Manter a velocidade do Game
Cada ciclo do Game Loop é chamado de frame e quanto mais rápido fizermos as ações em cada ciclo, mais rápido o jogo será executado. Os frames continuam a ocorrer até que alguma condição para sair do jogo seja satisfeita. Em seu projeto, existem duas condições que podem encerrar o Game Loop:
O jogador colide com um obstáculo.
O jogador fecha a janela do Game.
A primeira coisa que o Game Loop faz é processar o Input do Usuário para permitir que o jogador se mova pela tela. Portanto, precisamos de alguma forma para capturar e processar uma variedade de inputs. Fazemos isso usando o sistema de eventos do Pygame.
O fluxograma a seguir nos apresenta uma ideia geral de como um Game é estruturado e funciona no PyGame:
Processando eventos
A parte essencial de qualquer aplicação interativa é o loop de eventos. Reagir a eventos permite que o usuário interaja com a aplicação. Eventos são ações que podem acontecer em um programa, como:
Clique do mouse
Movimento do mouse
Teclado pressionado
Ação do joystick
A seguir temos um exemplo de um loop infinito que imprime todos os eventos no console:
import pygame
pygame.init()
# Inicializa a tela
screen = pygame.display.set_mode((500,500))
pygame.display.set_caption("Eventos")
# Game Loop ficará ativo até que running seja False
running = True
while running:
# Observa cada evento na fila de eventos
for event in pygame.event.get():
# Imprime no console todos os eventos que vierem a ocorrer
print(event)
# Fecha o jogo
if event.type == pygame.QUIT:
running = False
pygame.quit()
Ao executarmos o script acima veremos uma janela com uma tela preta, ela não irá desaparecer até que cliquemos no botão fechar, todas as ações executadas por nós serão impressas em nosso console.