CProgPy Pygame
CProgPy Pygame
Introdução......................................................................................................................................3
Programa 1: Criando uma Janela...........................................................................................5
Programa 2: Figuras e Texto...................................................................................................12
Programa 3: Animação............................................................................................................24
Programa 4: Colisão.................................................................................................................34
Programa 5: Teclado e Mouse..............................................................................................42
Programa 6: Imagem e Som.................................................................................................53
Programa 7: Jogo......................................................................................................................64
CURSO DE INTRODUÇÃO À PROGRAMAÇÃO DE JOGOS EM PYTHON
Introdução
Na primeira parte do curso adquirimos algumas noções de programação em Python.
Lá vimos que programar consiste, basicamente, em trabalhar com dados. Vimos como os
dados eram manipulados através de certas estruturas como loops, condicionais, funções,
etc. Agora aplicaremos esse conhecimento para o verdadeiro objetivo do curso, que é fazer
jogos. Mas quando pensamos em jogos nos vêm à cabeça aspectos como figuras, sons, ani-
mações, controle de personagens, etc. Para isto precisaremos de outras ferramentas. Neste
caso, usaremos o Pygame.
O módulo Pygame inclui vários outros módulos com funcionalidades para a parte
gráfica, som, mouse e muitos outros. Neste tutorial abordaremos os módulos e funções bá-
sicas de Pygame. Para isto, faremos vários programas que nos mostrarão como utilizá-los.
Programa 1:
Criando uma Janela
Em nosso primeiro programa vamos criar uma janela. Esta janela ficará aberta até o
usuário clicar no “x” no canto superior da janela. O código está no arquivo p1_janela.py.
import pygame
# Loop do jogo
while deve_continuar:
# Checando eventos
for event in pygame.event.get():
# Se for um evento QUIT
if event.type == pygame.QUIT:
deve_continuar = False
import pygame
Pygame é formado por outros módulos. Para poder usá-los é necessário inicializá
-los. Isto é conseguido com pygame.init().
Continuando...
Largura Altura
janela = pygame.display.set_mode((400, 300))
Tupla
Título da Janela
pygame.display.set_caption(‘Olá, mundo!’)
Objetos, métodos e atributos serão palavras muito utilizadas a partir de agora neste tutorial. Já usamos
métodos anteriormente, sem mencioná-los, como por exemplo no uso de listas. Vejamos o seguinte
exemplo:
lista_var = [1,2,3]
lista_var.append(4)
Podemos ver que lista_var contém uma lista como valor e nela adicionamos “.append” passando 4
como argumento.
Um método é como uma função que está acoplada a um valor, neste caso o
método append() está acoplado ao valor lista_var. O método append() é um dos
muitos métodos de listas e, como explicado quando vimos listas, adiciona um
elemento no final da lista.
Já um objeto nada mais é do que um valor que contém métodos (e atributos).
No exemplo dado o objeto é lista_var.
Assim como um método é uma função associada a um objeto, um atributo é
uma variável associada a um objeto. Veremos vários casos de atributos ao longo
deste texto.
# função sum() de Python: recebe uma lista (neste caso) e devolve a soma de seus elementos
# função sqrt() do módulo math: recebe um número e devolve a sua raíz quadrada
>>> lista_var.append(4)
math.sqrt(16) lista_var.append(4)
Módulo Objeto
Talvez a melhor forma de lidar com esta situação seja não se preocupar muito se está sendo usado uma
função de um módulo ou um método de um objeto, no próprio texto explicitaremos o que está sendo
feito. O importante é entender que tanto funções como métodos podem receber dados e realizam al-
guma tarefa.
Antes de entrar no loop, foi criado um booleano com o nome deve_continuar que nos
indicará se o loop que está a seguir deve ser repetido ou não. Inicialmente damos o valor True
para que o código dentro do loop seja executado.
deve_continuar = True
Após, temos um loop que será executado sempre que a variável deve_continuar for
True. No seu interior checamos por eventos. Eventos são gerados sempre que o usuário pres-
siona uma tecla ou dá um clique no mouse, por exemplo.
deve_continuar = True
# Loop do jogo
while deve_continuar:
# Checando eventos
for event in pygame.event.get():
# Se for um evento QUIT
if event.type == pygame.QUIT:
deve_continuar = False
Programa 2:
Figuras e Textos
No programa anterior vimos como criar uma janela. Agora veremos como adicionar
algumas figuras e textos. O código se encontra no arquivo p2_figuras.py.
import pygame
# Definindo as cores
PRETO = (0, 0, 0)
BRANCO = (255, 255, 255)
VERMELHO = (255, 0, 0)
VERDE = (0, 255, 0)
AZUL = (0, 0, 255)
# Definindo PI
PI = 3.1416
# Desenhando figuras
pygame.draw.line(janela, VERDE, (60, 260), (420, 260), 4)
pygame.draw.polygon(janela, PRETO, ((191, 206), (236, 277), (156, 277)),0)
pygame.draw.circle(janela, AZUL, (300, 50), 20, 0)
pygame.draw.ellipse(janela, VERMELHO, (400, 250, 40, 80), 1)
pygame.draw.rect(janela, VERDE, (20, 20, 60, 40), 0)
pygame.draw.arc(janela, VERMELHO, [250, 75, 150, 125], PI/2, 3*PI/2, 2)
pygame.draw.arc(janela, PRETO, [250, 75, 150, 125], -PI/2, PI/2, 2)
deve_continuar = True
while deve_continuar:
#Loop para checar eventos
for event in pygame.event.get():
#Condicional para sair do loop
if event.type == pygame.QUIT:
deve_continuar = False
pygame.quit()
Após importar pygame, definimos algumas cores e a variável PI. Usamos alguns no-
mes de variáveis em letras maiúsculas, pois queremos que estes valores sejam constantes,
ou seja, em nenhum momento alteraremos o valor destas variáveis. O uso de variáveis em
maiúsculas para constantes é apenas uma convenção na programação, ou seja, não é algo
que deva ser feito desse jeito, mas é costume em muitas linguagens.
import pygame
# Definindo as cores
PRETO = (0, 0, 0)
BRANCO = (255, 255, 255)
VERMELHO = (255, 0, 0)
VERDE = (0, 255, 0)
AZUL = (0, 0, 255)
# Definindo PI
PI = 3.1416
Estas cores formam o que é conhecido como sistema de cores RGB. Em pygame re-
presentamos estes valores como uma tupla de três inteiros com valores entre 0 e 255 cada
um. Sendo que o primeiro valor da tupla corresponde à quantidade de vermelho, o segundo
à quantidade de verde e o último à quantidade de azul.
janela.fill(BRANCO)
Só será visível se
pygame.display.update()
linha. No código foi passado o valor True, pois queremos suavizado. O terceiro parâmetro é
a cor do texto e o quarto parâmetro a cor do fundo do texto. Com isto temos a imagem do
texto, porém, ainda precisamos dizer onde o texto será colocado. Para isto precisamos do
método blit().
Cor de Fundo
Texto a Cor do
ser inserido Texto
Posição em janela
janela.blit(texto, [30, 150])
Desenha texto em janela
Origem
(0,0)
0
Altura
da Janela
0
Largura da Janela
Coordenadas
Onde será Cor
dos vértices
desenhado
Coordenadas
do centro
pygame.draw.circle(janela, AZUL, (300, 50), 20, 0)
A seguinte figura é uma elipse, criada com a função pygame.draw.ellipse(). Esta fun-
ção é similar à pygame.draw.circle(), com uma diferença: em vez de passar as coordenadas
do centro do círculo e o raio, uma tupla de quatro inteiros indicando a posição da esquerda
(em relação ao eixo x - horizontal), do topo (en relação ao eixo y - vertical), a largura e a altura
da elipse é passada.
Topo
Esquerda Largura
Altura
pygame.draw.ellipse(janela, VERMELHO, (400, 250, 40, 80), 1)
Topo
Esquerda Largura
Altura
pygame.draw.rect(janela, VERDE, (20, 20, 60, 40), 0)
Largura da linha
Se 0 ou nada,
figura é preenchida
Para finalizar as figuras, desenhamos dois arcos para formarem uma elipse de duas
cores. A diferença aqui são o quarto e quinto parâmetros. Estes se referem ao ângulo inicial e
final, em radianos, com o 0 à direita.
Relação entre
graus e radianos
~
graus 90o /2 radianos
=
~
180o 0o 0
=
~
360o 2
=
~
270o 3 /2
=
pygame.display.update()
Exibe tudo
o que
inserimos
em janela
Assim como no programa anterior, este loop apenas mantém a janela aberta até que
desejemos fechá-la. Futuramente, toda a ação do jogo estará aqui dentro.
deve_continuar = True
while deve_continuar:
#Loop para checar eventos
for event in pygame.event.get():
#Condicional para sair do loop
if event.type == pygame.QUIT:
deve_continuar = False
Programa 3:
Animação
# definindo as cores
PRETO = (0, 0, 0)
AMARELO = (255, 255, 0)
VERMELHO = (255, 0, 0)
VERDE = (0, 255, 0)
AZUL = (0, 0, 255)
# criando a janela
janela = pygame.display.set_mode((LARGURAJANELA, ALTURAJANELA))
pygame.display.set_caption(‘Animação’)
# criando as figuras
f1 = {‘objRect’: pygame.Rect(300, 80, 40, 80), ‘cor’: VERMELHO, ‘vel’: [0,-5], ‘forma’: ‘ELIPSE’}
f2 = {‘objRect’: pygame.Rect(200, 200, 20, 20), ‘cor’: VERDE, ‘vel’: [5,5], ‘forma’: ‘ELIPSE’}
f3 = {‘objRect’: pygame.Rect(100, 150, 60, 60), ‘cor’: AZUL, ‘vel’: [-5,5], ‘forma’: ‘RETANGULO’}
f4 = {‘objRect’: pygame.Rect(200, 150, 80, 40), ‘cor’: AMARELO, ‘vel’: [5,0], ‘forma’: ‘RETANGULO’}
deve_continuar = True
# loop do jogo
while deve_continuar:
#checando se ocorreu um evento QUIT
for evento in pygame.event.get():
if evento.type == pygame.QUIT:
deve_continuar = False
# definindo as cores
PRETO = (0, 0, 0)
AMARELO = (255, 255, 0)
VERMELHO = (255, 0, 0)
VERDE = (0, 255, 0)
AZUL = (0, 0, 255)
Continuando, foi definida a função mover(). Esta função terá como parâmetros uma
figura e as dimensões da janela. Cada figura será um dicionário e as dimensões da janela
estarão em uma tupla. A função se encarregará de dar as novas coordenadas às figuras que
receber como argumento.
Será um dicionário
figura[‘objRect’].x += figura[‘vel’][0]
figura[‘objRect’].y += figura[‘vel’][1]
# criando a janela
janela = pygame.display.set_mode((LARGURAJANELA, ALTURAJANELA))
pygame.display.set_caption(‘Animação’)
# criando as figuras
f1 = {‘objRect’: pygame.Rect(300, 80, 40, 80), ‘cor’: VERMELHO, ‘vel’: [0,-5], ‘forma’: ‘ELIPSE’}
f2 = {‘objRect’: pygame.Rect(200, 200, 20, 20), ‘cor’: VERDE, ‘vel’: [5,5], ‘forma’: ‘ELIPSE’}
f3 = {‘objRect’: pygame.Rect(100, 150, 60, 60), ‘cor’: AZUL, ‘vel’: [-5,5], ‘forma’: ‘RETANGULO’}
f4 = {‘objRect’: pygame.Rect(200, 150, 80, 40), ‘cor’: AMARELO, ‘vel’: [5,0], ‘forma’: ‘RETANGULO’}
Chegou a hora de falar sobre a estrutura de cada figura. Cada figura é representada
por um dicionário que contém 4 chaves (objRect, cor, vel e forma).
• A chave objRect contém um objeto pygame.Rect criado a partir de realizar py-
game.Rect(x,y,l,a), onde x e y correspondem às coordenadas do canto superior
esquerdo do retângulo em relação a um outro objeto Surface, l à largura e a à al-
tura da figura. Objetos do tipo pygame.Rect são úteis para armazenar e manipular
áreas retangulares. Perceba que estamos usando este tipo de objeto até mesmo
para trabalhar com elipses.
Objeto Rect
Pense nele como um retângulo invisível que envolve a figura que vamos dese-
nhar.
Este tipo de objeto tem muitos atributos, entre eles left (ou x), right, top (ou y) e
bottom, que guardam as posições de cada lado do retângulo.
# criando as figuras
f1 = {‘objRect’: pygame.Rect(300, 80, 40, 80), ‘cor’: VERMELHO, ‘vel’: [0,-5], ‘forma’: ‘ELIPSE’}
• A chave vel guarda uma lista com dois elementos referentes ao valor em que as
posições x e y irão variar. Lembrando que a coordenada x cresce para a direita e a
coordenada y cresce para baixo, se tivermos [3,3] significa que a figura se moverá
3 pixels para direita e 3 para baixo; se tivermos [3,-3] significa que a figura se mo-
verá 3 pixels para a direita e 3 para cima; já se tivermos [-3,0] a figura se moverá
3 pixels para a esquerda e não se moverá na vertical.
f1 = {‘objRect’: pygame.Rect(300, 80, 40, 80), ‘cor’: VERMELHO, ‘vel’: [0,-5], ‘forma’: ‘ELIPSE’}
y cresce
para baixo
• A chave forma guarda uma string com a forma da figura. No caso usamos apenas
‘ELIPSE’ e ‘RETANGULO’, já que círculos e quadrados são casos especiais destes
tipos.
Podemos ver que a parte que corresponde ao loop está maior, se comparado com
a dos programas anteriores. Antes de entrar no loop, inicializamos a variável deve_continuar
com o valor True, uma vez que queremos que o loop seja executado.
deve_continuar = True
# loop do jogo
while deve_continuar:
#checando se ocorreu um evento QUIT
for evento in pygame.event.get():
if evento.type == pygame.QUIT:
deve_continuar = False
• Criamos um outro loop (loop for, desta vez) onde cada figura será reposicionada
e desenhada. Perceba que, nas funções pygame.draw.rect() e pygame.draw.ellip-
se(), passamos o objeto pygame.Rect (ou simplesmente Rect, para simplificar)
como terceiro argumento, enquanto que no programa anterior usávamos uma
tupla contendo as coordenadas e dimensões da figura. Fazemos isto porque o
objeto Rect de cada figura é que está guardando estes dados atualizados.
• Retardamos a execução por 0.02 segundos. Para isto usamos a função sleep()
do módulo time. Ela recebe um número que será a quantidade de segundos na
qual a execução ficará pausada.
Para finalizar, fechamos os módulos de pygame uma vez que saímos do loop.
Programa 4:
Colisão
No programa anterior vimos como fazer com que figuras se movimentem. Agora,
queremos que exista algum tipo de interação entre as figuras. Ou seja, que aconteça alguma
coisa quando entrem em contato. Por exemplo, um muro pode impedir que a personagem
se movimente em certas direções; ou a personagem pode adquirir uma moeda quando toca
nela. O código deste capítulo se encontra em p4_colisao.py.
import pygame
# definindo as cores
PRETO = (0, 0, 0)
AMARELO = (255, 255, 0)
VERMELHO = (255, 0, 0)
VERDE = (0, 255, 0)
AZUL = (0, 0, 255)
BRANCO = (255, 255, 255)
# inicializando pygame
pygame.init()
# criando a janela
janela = pygame.display.set_mode((LARGURAJANELA, ALTURAJANELA))
pygame.display.set_caption(‘Colisão’)
# criando a bola
bola = {‘objRect’: pygame.Rect(270, 330, 30, 30), ‘cor’: BRANCO, ‘vel’: [3,3]}
deve_continuar = True
# loop do jogo
while deve_continuar:
# checando se ocorreu um evento QUIT
for evento in pygame.event.get():
if evento.type == pygame.QUIT:
deve_continuar = False
Nota: Já usamos a palavra “iteração” no programa anterior quando falamos do loop do jogo e usamos
“interação” no parágrafo anterior. A falta do “n” não foi uma distração durante a escrita, elas são palavras
distintas. “Iteração” significa “repetição” e “interação” significa “contato”.
Aqui podemos ver que foi importado o módulo pygame, definidas algumas cores, as
dimensões da janela, a função mover() e inicializados os módulos de Pygame, como já visto
antes.
import pygame
# definindo as cores
PRETO = (0, 0, 0)
AMARELO = (255, 255, 0)
VERMELHO = (255, 0, 0)
VERDE = (0, 255, 0)
AZUL = (0, 0, 255)
BRANCO = (255, 255, 255)
# inicializando pygame
pygame.init()
Na próxima linha temos algo não visto anteriormente: o objeto Clock. Este objeto
pertence ao módulo time de pygame. Ele é criado com a chamada pygame.time.Clock() e
guardado na variável relogio.
Algo a ser notado, também, é que no programa anterior usamos uma função (sle-
ep()) do módulo time de Python e aqui estamos usando o objeto Clock que está definido no
módulo time de Pygame! Estes módulos, apesar de possuírem o mesmo nome, não são os
mesmos!
Python Pygame
Em seguida criamos a janela, alguns blocos e a bola (que se chocará com os blocos).
Estes elementos foram criados de forma muito parecida com o realizado no programa ante-
rior. Também inicializamos o valor da variável deve_continuar antes de entrar no loop do jogo.
# criando a janela
janela = pygame.display.set_mode((LARGURAJANELA, ALTURAJANELA))
pygame.display.set_caption(‘Colisão’)
# criando a bola
bola = {‘objRect’: pygame.Rect(270, 330, 30, 30), ‘cor’: BRANCO, ‘vel’: [3,3]}
deve_continuar = True
Programa 5:
Teclado e Mouse
No programa anterior vimos como figuras podem interagir, ou seja, que algo acon-
tece quando elas entram em contato. No caso, o círculo mudava de cor quando colidia com
algum quadrado. Agora, veremos que a colisão fará com que uma das figuras desapareça,
como se ela fosse comida pela outra figura. Também veremos como controlar uma das figu-
ras usando o teclado, e como criar outras usando o botão do mouse. Afinal, em todo jogo tem
que haver algum tipo de interação do jogador.
# definindo as cores
PRETO = (0, 0, 0)
VERDE = (0, 255, 0)
BRANCO = (255, 255, 255)
# inicializando pygame
pygame.init()
relogio = pygame.time.Clock()
# criando janela
janela = pygame.display.set_mode((LARGURAJANELA, ALTURAJANELA))
pygame.display.set_caption(‘Teclado e Mouse’)
# criando jogador
jogador = {‘objRect’: pygame.Rect(300, 100, 50, 50), ‘cor’: VERDE, ‘vel’: VEL}
# loop do jogo
while deve_continuar:
# checando os eventos
for evento in pygame.event.get():
if evento.type == pygame.QUIT:
deve_continuar = False
contador += 1
if contador >= ITERACOES:
# adicionando um novo bloco
contador = 0
posX = random.randint(0, LARGURAJANELA - TAMANHOBLOCO)
posY = -TAMANHOBLOCO
velRandom = random.randint(1, VEL + 3)
blocos.append({‘objRect’: pygame.Rect(posX, posY, TAMANHOBLOCO, TAMANHOBLOCO), ‘cor’: BRANCO, ‘vel’: velRandom})
# movendo o jogador
moverJogador(jogador, teclas, (LARGURAJANELA, ALTURAJANELA))
# desenhando jogador
pygame.draw.rect(janela, jogador[‘cor’], jogador[‘objRect’])
# checando se jogador bateu em algum bloco ou se bloco saiu da janela para retirá-lo da lista
for bloco in blocos[:]:
bateu = jogador[‘objRect’].colliderect(bloco[‘objRect’])
if bateu or bloco[‘objRect’].y > ALTURAJANELA:
blocos.remove(bloco)
# atualizando a janela
pygame.display.update()
relogio.tick(40)
# definindo as cores
PRETO = (0, 0, 0) Já vimos isso...
VERDE = (0, 255, 0)
BRANCO = (255, 255, 255)
Após, temos a definição da função moverBloco(). Com ela é que cada bloco guarda
sua nova posição, de acordo com sua velocidade.
def moverBloco(bloco):
bloco[‘objRect’].y += bloco[‘vel’]
# inicializando pygame
pygame.init()
relogio = pygame.time.Clock()
# criando janela
janela = pygame.display.set_mode((LARGURAJANELA, ALTURAJANELA))
pygame.display.set_caption(‘Teclado e Mouse’)
Depois criamos jogador, que será um dicionário com as chaves objRect, cor e vel. Es-
tas chaves guardarão características referentes às coordenadas e dimensões (objRect), cor
(cor) e velocidade (vel).
# criando jogador
jogador = {‘objRect’: pygame.Rect(300, 100, 50, 50), ‘cor’: VERDE, ‘vel’: VEL}
Na linha seguinte podemos ver que temos um dicionário guardado na variável teclas.
Existem quatro chaves (esquerda, direita, cima, baixo), todas elas com o valor False. Este di-
cionário será o encarregado de registrar as teclas pressionadas. Quando alguma tecla dire-
cional (teclas de setas e as teclas A, S, D e W) estiver sendo pressionada, o valor correspon-
dente mudará para True.
Também foram criadas algumas variáveis que serão úteis, como contador e blocos,
além de deve_continuar que já foi usada e explicada em códigos anteriores.
A variável contador será responsável pelo número de repetições. Inicialmente terá o
valor 0 e a cada execução do loop do jogo este valor será incrementado em uma unidade. Isto
acontecerá até atingir o valor de ITERACOES, quando voltará ao valor 0.
Já a variável blocos será a encarregada de guardar todos os blocos presentes no jogo.
Perceba que ela é uma lista vazia, pois, inicialmente, o jogo não contém blocos.
while deve_continuar:
# checando os eventos
for evento in pygame.event.get():
if evento.type == pygame.QUIT:
deve_continuar = False
Quando o tipo de evento é KEYDOWN, o evento terá um atributo chamado key. Este
atributo faz referência à tecla que provocou o evento. Podemos ver algumas “constantes” no
código, como K_ESCAPE, K_LEFT, K_RIGHT, K_UP e K_DOWN. Elas se referem à tecla ESC e às
setas para esquerda, direita, cima e baixo, respectivamente.
As teclas alfanuméricas podem ser referidas através de K_<tecla>. Para referirmos
à tecla A, por exemplo, devemos fazer: K_a . No código, pressionar a tecla A terá o mesmo
comportamento do que pressionar a seta da esquerda. Isto mudará a chave esquerda do
dicionário teclas para True, indicando que umas das teclas que movimentará jogador para a
esquerda foi pressionada. Para as outras teclas de movimentação ocorre algo semelhante.
Atributo KEY
Tecla de seta esquerda gera mesmo efeito que a tecla A;
Tecla de seta direita gera mesmo efeito que a tecla D;
Tecla de seta para cima gera mesmo efeito que a tecla W;
Tecla de seta para baixo gera mesmo efeito que a tecla S.
Também podemos ver, no código, que ao pressionarmos a tecla ESC a variável deve_
continuar mudará para False, com isso não se entrará no loop do jogo novamente, fazendo
com que o jogo termine.
Se deixarmos de pressionar algumas das teclas, o valor da chave que indica sua dire-
ção será mudado para False.
Também podemos ver que algo acontece quando pressionamos um dos botões do
mouse. Isto provoca o surgimento de um novo bloco no local onde se encontra o cursor, no
momento em que o botão é pressionado (dentro da janela). Eventos relacionados a alguma
ação do mouse possuem um atributo chamado pos, que consiste de uma tupla contendo as
coordenadas x (pos[0]) e y (pos[1]) do cursor do mouse na janela.
contador += 1
if contador >= ITERACOES:
# adicionando um novo bloco
contador = 0
posX = random.randint(0, LARGURAJANELA - TAMANHOBLOCO)
posY = -TAMANHOBLOCO
velRandom = random.randint(1, VEL + 3)
blocos.append({‘objRect’: pygame.Rect(posX, posY, TAMANHOBLOCO, TAMANHOBLOCO), ‘cor’: BRANCO, ‘vel’: velRandom})
# movendo o jogador
moverJogador(jogador, teclas, (LARGURAJANELA, ALTURAJANELA))
# desenhando jogador
pygame.draw.rect(janela, jogador[‘cor’], jogador[‘objRect’])
• Examinamos cada bloco para verificar se colidiu com jogador. Se isto ocorreu, ou
se o bloco saiu da janela, o eliminamos da lista de blocos usando o método remo-
ve() de listas. Já falamos sobre este método quando falamos de listas na primeira
parte do tutorial. Revisando, o método remove() elimina da lista o elemento pas-
sado como argumento.
Aqui vem outra questão importante. Poderia se pensar na não necessidade de
remover o bloco quando ele sai da janela, uma vez que ele não interagirá mais
com jogador. Por mais que sua representação gráfica não esteja presente na tela,
o restante de seus dados continua na memória do computador. É para evitar que
informação desnecessária ocupe lugar na memória que removemos o bloco.
# checando se jogador bateu em algum bloco ou se bloco saiu da janela para retirá-lo da lista
for bloco in blocos[:]:
bateu = jogador[‘objRect’].colliderect(bloco[‘objRect’])
if bateu or bloco[‘objRect’].y > ALTURAJANELA:
blocos.remove(bloco)
# atualizando a janela
pygame.display.update()
Programa 6:
Imagem e Som
# carregando imagens
imagemTubarao = pygame.image.load(‘tubarao.png’)
imagemPeixe = pygame.image.load(‘peixe.png’)
imagemFundo = pygame.image.load(‘cenario.png’)
# inicializando pygame
pygame.init()
relogio = pygame.time.Clock()
# criando janela
janela = pygame.display.set_mode((LARGURAJANELA, ALTURAJANELA))
pygame.display.set_caption(‘Imagem e Som’)
# criando jogador
jogador = {‘objRect’: pygame.Rect(300,100,LARGURATUBARAO,ALTURATUBARAO), ‘imagem’: imagemTubarao, ‘vel’: VEL}
# configurando o som
somComer = pygame.mixer.Sound(‘comer.wav’)
pygame.mixer.music.load(‘musica.mid’)
pygame.mixer.music.play(-1, 0.0)
somAtivado = True
# loop do jogo
while deve_continuar:
# checando os eventos
for evento in pygame.event.get():
if evento.type == pygame.QUIT:
deve_continuar = False
contador += 1
if contador >= ITERACOES:
# adicionando um novo peixe
contador = 0
posY = random.randint(0, ALTURAJANELA - ALTURAPEIXE)
posX = -LARGURAPEIXE
velRandom = random.randint(VEL - 3, VEL + 3)
peixes.append({‘objRect’: pygame.Rect(posX, posY,LARGURAPEIXE,ALTURAPEIXE), ‘imagem’: imagemPeixe, ‘vel’: velRandom})
# movendo jogador
moverJogador(jogador, teclas, (LARGURAJANELA, ALTURAJANELA))
# desenhando jogador
janela.blit(jogador[‘imagem’], jogador[‘objRect’])
# checando se jogador comeu algum peixe ou se o peixe saiu da janela para retirá-lo da lista
for peixe in peixes[:]:
comeu = jogador[‘objRect’].colliderect(peixe[‘objRect’])
if comeu and somAtivado:
somComer.play()
if comeu or peixe[‘objRect’].x > LARGURAJANELA:
peixes.remove(peixe)
# atualizando a janela
pygame.display.update()
relogio.tick(40)
A seguir, carregamos as imagens que usaremos. No caso serão três imagens. Uma
para representar o elemento que controlamos (tubarao), outra para representar o elemento
com que interagimos (peixe) e a última será a imagem de fundo.
Para carregar as imagens usamos a função load() do módulo image. Devemos pas-
sar como argumento uma string com o nome do arquivo da imagem a ser carregada. Essa
função devolve um objeto do tipo pygame.Surface que contém a imagem do arquivo dese-
nhada na sua superfície. No código, guardamos os respectivos objetos nas variáveis imagem-
Tubabao e imagemPeixe. Note que os arquivos de imagem devem estar na mesma pasta do
arquivo com o código que as usará (no caso, p6_imagemsom) ou será necessário, então,
colocar o endereço completo do arquivo.
Definimos algumas constantes. Algumas delas foram definidas a partir das dimen-
sões das imagens. Objetos Surface possuem os métodos get_width() e get_height() que nos
devolvem a largura e a altura do objeto em pixels. Desta forma encontramos as dimensões
que usaremos mais adiante na hora de criar os dicionários que representarão o tubarão e os
peixes. Note que as imagens do tubarão e peixe são bem menores da que usaremos para o
fundo da janela. Caso contrário teríamos que redimensioná-las para que fiquem em um ta-
manho adequado.
Já moverBloco() ficou ligeiramente alterada, também alteramos seu nome para mo-
verPeixe(). No programa anterior os blocos se moviam na vertical; agora seus equivalentes,
os peixes, se moverão na horizontal.
# inicializando pygame
pygame.init()
relogio = pygame.time.Clock()
# criando janela
janela = pygame.display.set_mode((LARGURAJANELA, ALTURAJANELA))
pygame.display.set_caption(‘Imagem e Som’)
Logo a seguir criamos o dicionário que representará o jogador. Ele é muito parecido
ao do programa anterior, a diferença básica é que em vez de uma cor, agora usamos uma
imagem. Para isso, substituímos a chave cor pela chave imagem, que terá como valor o obje-
to Surface que conterá a imagem.
# criando jogador
jogador = {‘objRect’: pygame.Rect(300,100,LARGURATUBARAO,ALTURATUBARAO), ‘imagem’: imagemTubarao, ‘vel’: VEL}
O segundo parâmetro indica em que ponto da música ela iniciará. Passando 0.0, a música
começará a ser tocada desde o começo. Se for passado 2.5, por exemplo, a música de fundo
começará na posição correspondente a 2.5 segundos desde seu início.
Por último, temos uma variável booleana chamada somAtivado que indicará se a
música e os efeitos sonoros estão ligados ou não, caso o jogador prefira jogar sem som.
# configurando o som
somComer = pygame.mixer.Sound(‘comer.wav’)
pygame.mixer.music.load(‘musica.mid’)
pygame.mixer.music.play(-1, 0.0)
somAtivado = True A música será tocada desde o seu começo.
# loop do jogo
while deve_continuar:
# checando os eventos
for evento in pygame.event.get():
if evento.type == pygame.QUIT:
deve_continuar = False
• Criamos um novo peixe se o valor de contador assim o indicar. Este peixe será
criado logo à esquerda da janela e em uma posição vertical aleatória dentro dela.
Também terá uma velocidade ligeiramente diferente daquela de jogador, escolhi-
da entre certos valores.
contador += 1
if contador >= ITERACOES:
# adicionando um novo peixe
contador = 0
posY = random.randint(0, ALTURAJANELA - ALTURAPEIXE) Posição vertical aleatória
posX = -LARGURAPEIXE
velRandom = random.randint(VEL - 3, VEL + 3) Velocidade escolhida de acordo com o intervalo
peixes.append({‘objRect’: pygame.Rect(posX, posY,LARGURAPEIXE,ALTURAPEIXE), ‘imagem’: imagemPeixe, ‘vel’: velRandom})
# movendo jogador
moverJogador(jogador, teclas, (LARGURAJANELA, ALTURAJANELA))
# desenhando jogador
janela.blit(jogador[‘imagem’], jogador[‘objRect’])
• Checamos cada peixe para ver se ele colidiu com jogador. Se isto ocorreu e o som
estiver ativado, será emitido um som. Ele também será eliminado da lista se tiver
colidido ou passado da largura da janela.
# checando se jogador comeu algum peixe ou se o peixe saiu da janela para retirá-lo da lista
for peixe in peixes[:]: Verifica se peixe colidiu com jogador
comeu = jogador[‘objRect’].colliderect(peixe[‘objRect’])
if comeu and somAtivado:
Se colidiu e o som estiver ativado, emitir som
somComer.play()
if comeu or peixe[‘objRect’].x > LARGURAJANELA:
peixes.remove(peixe)
Se colidiu ou passou da largura da janela, remover da lista
# atualizando a janela
pygame.display.update()
relogio.tick(40)
Programa 7:
Jogo
Começamos esta parte do curso com um programinha que nos mostrou como criar
uma janela. Fomos evoluindo esse programa com a inserção de figuras, movimentação, in-
teração entre elas, controle, uso de imagens e som; para finalmente chegarmos ao objetivo:
um jogo! O código do jogo se encontra no arquivo p7_jogo.py. Ele consiste em uma nave,
controlada pelo jogador, que tem que evitar se chocar com asteroides. Para isto ela pode
desviá-los ou atirar raios laser para destruí-los. A pontuação está relacionada com o tempo
de vida (mais precisamente, com o número de repetições do loop do jogo), quanto maior o
tempo em que conseguir evitar os asteroides, maior a pontuação do jogador.
# Carregando as imagens.
imagemNave = pygame.image.load(‘nave.png’)
imagemAsteroide = pygame.image.load(‘asteroide.png’)
imagemRaio = pygame.image.load(‘raio.png’)
imagemFundo = pygame.image.load(‘magellanic-clouds.png’)
LARGURANAVE = imagemNave.get_width()
ALTURANAVE = imagemNave.get_height()
LARGURARAIO = imagemRaio.get_width()
ALTURARAIO = imagemRaio.get_height()
def moverElemento(elemento):
elemento[‘objRect’].x += elemento[‘vel’][0]
elemento[‘objRect’].y += elemento[‘vel’][1]
def terminar():
# Termina o programa.
pygame.quit()
exit()
def aguardarEntrada():
# Aguarda entrada por teclado ou clique do mouse no “x” da janela.
while True:
for evento in pygame.event.get():
if evento.type == pygame.QUIT:
terminar()
if evento.type == pygame.KEYDOWN:
if evento.key == pygame.K_ESCAPE:
terminar()
return
# Configurando a fonte.
fonte = pygame.font.Font(None, 48)
# Configurando o som.
somFinal = pygame.mixer.Sound(‘final_fx.wav’)
somRecorde = pygame.mixer.Sound(‘record.wav’)
somTiro = pygame.mixer.Sound(‘laser.wav’)
pygame.mixer.music.load(‘trilha_nave.wav’)
# Tela de inicio.
colocarTexto(‘Asteroides Troianos’, fonte, janela, LARGURAJANELA / 5, ALTURAJANELA / 3)
colocarTexto(‘Pressione uma tecla para começar.’, fonte, janela, LARGURAJANELA / 20 , ALTURAJANELA / 2)
pygame.display.update()
aguardarEntrada()
recorde = 0
while True:
# Configurando o começo do jogo.
asteroides = [] # lista com os asteroides
raios = [] # lista com os raios
pontuacao = 0 # pontuação
deve_continuar = True # indica se o loop do jogo deve continuar
# direções de movimentação
teclas = {}
teclas[‘esquerda’] = teclas[‘direita’] = teclas[‘cima’] = teclas[‘baixo’] = False
contador = 0 # contador de iterações
pygame.mixer.music.play(-1, 0.0) # colocando a música de fundo
# Criando jogador.
posX = LARGURAJANELA / 2
posY = ALTURAJANELA - 50
jogador = {‘objRect’: pygame.Rect(posX, posY, LARGURANAVE, ALTURANAVE), ‘imagem’: imagemNave, ‘vel’: VELJOGADOR}
while deve_continuar:
pontuacao += 1
if pontuacao == recorde:
somRecorde.play()
if evento.type == pygame.KEYDOWN:
if evento.key == pygame.K_ESCAPE:
terminar()
if evento.key == pygame.K_LEFT or evento.key == pygame.K_a:
teclas[‘esquerda’] = True
if evento.key == pygame.K_RIGHT or evento.key == pygame.K_d:
teclas[‘direita’] = True
if evento.key == pygame.K_UP or evento.key == pygame.K_w:
teclas[‘cima’] = True
if evento.key == pygame.K_DOWN or evento.key == pygame.K_s:
teclas[‘baixo’] = True
if evento.key == pygame.K_SPACE:
raio = {‘objRect’: pygame.Rect(jogador[‘objRect’].centerx, jogador[‘objRect’].top, LARGURARAIO, ALTURARAIO),
‘imagem’: imagemRaio,
‘vel’: VELRAIO}
raios.append(raio)
somTiro.play()
if evento.type == pygame.KEYUP:
if evento.key == pygame.K_LEFT or evento.key == pygame.K_a:
teclas[‘esquerda’] = False
if evento.key == pygame.K_RIGHT or evento.key == pygame.K_d:
teclas[‘direita’] = False
if evento.key == pygame.K_UP or evento.key == pygame.K_w:
teclas[‘cima’] = False
if evento.key == pygame.K_DOWN or evento.key == pygame.K_s:
teclas[‘baixo’] = False
if evento.type == pygame.MOUSEMOTION:
# Se o mouse se move, movimenta jogador para onde o cursor está.
centroX_jogador = jogador[‘objRect’].centerx
centroY_jogador = jogador[‘objRect’].centery
jogador[‘objRect’].move_ip(evento.pos[0] - centroX_jogador, evento.pos[1] - centroY_jogador)
if evento.type == pygame.MOUSEBUTTONDOWN:
raio = {‘objRect’: pygame.Rect(jogador[‘objRect’].centerx, jogador[‘objRect’].top, LARGURARAIO, ALTURARAIO),
‘imagem’: imagemRaio,
‘vel’: VELRAIO}
raios.append(raio)
somTiro.play()
# Colocando as pontuações.
colocarTexto(‘Pontuação: ‘ + str(pontuacao), fonte, janela, 10, 0)
colocarTexto(‘Recorde: ‘ + str(recorde), fonte, janela, 10, 40)
pygame.display.update()
relogio.tick(QPS)
# Carregando as imagens.
imagemNave = pygame.image.load(‘nave.png’)
imagemAsteroide = pygame.image.load(‘asteroide.png’)
imagemRaio = pygame.image.load(‘raio.png’)
imagemFundo = pygame.image.load(‘magellanic-clouds.png’)
LARGURANAVE = imagemNave.get_width()
ALTURANAVE = imagemNave.get_height()
LARGURARAIO = imagemRaio.get_width()
ALTURARAIO = imagemRaio.get_height()
def moverElemento(elemento):
elemento[‘objRect’].x += elemento[‘vel’][0]
elemento[‘objRect’].y += elemento[‘vel’][1]
def terminar():
# Termina o programa.
pygame.quit()
exit()
No capítulo “Figuras e Texto” mostramos como incluir um texto na janela. Neste pro-
grama também usaremos texto.
A função colocarTexto() se encarrega de pôr um determinado texto em um determi-
nado lugar. Ela tem os parâmetros texto, fonte, janela, x e y. O primeiro é a string que será co-
locada; o segundo é a fonte (que inclui o tamanho) a ser usada; o terceiro é o objeto Surface
onde aparecerá tal texto; e os dois últimos são as coordenadas, no objeto Surface passado
como argumento, onde será colocado o texto.
Tipo e tamanho
da fonte
Objeto Surface
onde aparecerá
o texto
No seu interior foi usado o método get_rect() de objetos do tipo Surface (objTexto,
neste caso). Este método devolve um retângulo (objeto do tipo Rect) “cobrindo” a superfície
do objeto que o chamou. Lembrando que um objeto Rect guarda as informações de tama-
nho e posição do objeto Surface.
Já falamos de alguns atributos de um objeto Rect como bottom, top, left e right. Ou-
tro atributo destes objetos é o topleft, que é como uma combinação dos atributos top e left.
Assim, com uma tupla (ou lista) passamos as coordenadas do canto superior esquerdo do
retângulo.
Esta função termina com o uso do método blit() que “desenha” o texto na janela.
# Configurando a fonte.
fonte = pygame.font.Font(None, 48)
# Configurando o som.
somFinal = pygame.mixer.Sound(‘final_fx.wav’)
somRecorde = pygame.mixer.Sound(‘record.wav’)
somTiro = pygame.mixer.Sound(‘laser.wav’)
pygame.mixer.music.load(‘trilha_nave.wav’)
Usamos a função que definimos colocarTexto() para colocar os textos iniciais, atu-
alizamos a janela e pausamos o jogo até que seja pressionada uma tecla que não seja ESC
para iniciar o jogo.
# Tela de inicio.
colocarTexto(‘Asteroides Troianos’, fonte, janela, LARGURAJANELA / 5, ALTURAJANELA / 3)
colocarTexto(‘Pressione uma tecla para começar.’, fonte, janela, LARGURAJANELA / 20 , ALTURAJANELA / 2)
pygame.display.update() Atualizar janela
aguardarEntrada()
Pausamos o jogo até que uma tecla
(que não seja ESC) seja acionada
Chegamos a um loop while que contém em seu interior o loop do jogo. Esse loop se
repete enquanto o jogador quiser continuar jogando após ter batido em um asteroide, evitan-
do ter que iniciar o programa novamente para jogar. Vejamos o que acontece no loop. Mas
antes de entrar nele, inicializamos a variável recorde. Ela guardará os recordes atualizados.
Nesse loop, acontece:
• Inicializamos todas as variáveis necessárias, ativamos a música e criamos o di-
cionário jogador, guardando nele o objeto Rect que o representará, a imagem e
sua velocidade.
recorde = 0
while True:
# Configurando o começo do jogo.
asteroides = [] # lista com os asteroides
raios = [] # lista com os raios
pontuacao = 0 # pontuação
deve_continuar = True # indica se o loop do jogo deve continuar
# direções de movimentação
teclas = {}
teclas[‘esquerda’] = teclas[‘direita’] = teclas[‘cima’] = teclas[‘baixo’] = False
contador = 0 # contador de iterações
pygame.mixer.music.play(-1, 0.0) # colocando a música de fundo
# Criando jogador.
posX = LARGURAJANELA / 2
posY = ALTURAJANELA - 50
jogador = {‘objRect’: pygame.Rect(posX, posY, LARGURANAVE, ALTURANAVE), ‘imagem’: imagemNave, ‘vel’: VELJOGADOR}
• Aqui vem toda a ação, é o que temos chamado de loop do jogo ao longo desta
parte do tutorial. Tudo desde a aparição do cenário com a nave e asteroides, até
que um asteroide se choca com ela, acontece aqui. Falaremos deste loop depois.
• Uma vez que saímos do loop do jogo (a nave se chocou com um asteroide), a
música é interrompida, executando o som de fim de jogo, são colocados dois tex-
tos e a função pygame.display.update() é usada para mostrar tudo o que deve
aparecer na janela.
• Finalmente, ocorre uma pausa até que o jogador pressione uma tecla para con-
tinuar jogando ou feche o jogo (pressionando ESC ou fechando a janela). O som
de fim de jogo é interrompido (caso ele já não tenha terminado).
Agora, sim, vamos comentar mais detalhadamente o que acontece no loop do jogo.
• Incrementamos a pontuação. Se ela for igual ao recorde, o som de recorde é to-
cado.
while deve_continuar:
pontuacao += 1
if pontuacao == recorde:
somRecorde.play()
• Checamos por eventos. Esta parte é muito parecida com a do programa anterior.
As principais mudanças são a inserção da tecla ESPAÇO e a movimentação com
o uso do mouse.
Quando pressionamos a tecla ESPAÇO (pygame.K_SPACE, no código) criamos
um raio. Perceba que o raio é criado a partir da posição do objeto Rect de jogador
(nave). Onde foi usado a posição do centro da nave na horizontal (atributo cen-
terx) e a posição do topo da nave na vertical (atributo top).
top
centerx
Após, colocamos a raio na lista de raios e tocamos o som de disparo. Tudo isto
também é realizado quando pressionamos um dos botões do mouse na janela.
if evento.key == pygame.K_SPACE:
raio = {‘objRect’: pygame.Rect(jogador[‘objRect’].centerx, jogador[‘objRect’].top, LARGURARAIO, ALTURARAIO),
‘imagem’: imagemRaio,
‘vel’: VELRAIO}
raios.append(raio)
somTiro.play()
if evento.type == pygame.MOUSEBUTTONDOWN:
raio = {‘objRect’: pygame.Rect(jogador[‘objRect’].centerx, jogador[‘objRect’].top, LARGURARAIO, ALTURARAIO),
‘imagem’: imagemRaio,
‘vel’: VELRAIO}
raios.append(raio)
somTiro.play()
if evento.type == pygame.MOUSEMOTION:
# Se o mouse se move, movimenta jogador para onde o cursor está.
centroX_jogador = jogador[‘objRect’].centerx
centroY_jogador = jogador[‘objRect’].centery
jogador[‘objRect’].move_ip(evento.pos[0] - centroX_jogador, evento.pos[1] - centroY_jogador)
# Colocando as pontuações.
colocarTexto(‘Pontuação: ‘ + str(pontuacao), fonte, janela, 10, 0)
colocarTexto(‘Recorde: ‘ + str(recorde), fonte, janela, 10, 40)
• Fazemos o mesmo com os raios laser. Porém, eliminamos da lista de raios aque-
les que passaram pelo topo da janela.
pygame.display.update()
relogio.tick(QPS)
Créditos: