0% acharam este documento útil (0 voto)
25 visualizações

Tutorial de Pygame (Python)

Este documento descreve os princípios básicos de desenvolvimento de um jogo e motor de jogo usando o framework Pygame em Python. O documento usa como exemplo o desenvolvimento do jogo clássico Pong para ilustrar conceitos como entrada, saída, lógica do jogo e ciclo do motor.

Enviado por

caujonas2
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
25 visualizações

Tutorial de Pygame (Python)

Este documento descreve os princípios básicos de desenvolvimento de um jogo e motor de jogo usando o framework Pygame em Python. O documento usa como exemplo o desenvolvimento do jogo clássico Pong para ilustrar conceitos como entrada, saída, lógica do jogo e ciclo do motor.

Enviado por

caujonas2
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 17

A Anatomia de um Motor de jogo

Texto original e adaptação: António Coelho e Fernando Nunes Ferreira


Colaboração: João Jacob e Tiago Marques

Neste workshop vais aprender os princípios básicos do desenvolvimento de jogos digitais e


compreender o funcionamento de um motor de jogo.
Iremos desenvolver um jogo clássico, que foi um marco na história dos jogos digitais, com o qual
iremos desvendar os princípios de funcionamento de um motor de jogo.
O jogo será desenvolvido em Python, utilizando um conjunto de módulos específicos para o
desenvolvimento de jogos digitais – o Pygame.
O Python é uma linguagem de scripting, relativamente simples, pelo que como pré-requisitos
apenas deverás ter conhecimentos num nível introdutório de programação. E claro, gostares de
jogos digitais...
Deves instalar em primeiro lugar o Python 2.7 (http://www.python.org/download/) e
posteriormente o Pygame (http://www.pygame.org/download.shtml). Existem versões para
Windows, Mac OS X e Linux.

26 de Março de 2013

O ficheiro PDF do tutorial pode ser acedido em:


http://www.fe.up.pt/~acoelho/wsjogos/tutorial.pdf

Este documento serve de apoio ao Workshop “A Anatomia de um Motor de jogo” realizado a 26


de março de 2013 no âmbito do ENEI 2013 - Encontro Nacional de Estudantes de Informática,
Faculdade de Engenharia da Universidade do Porto, Portugal.

1
Vamos desenvolver um jogo clássico... O Pong.

A indústria dos jogos de computador é uma das mais lucrativas e com maior crescimento da
atualidade. Tendo sido considerados como parentes pobres das outras aplicações informáticas
“mais sérias”, os jogos de computador possuem, na atualidade, orçamentos equiparados aos
filmes de Hollywood.

Figura 1 - Pong (Atari Inc.)


Um dos jogos mais marcantes da história dos jogos de computador foi o Pong, criado pela Atari
Inc. em 1972 (ver Figura 1). Não porque tivesse sido o primeiro jogo digital, mas porque foi o
primeiro a ter êxito comercial, quer em máquinas arcade, quer em consolas domésticas, lançando
as bases para a atual indústria dos jogos digitas. Os jogos digitais são, na sua generalidade,
desenvolvidos para o entretenimento. No entanto, cada vez mais esta tecnologia ganha terreno em
outras áreas como a educação ou a formação profissional (game-based learning/training) e as
aplicações para a saúde, para as empresas, para a publicidade, entre muitas outras áreas com
outros propósitos que não apenas o entretenimento (serious games).
O jogo será desenvolvido em Python, utilizando um conjunto de módulos específicos para o
desenvolvimento de jogos digitais – o Pygame. Deve instalar em primeiro lugar o Python 2.7 e
posteriormente o Pygame. Existem versões para Windows, Mac OS X e Linux.

O motor do jogo
O primeiro passo na criação de um jogo é a seleção ou o desenvolvimento do motor de jogo1. Um
motor de jogo é, na sua base, muito simplesmente um ciclo que atualiza todos os objetos e, sendo
a maior parte dos jogos aplicações gráficas interativas, lê os dispositivos de entrada e sintetiza
imagem e som nos dispositivos de saída.

1
Atualmente já existe uma grande diversidade de motores do jogo disponíveis para o
programador com uma extensa gama de funcionalidades.

2
Assim, o motor do jogo realiza as seguintes tarefas de forma cíclica:
1. Dispositivos de entrada (eventos)
2. Lógica do jogo
3. Dispositivos de saída
Em Pygame, o código que implementa este ciclo é o seguinte:
# ciclo de jogo
while True:
# 1. Dispositivos de entrada (eventos)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()

# 2. Logica do jogo

# 3. Dispositivos de saida
pygame.draw.circle(DISPLAYSURF, (255,255,0), (400, 300), 30, 0)
pygame.display.update()

Em que há um ciclo infinito que engloba os três blocos de código. Um ciclo for lê todos os
eventos que tenham sido ativados pelos dispositivos de entrada ou pelo sistema. Neste caso
particular é lido apenas o evento QUIT que serve para terminar o ciclo de jogo e sair do
programa. (Por muito que nos agrade um jogo, ele irá ter mesmo que terminar... )
Após o passo de leitura dos eventos, é preciso atualizar o estado e os objetos de jogo. Neste
exemplo ainda não colocamos nenhum código, que irá aparecendo ao longo das próximas
secções...
Finalmente, o passo 3 envia os objetos para os dispositivos de saída e atualiza o ecrã gráfico,
através da instrução pygame.display.update(). Neste caso particular é desenhado um círculo
amarelo no centro do ecrã.
Mas antes de se definir o ciclo de jogo, é necessário colocar algum código para inicializar
algumas definições do Pygame e o próprio ambiente gráfico:
import pygame, sys
from pygame.locals import *

##############
# Definicoes #
##############

# Dimensoes da janela grafica


janela_largura = 800
janela_altura = 600

#################
# inicializacao #
#################
pygame.init()

# define a janela grafica de desenho


DISPLAYSURF = pygame.display.set_mode((janela_largura, janela_altura))
pygame.display.set_caption('ENEI Pong')

Nas duas primeiras linhas são importados os módulos Pygame e Sys, que disponibilizam os
objetos necessários para a execução do nosso programa.
Segue-se uma secção de definições como é boa prática de programação. Nesta caso são apenas
definidas as dimensões da janela gráfica (largura e altura).

3
Na secção de inicialização chama-se a função pygame.init() e define-se a dimensão da janela
gráfica e o título dessa janela. É nesta secção que se devem inicializar todas as variáveis e objetos
do jogo, antes de se entrar no ciclo de jogo.

LAB1: Espaço para experimentar o código desenvolvido.


Crie este código com o editor IDLE.
Alternativamente pode fazer download do ficheiro pong1.py .
Com este programa básico apenas poderá visualizar um círculo amarelo em fundo
escuro... Nada que se pareça com um jogo digital...

Desenhando no ecrã
Uma das saídas mais importantes para a maioria dos jogos de computador é a imagem (daí que
sejam também conhecidos por videojogos). As imagens são apresentadas em ecrãs de computador
segundo um sistema de referência cartesiano, onde cada objeto geométrico é representado pelos
seus vértices, cada um dos quais se associa a um par de coordenadas (x,y), tal como apresentado
na Figura 2.

(x2,y2)

(x1,y1)
y
X

Figura 2 - Sistema de referência cartesiano.

No Pygame, os gráficos são apresentados em bitmaps, ou seja, matrizes de pixels. Um pixel


("PICture ELement") é o menor elemento que compõe uma imagem e ao qual é possível atribuir-
se uma cor. Desta forma, qualquer imagem em Allegro, inclusivamente o ecrã, é tratado como
uma matriz, com uma determinada dimensão (nº de pixels largura x nº de pixels altura). É
possível atribuir um determinado valor de cor a cada pixel para formar qualquer gráfico, tal como
apresentado na Figura 3.

4
Figura 3 - Definição das imagens através de pixels

O Pygame não opera diretamente no ecrã, por razões que têm que ver com restrições impostas
pelos sistemas operativos, mas sim em janelas gráficas. As coordenadas destas janelas são valores
inteiros entre 0 e as dimensões da imagem (subtraídos de 1). Ou seja, tomando como exemplo
uma janela com dimensões 800x600, a coordenada x pode tomar valores entre 0 e 799 e a
coordenada y pode tomar valores entre 0 e 599. A origem do referencial é o canto superior
esquerdo.
Já consegue perceber o que faz a seguinte instrução:
DISPLAYSURF = pygame.display.set_mode((janela_largura, janela_altura))

Cria uma janela gráfica com as dimensões definidas pelas variáveis janela_largura e
janela_altura. Neste caso particular as dimensões indicadas foram 800x600.

Figura 4 - Modelo RGB


A definição da cor a atribuir a cada pixel é realizada através da especificação de 3 componentes,
que quantificam a contribuição de cada uma das três cores do modelo RGB. O modelo de cores
RGB é um modelo aditivo no qual o vermelho, o verde e o azul são combinados de diversas
maneiras para reproduzir outras cores, tal como pode ser observado na Figura 4. O nome do

5
modelo e a abreviação RGB vêm das três cores primárias: vermelho, verde e azul (Red, Green e
Blue, em inglês).
No código apresentado anteriormente, a instrução que desenhava o círculo tinha como segundo
parâmetro o triplo (255,255,0) que define a sua cor (amarelo). Repare-se que o amarelo é definido
pela mistura das componentes vermelho e verde.
Voltando ao nosso jogo do Pong, verifica-se a necessidade de desenhar a bola e ambas as
raquetes. Para a primeira, utilizaremos um círculo, enquanto para as raquetes utilizaremos
retângulos.

largRaquete rebordo
raiobola

compRaquete
raquete1

(bolaX, bolaY)
raquete2

Figura 5 - Desenho dos objetos do jogo

Voltando ao nosso jogo do Pong, verifica-se a necessidade de desenhar a bola e ambas as


raquetes. Para a primeira, utilizaremos um círculo, enquanto que para as raquetes utilizaremos
retângulos.
O código para o desenho da bola e das raquetes ficará definido pelas seguintes chamadas aos
métodos circle e rect do objeto pygame.draw:
# 3. Dispositivos de saida

#bola
pygame.draw.circle(DISPLAYSURF, (255,255,0), (bolaX, bolaY), raiobola, 0)

# raquetes
pygame.draw.rect(DISPLAYSURF, (0,0,255), raquete1, 0) # raquete azul
pygame.draw.rect(DISPLAYSURF, (255,0,0), raquete2, 0) # raquete vermelha

pygame.display.update()

No entanto, há que definir algumas variáveis auxiliares para controlar a dimensão da bola e das
raquetes, bem como a distância entre estas últimas e os limites da janela (rebordo).
Escreva o seguinte código na secção de definições:
# definicoes dos objetos graficos
raiobola = 10

compRaquete = 80
largRaquete = 20

rebordo = 20

6
E claro que também necessitamos de definir as variáveis que controlarão a posição da bola e das
raquetes ao longo do jogo e os seus valores iniciais.
O seguinte código deverá ser colocado na secção de inicialização:
# bola
bolaX = janela_largura / 2
bolaY = janela_altura / 2

# raquetes
raquete1 = pygame.Rect(rebordo,(janela_altura-compRaquete)/2,largRaquete,compRaquete)
raquete2 = pygame.Rect(janela_largura-rebordo-largRaquete,
(janela_altura-compRaquete)/2,largRaquete,compRaquete)

Este código deverá ser invocado sempre que o jogo seja reiniciado.

LAB2: Espaço para experimentar o código desenvolvido.


Acrescente este código ao anterior....
Alternativamente pode fazer download do ficheiro pong2.py .
Os atores do jogo aparecem finalmente no ecrã: as duas raquetes e a bola. Mas o ecrã é
estático, não havendo possibilidade de interação com estes elementos... não se trata
ainda de um jogo!

As peças do jogo
Qualquer jogo de computador precisa de um conjunto de variáveis que armazenem as
propriedades dos diversos elementos do jogo. Neste caso particular, consideram-se os dois
jogadores, as suas raquetes, a bola e os valores ou restrições associados ao jogo.
A bola e as raquetes já têm variáveis que permitem redefinir a sua posição. No entanto faltam as
variáveis associadas ao jogo em si, o número de golos de cada jogador e o número máximo de
golos que faz um dos jogadores ganhar o jogo.
Assim, na secção de inicialização acrescente o seguinte código:
# jogo
golos1 = 0
golos2 = 0
golosVitoria = 5

Estas variáveis serão utilizadas mais à frente...

Agora o rato entra em jogo


Um jogo de computador é uma aplicação interativa, e como tal é essencial definir a forma como o
jogador poderá interagir com o jogo. Para este jogo do Pong, optou-se por utilizar o rato para
mover a raquete do jogador 1, sendo a raquete 2 movimentada pelo computador.
Quando o rato se desloca no ecrã gera um evento (MOUSEMOTION). No ciclo for que percorre
os eventos em cada ciclo devemos acrescentar uma nova condição:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEMOTION:
xrato, yrato = event.pos
raquete1.centery = yrato

7
A raquete do jogador 1 apenas pode movimentar-se na vertical, pelo que utilizaremos apenas o valor
da ordenada (yrato) para posicionar o centro da raquete.
LAB3: Espaço para experimentar o código desenvolvido.
Acrescente este código ao anterior....
A raquete do jogador 1 começa a responder ao movimento do rato... Mas o resultado é
inesperado...

Imagens em movimento... o ciclo de animação


O efeito de animação é criado ao apresentar uma sequência de imagens a uma velocidade
suficientemente rápida. Para que a cada ciclo a imagem apresentada seja diferente da anterior, é
necessário apagar o que foi desenhado anteriormente.
Assim, acrescente uma instrução para apagar o ecrã no início da fase de visualização:
# apaga o ecra
DISPLAYSURF.fill((0,0,0))

# bola
pygame.draw.circle(DISPLAYSURF, (255,255,0), (bolaX, bolaY), raiobola, 0)
# raquetes
pygame.draw.rect(DISPLAYSURF, (0,0,255), raquete1, 0) # raquete azul
pygame.draw.rect(DISPLAYSURF, (255,0,0), raquete2, 0) # raquete vermelha

A animação deve-se realizar a uma determinada frequência que, no caso das aplicações gráficas,
se denomina Frames Por Segundo (FPS). Utilizaremos para tal um temporizador para nos dar 30
FPS.
Para que se possa mais tarde alterar essa frequência, crie uma variável na secção de definições:
FPS = 30

Temos que inicializar o temporizador. Na secção de inicialização defina:


fpsTemp = pygame.time.Clock()

E finalmente, insira no final do ciclo de jogo a chamada ao método do temporizador que faz o
sincronismo (fpsTemp.tick), de forma a garantir a frequência definida:
pygame.display.update()
fpsTemp.tick(FPS)

Desta forma, fica assim assegurado que as animações se processam de forma semelhante em
qualquer máquina.
LAB4: Espaço para experimentar o código desenvolvido.
Acrescente este código ao anterior....
Alternativamente pode fazer download do ficheiro pong3.py .
Agora sim, a raquete do jogador 1 é animada de forma suave, como era suposto.

Lendo do teclado
O rato é, tipicamente, um dispositivo apontador, o que significa que serve para apontar coordenadas
no ecrã. Embora possua botões, o dispositivo por excelência para indicar opções e comandos é o
teclado.

8
De forma alternativa à utilização do rato, no nosso jogo do Pong iremos possibilitar a utilização do
teclado. Para tal, a tecla "T" inibirá a ação do rato, passando a ser utilizadas as setas do cursor (cima e
baixo). A tecla "R" volta a atribuir o controlo da raquete ao rato. Esta funcionalidade é
disponibilizada no código seguinte, a colocar no bloco que percorre os eventos.
O evento a ler é o KEYDOWN. Será ainda necessário definir uma outra variável que selecione o tipo
de controlo (rato ou teclado):
# modo de controlo (rato/teclado)
controloRato = True

#################
# ciclo de jogo #
#################
while True:
# 1. Dispositivos de entrada (eventos)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEMOTION and controloRato:
xrato, yrato = event.pos
raquete1.centery = yrato
elif event.type == KEYDOWN:
if event.key == K_t:
controloRato = False
pygame.key.set_repeat(FPS)
elif event.key == K_r:
controloRato = True
pygame.key.set_repeat()
elif not controloRato: # controlo pelo teclado
if event.key == K_UP:
raquete1.centery = raquete1.centery - 5
elif event.key == K_DOWN:
raquete1.centery = raquete1.centery + 5

LAB5: Espaço para experimentar o código desenvolvido.


Acrescente este código ao anterior....
Alternativamente pode fazer download do ficheiro pong4.py .
Agora pode também utilizar o teclado...

Movimentando a bola... o motor de física.


Até ao momento, o nosso jogo do Pong já se tornou interativo dado que é possível controlar a
raquete do jogador 1, tanto através do rato, como do teclado. No entanto, uma grande maioria de
jogos de computador pressupõe a movimentação de diversos elementos do jogo. Neste caso
baseia-se na movimentação da bola (deslocamento e rebatimento nas paredes e raquetes). A
simulação deste tipo de movimentos poderá ser efetuada desde uma forma muito simples, até à
utilização de uma biblioteca de funções para simulação dos processos físicos – o motor de física.
Para este caso, utilizaremos um mecanismo relativamente simples, baseado num vetor velocidade,
que é utilizado para atualizar a posição da bola a cada ciclo de jogo. Este vetor é representado por
duas variáveis, xvelbola e yvelbola, que representam as suas componente x e y, a serem colocadas
junto à definição da posição da bola. Quando a bola bate em algum obstáculo (parede ou raquete),
uma das componentes (x ou y) do vetor velocidade é tornada simétrica. Exemplificando, quando a
bola bate na parede de cima ou de baixo, a componente y da velocidade é tornada simétrica (por
exemplo, se a bola subia, passa a descer) e, quando atinge qualquer das raquetes, é a componente
x que é tornada simétrica, como pode ser observado na Figura 6.

9
V=(xvel, yvel) V=(xvel, -yvel)

Figura 6 - Rebatimento da bola na parede

O ângulo inicial deverá ser obtido aleatoriamente. Este ângulo não deverá fazer mais de 45º com
a horizontal de forma a não tornar o jogo demasiado lento (no limite, se a velocidade fosse
vertical, a bola nunca atingiria as raquetes!). A posição inicial da bola será no centro do ecrã. Será
assim necessário criar uma função lancabola:
# procedimento para o lancamento da bola
velbola = 10
def lancabola():
# angulo aleatorio de 180 graus
angbola = math.pi * random.random()

# evita angulos superiores a 45º com a horizontal


if angbola >= math.pi/2:
angbola = angbola + math.pi / 2
angbola = angbola - math.pi / 4

# componentes x e y do vetor - conversao polar -> retangular


xvelbola = int(velbola * math.cos(angbola))
yvelbola = int(velbola * math.sin(angbola))

return (xvelbola, yvelbola)

Este procedimento deverá ser utilizado no início do jogo, pelo que se deve inserir uma chamada
na inicialização:
# bola
bolaX = janela_largura / 2
bolaY = janela_altura / 2
xvelbola, yvelbola = lancabola()

Mas para que a bola seja efetivamente animada é necessário atualizar a sua posição no ecrã a cada
ciclo de jogo. O código definido a seguir deverá ser inserido no bloco da lógica do jogo (bloco 2).
A primeira questão a considerar é a atualização da posição da bola, de acordo com a velocidade,
bem como a determinação das coordenadas de ecrã:
# 2. Logica do jogo
bolaX = bolaX + xvelbola
bolaY = bolaY + yvelbola

A segunda questão é a confrontação com os limites do jogo. Repare que sendo as coordenadas da
bola relativas ao seu centro, a confrontação terá que ter em conta o seu raio:

10
# limite superior ou inferior
if bolaY < raiobola or bolaY > janela_altura - raiobola:
yvelbola = -yvelbola
# limite esquerdo
elif bolaX < raiobola:
# golo do jogador 2
golos2 = golos2 + 1
# bola ao centro
bolaX = janela_largura / 2
bolaY = janela_altura / 2
xvelbola, yvelbola = lancabola()
# limite direito
elif bolaX > janela_largura - raiobola:
# golo do jogador 1
golos1 = golos1 + 1
# bola ao centro
bolaX = janela_largura / 2
bolaY = janela_altura / 2
xvelbola, yvelbola = lancabola()

E, finalmente, a terceira questão a considerar é a confrontação da bola com as raquetes. Dado que
a raquete é representada por um retângulo, optou-se por verificar a colisão destes com o retângulo
da bola.
# testa com as raquetes
bolaRect = pygame.Rect(bolaX-raiobola, bolaY-raiobola, 2*raiobola, 2*raiobola)
# raquete do jogador 1
if raquete1.colliderect(bolaRect) or raquete2.colliderect(bolaRect):
xvelbola = -xvelbola

LAB6: Espaço para experimentar o código desenvolvido.


Acrescente este código ao anterior....
Alternativamente pode fazer download do ficheiro pong5.py .
Agora já se parece mais com um jogo... Exceto o facto de o jogo não terminar e de o
jogador 2 estar estático...
Certamente reparou que o movimento é muito previsível e depois de iniciado deixa poucas
margens a alteração. Seria certamente mais aliciante, se fosse possível alterar o ângulo de
reflexão da bola com o movimento da raquete (uma espécie de "efeito" aplicado à bola).
LAB7: Espaço para melhorar o código desenvolvido.
Utilize o procedimento pygame.mouse.get_rel() para determinar o deslocamento y da
raquete quando a mesma é atingida pela bola. Utilize este valor para alterar a
componente y da velocidade da bola.
O método de colisão com as raquetes não é totalmente correto. Caso a colisão seja
verificada com o topo e a base das raquetes, algo estranho acontece... Tente também
corrigir esse problema.

O computador também sabe jogar!


Até esta fase não deverá ter tido dificuldade em derrotar o jogador adversário... mais exatamente
porque ele não existe!
Nos jogos de computador que requeiram mais do que um jogador, é necessário arranjar forma de
controlar o segundo jogador (ou restantes). Uma possibilidade é permitir que mais do que um
jogador possa utilizar o teclado ou o rato (ou outro periférico) no mesmo computador, ou em

11
computadores distintos, partilhando uma ligação em rede. Outra forma, é "dar inteligência" ao
computador para que possa tomar o lugar dos outros jogadores. Esta "inteligência" pode ir de algo
extremamente simples, como será o caso deste jogo, até algoritmos extremamente complexos,
como no caso de jogos de estratégia, caindo no âmbito de áreas científicas com a Inteligência
Artificial.
Neste jogo do Pong, optaremos pela segunda opção, em que o computador controlará o jogador 2.
A estratégia será simples, fazendo deslocar a raquete na vertical enquanto a coordenada y da bola
for diferente. A raquete só se deslocará quando a bola for na sua direção, e de acordo com o facto
de a bola estar acima ou abaixo da raquete, o sentido do deslocamento será distinto. O seguinte
código, a colocar no bloco 2., executa esta funcionalidade:
# deslocamento da raquete do jogador 2
if xvelbola > 0:
if bolaY > raquete2.centery:
raquete2.centery = raquete2.centery + min(velraquete2, bolaY - raquete2.centery)
else:
raquete2.centery = raquete2.centery - min(velraquete2, raquete2.centery - bolaY)

É também necessário definir, no bloco das definições, a velocidade da raquete:


velraquete2 = 5

O computador é bastante eficiente e preciso a jogar, dado ter acesso às variáveis do jogo. Isto nem
sempre é uma vantagem, pois desmoraliza o jogador humano que, se vir que será quase impossível
ganhar, na maioria das vezes, desiste. Assim, é comum diminuir a precisão do seu jogo, através da
limitação do acesso a estes dados ou da introdução de "ruído", incorporando erros aleatórios. No
nosso caso, poderíamos tentar limitar a resposta do computador a um "campo de visão" limitado. Ou
seja, o computador só poderia mexer a sua raquete quanto a bola estivesse a uma distância inferior a
um determinado valor (por exemplo, metade da janela de jogo).
LAB8: Espaço para experimentar o código desenvolvido.
Acrescente este código ao anterior....
Alternativamente pode fazer download do ficheiro pong6.py .
Agora já se parece mais com um jogo. Dois jogadores conformam-se... Mas não há
vencedor!

Quem vence? A interface.


O objetivo final de um jogo de computador, tal como de outro jogo qualquer, é... vencê-lo!
É assim imprescindível mostrar ao jogador qual a sua pontuação ou a progressão no jogo, quando
este é jogado por níveis ou etapas. No caso do jogo do Pong, a situação de jogo é retratada pelos
golos de cada um dos jogadores. Quem marcou mais golos está a ganhar...
Para mostrar o resultado do jogo colocar-se-á um texto com o número de golos de cada um dos
jogadores, especificados nas variáveis golos1 e golos2. Assim, no bloco 3 (saída gráfica) será
necessário acrescentar o seguinte código:

12
# HUD
fontGolos = pygame.font.Font('freesansbold.ttf', fontSize)
# golos do jogador 1
textoGolos = fontGolos.render(str(golos1), True, (255,255,255))
rectGolos = textoGolos.get_rect()
rectGolos.centerx = janela_largura/4
rectGolos.top = rebordo
DISPLAYSURF.blit(textoGolos, rectGolos)

Este é o código para apresentar o texto do jogador 1. Em primeiro lugar é preciso criar uma font
para desenhar os caracteres. Posteriormente, cria-se o texto relativo ao número presente em
golos1 e centra-se o retângulo do texto no topo do ecrã e a meio do campo do jogador 1.
A visualização do texto é feito através do método blit, de que falaremos mais à frente...
Para o jogador 2 o código é semelhante:
# golos do jogador 2
textoGolos = fontGolos.render(str(golos2), True, (255,255,255))
rectGolos = textoGolos.get_rect()
rectGolos.centerx = janela_largura*3/4
rectGolos.top = rebordo
DISPLAYSURF.blit(textoGolos, rectGolos)

Não se esqueça de colocar na secção de definições o tamanho da letra:


fontSize = 100

Este tipo de interface, denominada HUD (Heads-up display)2, caracteriza-se por se sobrepor de
forma transparente ao jogo, minimizando o espaço ocupado. Como princípio de usabilidade, a
interface deve mostrar toda a informação que é essencial, sem ser intrusiva.
LAB9: Espaço para experimentar o código desenvolvido.
Acrescente este código ao anterior....
Alternativamente pode fazer download do ficheiro pong7.py .
Agora já consegue saber quem está a ganhar...

Os personagens ganham vida... E realismo.


Até agora, o aspeto gráfico do nosso jogo é muito simples, possuindo apenas formas geométricas.
A utilização de imagens, no caso de jogos em 2D, melhora o aspeto visual e permite animar os
personagens. A técnica utilizada nestes casos denomina-se sprite.
Para criar um Sprite, carregamos a imagem bola.bmp (ver Figura 7). Os sprites usam
transparência para poderem ter formas diferentes de retângulos. Neste caso utilizamos a cor
magenta.

Figura 7- Imagem do sprite da bola

2
HUD é um dispositivo utilizado na aviação e que possibilita aos pilotos lerem informação sobre
a aeronave sem terem que desviar a sua atenção do exterior para olhar para os instrumentos de
bordo.

13
Na secção de definições coloque o seguinte código:
# sprite da bola
bolaSprite = pygame.sprite.Sprite() # cria sprite
bolaSprite.image = pygame.image.load("bola.bmp").convert() # carrega imagem
bolaSprite.rect = bolaSprite.image.get_rect() # dimensões da imagem
bolaSprite.image.set_colorkey((255,0,255)); # cor magenta transparente
raiobola = bolaSprite.rect.width/2

O ficheiro bola.bmp deve estar na mesma pasta do ficheiro com o código python, ou então deve
ser incluído o path do ficheiro no nome.
O atributo colorkey da imagem permite definir a cor que se converte em transparente. Repare
também que foi necessário alterar a definição de raiobola, pois agora a nossa bola tem outra
dimensão...
E finalmente no bloco 3, da saída gráfica alteramos a forma de visualizar a bola:
# bola
#pygame.draw.circle(DISPLAYSURF, (255,255,0), (bolaX, bolaY), raiobola, 0)
bolaSprite.rect.center = (bolaX, bolaY)
DISPLAYSURF.blit(bolaSprite.image, bolaSprite.rect)

O método blit sintetiza uma imagem no ecrã num determinado retângulo e segundo as suas
propriedades.
LAB10: Espaço para experimentar o código desenvolvido.
Acrescente este código ao anterior....
Alternativamente pode fazer download do ficheiro pong8.py .
A bola está com muito melhor aspeto... Aproveite também para melhorar as raquetes.
Na realidade, a maior parte dos sprites são animados, possuindo uma sequência de imagens para a
sua definição, que é visualizada em ciclo de forma criar o efeito de animação. Frequentemente, os
personagens possuem várias animações para cada uma das ações que desenvolvem no jogo.

Já se ouvem sons...
Um jogo deve proporcionar o máximo de imersão, e como tal, deverá despertar a maior parte dos
nossos sentidos. O som é extremamente importante para a orientação do ser humano e deve ser
parte integrante do processo de desenvolvimento de um jogo. Geralmente existem duas
componentes sonoras num jogo de computador, à semelhança de um filme: os efeitos sonoros e a
banda sonora.
Os efeitos sonoros permitem ao jogador aperceber-se de determinados eventos (colisões,
explosões, acionamento de mecanismos, etc.) enquanto a banda sonora proporciona determinados
tipos de emoções em distintas fases do jogo. Para este jogo do Pong, iremos implementar os
efeitos sonoros correspondentes ao bater da bola na parede e ao bater da bola na raquete.
A primeira fase corresponde ao carregamento em memória dos sons a reproduzir ao longo do
jogo. No caso do jogo do Pong, iremos utilizar dois sons: um para o batimento da bola na raquete
(raquete.wav) e outro para o batimento da bola na parede (parede.wav). Tal realiza-se com o
seguinte código, a colocar no bloco de inicialização:
# sons
somRaquete = pygame.mixer.Sound('raquete.wav')
somParede = pygame.mixer.Sound('parede.wav')

14
Para a reprodução do som, basta utilizar o método play(). Este método possibilita o carregamento
de ficheiros WAV, MP3 ou OGG. Para tal teremos que acrescentar o seguinte código ao bloco 2,
nas instruções onde se deteta a colisão com a parede:
# limite superior ou inferior
if bolaY < raiobola or bolaY > janela_altura - raiobola:
yvelbola = -yvelbola
# som de bater na parede
somParede.play()

Ou com a raquete:
# testa com as raquetes
bolaRect = pygame.Rect(bolaX-raiobola, bolaY-raiobola, 2*raiobola, 2*raiobola)
if raquete1.colliderect(bolaRect) or raquete2.colliderect(bolaRect):
xvelbola = -xvelbola
# som da raquete
somRaquete.play()

Embora não sendo tão relevante, é comum acrescentar-se uma banda sonora aos jogos, que
permita transmitir o ambiente emocional de cada fase de um jogo. Uma das opções é reproduzir,
de forma cíclica, um determinado ficheiro de som com a banda sonora.
Este tipo de funcionalidade pode ser implementada através do objeto pygame.mixer.music, que
possibilita a audição de ficheiros WAV, MP3, or MIDI. Faça download de um ficheiro MIDI, por
exemplo, e renomeie-o como fundo.mid.3 Os métodos play e stop permitem reproduzir e parar a
música.
Nem sempre a audição da banda sonora é desejada, pelo que deverá ser possível optar por este
efeito. Para este jogo vai ser utilizada a tecla "M" para ligar a banda sonora e a tecla "S" para a
desligar, de acordo com o seguinte código, a colocar no final do bloco 1, que lê o evento
KEYDOWN:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEMOTION and controloRato:
xrato, yrato = event.pos
raquete1.centery = yrato
elif event.type == KEYDOWN:
if event.key == K_t:
controloRato = False
pygame.key.set_repeat(FPS)
elif event.key == K_r:
controloRato = True
pygame.key.set_repeat()
elif not controloRato: # controlo pelo teclado
if event.key == K_UP:
raquete1.centery = raquete1.centery - 5
elif event.key == K_DOWN:
raquete1.centery = raquete1.centery + 5
# musica de fundo
if event.key == K_m: # Musica
pygame.mixer.music.load('fundo.mid')
pygame.mixer.music.play(-1, 0.0)
elif event.key == K_s: # Silencio
pygame.mixer.music.stop()

3
Existem vários sítios Web com ficheiros gratuitos, como por exemplo:
http://www.mfiles.co.uk/classical-midi.htm

15
LAB11: Espaço para experimentar o código desenvolvido.
Acrescente este código ao anterior....
Alternativamente pode fazer download do ficheiro pong9.py.
Agora já ouve o jogo a desenrolar-se...
Tente acrescentar um som de aplausos quando os jogadores marcam golo.

As etapas do Jogo
Um jogo é composto por diversas etapas, denominadas estados, traduzindo a evolução do seu
enredo.
No jogo do Pong, consideraremos apenas 3 estados: o menu inicial, o decorrer do jogo com bola e
o menu final do jogo, que indica o vencedor. Uma vez que o motor do jogo funciona de forma
cíclica, é necessário operar esta característica através de uma máquina de estados.
Para se saber o estado atual, a cada ciclo do motor de jogo, este é armazenado numa variável,
estado, que deverá ser adicionada ao bloco de inicialização, após a definição do número de golos
que faz terminar o jogo:
# jogo
golos1 = 0
golos2 = 0
golosVitoria = 5
estado = 0

O diagrama da Figura 8 apresenta a máquina de estados que iremos implementar para este jogo.

0. Menu inicial

Premir tecla "barra de espaços"

1. Jogo

golos1=golosVitoria OU golos2=golosVitoria

2. Final jogo
Premir qualquer tecla

Figura 8 - Máquina de estados do jogo

O programa inicia-se no estado "menu inicial". Após premir a tecla "barra de espaços" passa-se
para o estado "jogo", que por sua vez, evolui para o estado "final do jogo" quando o número de
golos de qualquer um dos jogadores for igual ao número máximo, definido por golosVitoria.
Premindo qualquer tecla retorna-se ao menu inicial.

16
Tipicamente, em cada fase do ciclo de jogo uma estrutura de decisão seleciona o código a
executar com base na variável estado:
if estado == 0:
# inicio do jogo

elif estado == 1:
# jogo

else:
# final do jogo

Será assim necessário introduzir esta estrutura de controlo em todos os blocos do ciclo de jogo:
1. Dispositivos de entrada (eventos)
2. Lógica do jogo
3. Dispositivos de saída
O código atual será incluído no estado 1, mas terá que ser definido o código para os restantes
estados. Adicionalmente, será necessário definir a mudança de estado, tal como definida no diagrama
anterior. Como a maior parte das mudanças de estado se processa por teclas, a maior parte das
alterações de estado será realizada no bloco 1.
LAB12: Espaço para experimentar o código desenvolvido.
Pode fazer download do ficheiro pong10.py .

Game Over... Ou talvez não?


Chega ao fim este tutorial, mas os autores esperam que tenha servido para dar uma perspectiva
sobre o desenvolvimento de jogos digitais e das diversas componentes de um motor de jogo (a
sua “anatomia”).
Com os conhecimentos obtidos e com o Pygame pode agora desenvolver outros jogos digitais,
para os quais o limite é apenas a sua imaginação! A criação e desenvolvimento de jogos digitais é
um trabalho de um coletivo, preferencialmente multidisciplinar. Convide outros amigos a
juntarem-se ao seu projeto, preferencialmente com perfis diversificados.
O Pygame não é um fim mas um apenas início para esta viagem, e existem disponíveis diversos
motores de jogo com capacidades distintas que se podem adequar melhor a cada tipo específico
de jogos digitais que pretenda desenvolver. Alguns desses motores de jogo têm capacidades mais
elevadas e por isso operam a um nível mais elevado, que esconde muito do detalhe que
acompanhou ao longo deste tutorial. Mas poderá agora perceber melhor as diversas opções
disponíveis nesse tipo de software.

Bibliografia
Ferreira, F. Nunes; Coelho, António: Scheme na Descoberta da Programação. Livro em formato
eletrónico (e-book), FEUP Edições, 2011. ISBN 978-972-752-115-9
Sweigart, Albert: Making Games with Python & Pygame, 2012. Available online at:
http://inventwithpython.com/pygame
Pygame. Available online at:
http://www.pygame.org/
Python Programming Language – Official Website. Available online at:
http://www.python.org/

17

Você também pode gostar