À semelhança do que acontece com os módulos externos do Python, como o random, math ou time, que acrescentam funcionalidades ao "núcleo" da linguagem, a framework pygame inclui recursos para gráficos, sons, eventos do rato, etc., que não estão disponíveis de raiz no Python.
O pygame não é a única biblioteca disponível para desenvolver programas que suportem interfaces gráficos. Existem, inclusivamente, outras bibliotecas mais adequadas para o desenvolvimento de programas "tipo Windows", suportando botões, caixas de texto, caixas de seleção, etc.. Como o nome indica, o pygame tem como principal objetivo o desenvolvimento de jogos.
Como instalar o pygame
A instalação do pygame depende do sistema operativo (Windows, Linux, Mac, etc.), da instalação ser de 32 bits ou de 64 bits e da versão de Python instalada.
Para instalar o pygame, em Windows, temos que seguir os passos:
Determinar a versão de Python instalada (IDLE > Help > About ou python --version).
Como iremos instalar no Win10/64 bits e Python 3.5.2, escolhemos no site http://www.lfd.uci.edu/~gohlke/pythonlibs/#pygame o ficheiro pygame‑1.9.2‑cp35‑cp35m‑win_amd64.whl (embora não seja um site oficial, tem o pygame preparado para as versões mais recentes de Windows e Python).
Fazer o download e copiar para a pasta [pasta de instalação do Python]\scripts.
Na pasta «scripts», abre-se uma linha de comandos em modo administrador (ver nota).
Dar o comando: pip3 install pygame-1.9.2-cp35-cp35m-win_amd64.whl (substituir pelo ficheiro descarregado).
Para verificar que está a funcionar, fazer import pygame, no IDLE. Se não der error, estará bem instalado e a funcionar.
Nota: no Win10 para abrir a linha de comando em modo administrador numa pasta, acede-se Explorador do Windows, Ficheiro e seleciona-se a opção «Abrir linha de comandos como administrador»:
Em Python usamos as funções print() e input() para escrever e ler texto. Estes programas, com um interface "tipo linha de comandos", são designados de programas para a consola ou CLI (Command-Line Interface). São programas limitados, porque não permitem trabalhar com gráficos (imagens), cores, sons ou usar o rato. Os programas CLI só podem receber inputs do teclado, respondendo somente após o utilizador dar enter nesses inputs. Isto significa que não é possível desenvolver jogos que respondam em tempo-real às ações do jogador.
O pygame providencia recursos para criar programas com interface gráfico ou GUI (Graphical User Interface). Um programa com interface gráfico (GUI) possui uma janela que suporta a utilização de imagens, cores, rato, etc..
«Olá Mundo», com pygame
Exemplo (OlaMundo.py):
import pygame, sys
from pygame.locals import *
pygame.init()
DISPLAYSURF = pygame.display.set_mode((400, 300))
pygame.display.set_caption("Olá Mundo!")
while True: # ciclo principal (game loop)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
Execução:
O programa acima contém o esqueleto de qualquer programa que use o pygame.
import pygame, sys
Importa as módulos pygame e sys. Todas as funcionalidades do pygame necessárias à utilização de gráficos, sons e outras são importadas. Não é necessária a importação de submódulos como pygame.images ou pygame.mixer.music.
from pygame.locals import *
É também uma instrução para importar módulos. No entanto, não usa o formato import modulename, usa o formato from modulename import *. Normalmente, quando se quer chamar uma função de um módulo usa-se modulename.functionname(). No entanto, with com modulename import *, não é necessário usar o prefixo modulename. e pode-se usar functionname() diretamente (usa-se como se tratasse de uma função nativa do Python).
pygame.init()
A instrução pygame.init() é sempre necessária após a importação do módulo pygame e deve ser chamada antes de invocar qualquer função do pygame. Se receber uma mensagem do tipo pygame.error: font not initialized, verifique se não se esqueceu de chamar pygame.init() no início do programa.
DISPLAYSURF = pygame.display.set_mode((400, 300))
Cria e armazena numa variável a nossa superfície de desenho (objeto do tipo pygame.Surface), isto é, a janela de visualização.
Repare que é passado um tuple (estrutura de dados) de inteiros: (400, 300). Este tuple diz à função set_mode() a dimensão da janela: 400 pixels de largura e 300 pixels de altura. Muito importante: indique um tuple, utilizando parêntesis, na forma (400, 300), e não 400, 300 (dois inteiros).
A nossa superfície de desenho (objeto) será armazenada na variável DISPLAYSURF.
pygame.display.set_caption("Olá Mundo")
Indica o texto que será mostrado no título da janela.
Ciclo Principal e Eventos
while True: # ciclo principal
for event in pygame.event.get():
Um ciclo while True é executado para sempre. A única maneira de terminar o ciclo é através de uma instrução de break, que fará com que o programa termine o ciclo passando a execução para a primeira linha após o ciclo. No nosso caso, o programa termina, pois não existem mais instruções após o ciclo.
Este ciclo, com o comentário «ciclo principal», faz tipicamente 3 tarefas (embora neste exemplo não se justifiquem todas estas tarefas):
1. Trata os eventos.
2. Atualiza o estado do jogo.
3. Desenha no ecrã.
O estado do jogo é simplesmente uma forma de se referir a um conjunto de valores para todas as variáveis de um programa de jogo.
Em muitos jogos, o estado do jogo inclui os valores nas variáveis que rastreiam a saúde e a posição do jogador, a saúde e a posição de qualquer inimigo, marcas que foram feitas num tabuleiro, a pontuação ou a sua vez. Sempre que algo acontece quando o jogador recebe algum dano (o que diminui o seu valor de saúde), ou um inimigo se move em alguma posição ou se algo acontece no mundo do jogo, dizemos que o estado do jogo mudou.
Como o estado do jogo geralmente é atualizado em resposta a eventos (como cliques do rato ou teclas que foram pressionadas) ou a passagem do tempo, o loop do jogo está, constantemente, a verificar os novos eventos que aconteceram.
Dentro do loop principal, está o código que verifica quais eventos foram criados (com Pygame, isso é feito chamando a função pygame.event.get()). O loop principal também tem o código que atualiza o estado do jogo (com base nos eventos que ocorreram), isto é chamado de tratamento de eventos ou event handling.
pygame.event.Event Objects
Sempre que o utilizador fizer uma de várias ações (listadas na documentação do pygame), como pressionar uma tecla ou mover o rato na janela do programa, um objeto pygame.event.Event é criado para guardar este "evento".
A lista obtida com pygame.event.get () contém os eventos ocorridos desde a última vez que a função foi chamada. (Ou, se pygame.event.get () nunca foi chamada, os eventos que aconteceram desde o início do programa.)
for event in pygame.event.get():
É um ciclo for que irá iterar a lista de objetos Event que foi retornada por pygame.event.get ().
Em cada iteração através do loop for, uma variável chamada event irá conter um dos eventos da lista. A lista de objetos Event retornados de pygame.event.get () estará na ordem em que os eventos aconteceram. Se o utilizador clicou no mouse e, em seguida, pressionou uma tecla do teclado, o evento para o clique do rato seria o primeiro item na lista e o evento para o o teclado seria o segundo. Se nenhum evento acontecer, pygame.event.get () retornará uma lista em branco.
if event.type == QUIT:
pygame.quit()
sys.exit()
Os objetos de evento têm propriedades (também chamadas de atributos), sendo que uma delas «type» indica que tipo de evento o objeto representa. O pygame tem uma constante para cada um dos tipos possíveis nos módulos pygame.locals. O if verifica se o tipo de objeto Event é igual à constante QUIT. Lembre-se que, uma vez que usamos a forma de importação de pygame.locals * da instrução import, basta digitar QUIT em vez de pygame.locals.QUIT.
Se o objeto Event é um evento quit, as funções pygame.quit () e sys.exit () são chamadas. A função pygame.quit() é o oposto da função pygame.init(): executa código que desativa a biblioteca Pygame. Os seus programas devem sempre chamar pygame.quit(), antes de chamar sys.exit(), para encerrar o programa. Isto normalmente não importaria, mas há um bug no IDLE que faz com que IDLE pare, quando um programa Pygame termina antes que pygame.quit () seja chamado.
Como não temos instruções if que executem código para outros tipos de objeto Event, não há nenhum código de manipulação de eventos para quando o usuário clica no rato, pressiona as teclas do teclado ou faz com que qualquer outro tipo ação. O utilizador pode fazer essas coisas, mas não altera nada no programa porque o programa, pois não há nenhum código de manipulação de eventos desse tipo.
pygame.display.update()
Desenha o objeto Surface retornado por pygame.display.set_mode () no ecrã (lembre-se de que armazenamos esse objeto na variável DISPLAYSURF). Como o objeto surface não foi alterado (por exemplo, por outras funções de desenho), a mesma imagem preta é redesenhada para a tela cada vez que pygame.display.update() é chamado.
Este programa não faz nada, além de fazer uma janela preta aparecer na tela, verificar constantemente para um evento QUIT e, em seguida, redesenha a janela preta inalterada para o ecrã, repetidamente.
Drawing.py
import pygame, sys
from pygame.locals import *
pygame.init()
# definir janela
DISPLAYSURF = pygame.display.set_mode((400, 300), 0, 32)
pygame.display.set_caption('Drawing')
# definir cores
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)
# desenhar vários tipos de elementos
DISPLAYSURF.fill(WHITE)
pygame.draw.polygon(DISPLAYSURF, GREEN, ((146, 0), (291, 106), (236, 277), (56, 277), (0, 106)))
pygame.draw.line(DISPLAYSURF, BLUE, (60, 60), (120, 60), 4)
pygame.draw.line(DISPLAYSURF, BLUE, (120, 60), (60, 120))
pygame.draw.line(DISPLAYSURF, BLUE, (60, 120), (120, 120), 4)
pygame.draw.circle(DISPLAYSURF, BLUE, (300, 50), 20, 0)
pygame.draw.ellipse(DISPLAYSURF, RED, (300, 200, 40, 80), 1)
pygame.draw.rect(DISPLAYSURF, RED, (200, 150, 100, 50))
pixObj = pygame.PixelArray(DISPLAYSURF)
pixObj[380][280] = BLACK
pixObj[382][282] = BLACK
pixObj[384][284] = BLACK
pixObj[386][286] = BLACK
pixObj[388][288] = BLACK
del pixObj
# ciclo principal (game loop)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
Execução:
CatAnimation.py
import pygame, sys
from pygame.locals import *
pygame.init()
FPS = 30 # frames por segundo
fpsClock = pygame.time.Clock()
# definir janela de visualização
DISPLAYSURF = pygame.display.set_mode((400, 300))
pygame.display.set_caption('Cat Animation')
WHITE = (255, 255, 255)
catImg = pygame.image.load('cat.png')
catx = 10
caty = 10
direction = 'direita'
while True: # ciclo principal (game loop)
DISPLAYSURF.fill(WHITE)
if direction == 'direita':
catx += 5
if catx == 280:
direction = 'baixo'
elif direction == 'baixo':
caty += 5
if caty == 220:
direction = 'esquerda'
elif direction == 'esquerda':
catx -= 5
if catx == 10:
direction = 'cima'
elif direction == 'cima':
caty -= 5
if caty == 10:
direction = 'direita'
DISPLAYSURF.blit(catImg, (catx, caty))
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_UP:
direction = 'cima'
if event.key == K_DOWN:
direction = 'baixo'
if event.key == K_LEFT:
direction = 'esquerda'
if event.key == K_RIGHT:
direction = 'direita'
pygame.display.update()
fpsClock.tick(FPS)
Execução:
Copie o código acima e atribua-lhe o nome CatAnimation.py.
Copie a imagem: http://invpy.com/cat.png para a mesma pasta.
O resultado será (pode usar o rato para alterar o sentido da deslocação do gato):
Adaptado de http://inventwithpython.com/pygame