Mini-Aulas PyGame (parte 1)
Autor: Nome: Igor Sobreira | Publicado: 2007-07-14T12:32:00-03:00

Tutorial enviado por Flavio Ribeiro.Para enviar o seu, mande para o email no perfil ao ladoOlá, hoje vou introduzir poucos conceitos que aprendi pra desenvolver games usando pygame. Vou fazer um pequeno joguinho onde uma nave se move na tela e dá tiros. No fim falo mais sobre esse 'jogo'.1. Antes de mais nada, instale o pygame. Observe que se você usar alguma distro debian-based, basta um apt-get install python-pygame que ele dá conta do resto. Não sei em outros gerenciadores de pacotes (yum, emerge, etc) mas se não conseguirem usa-los, basta fazer download do tarball.2. Teste se já tá funcionando importando no interpretador python:root@nerdy:/# pythonPython 2.5.1 (r251:54863, May  2 2007, 16:56:35)[GCC 4.1.2 (Ubuntu 4.1.2-0ubuntu4)] on linux2Type "help", "copyright", "credits" or "license" for more information.>>> import pygame>>>>Se o interpretador não chiar, estamos prontos.3. Vamos agora fazer nosso 'joguinho'. Comece importando os módulos necessários:import pygame, sys,osfrom pygame.locals import *__obsnãomuitoimportante__: O sys e os vou mostrar porque importei mais na frente, já o pygame.locals eu importei trazendo pro namespace pra economizar digitação.4. Inicialize o pygame usando o metodo init():pygame.init()5. Agora sim, vamos por a mão na massa. Sete o tamanho da telinha do seu jogo e o título (que vai ficar na barrinha):window = pygame.display.set_mode((200, 200))pygame.display.set_caption('Meu primeiro jogo!')6. Sete as váriaveis que vamos usar. Duas que indicarão a posição da nave (x_position e y_position), uma (step) que indica quantos pixels nossa nave vai se mexer quando o usuário apertar pros lados, e outra (shotspeed) que indica a velocidade do tiro.global x_position, y_position, stepx_position, y_position = 50,100step = 5shotspeed = 1obs_importante: O global indica que modificaremos os valores dessas variáveis dentro de funções. Para saber mais clique aqui.7. Hora de 'carregar' nossas imagens. Aqui vou carregar o background, a nave e a imagem do tiro ok? Primeiro passo o endereço completo de onde a imagem se encontra (tá aí o os sendo usado!), depois dou um pygame.image.load pra carregar a imagem em uma instância.background_draw = os.path.join("/home/bioinfo/pygame/mygames","tile3.png")background = pygame.image.load(background_draw)ship_draw = os.path.join("/home/bioinfo/pygame/mygames","nave.png")ship = pygame.image.load(ship_draw)shot_draw = os.path.join("/home/bioinfo/pygame/mygames","tiro.png")shot = pygame.image.load(shot_draw)8. Pra que o background e a nave apareça na tela é necessário que você desenhe (blit) ele. Mas não é só isso, tudo que você for desenhar ou atualizar no pygame você precisa atualizar (flip) a tela.  No blit() você passa como argumentos a instância do pygame.image.load e a posição em coordenadas de pixels.window.blit(background, (0,0)) # Desenha o background na tela. O background tem o mesmo tamanho setado por nós no passo 5)window.blit(ship, (x_position,y_position)) # Desenha a navepygame.display.flip() # Recarrega a janela9. Pronto, agora o que precisamos é de um laço infinito recebendo todos os eventos do gamer (aperta botão K, aperta botão SPACE, clica com o botão direito do mouse, etc...), e o pygame é bem eficiente nisso. Tudo que você precisa fazer é:while True: events = pygame.event.get()O pygame.event.get() está atribuinto a variavel events uma lista com os eventos que estão acontecendo. Então, quando essa lista não for vazia, alguem apertou ou moveu algo. Vamos tratar esse evento! for event in events:     if event.type == KEYDOWN and event.key == K_LEFT:         x_position -= step         window.blit(background, (0,0))         window.blit(ship, (x_position,y_position))         pygame.display.flip()      if event.type == KEYDOWN and event.key == K_RIGHT:         x_position += step         window.blit(background, (0,0))         window.blit(ship, (x_position,y_position))         pygame.display.flip()      if event.type == KEYDOWN and event.key == K_SPACE:         shot_pos_x, shot_pos_y = x_position, y_position         while shot_pos_y > 0:             window.blit(background, (0,0))             window.blit(ship, (x_position,y_position))             window.blit(shot, (shot_pos_x,shot_pos_y))             shot_pos_y -= shotspeed             pygame.display.flip()         window.blit(background, (0,0))         window.blit(ship, (x_position,y_position))         pygame.display.flip()      if event.type == QUIT:         sys.exit(0)Calma, calma. Vou explicar tudinho. Esse for trata os eventos como falei acima, e se o tipo do evento for KEYDOWN (alguem pressionou uma tecla) e essa tecla for setinha-pra-esquerda (K_LEFT) nós alteramos a posição da nave em cinco pixels pra esquerda (diminuimos o x_position com o step), apagamos tudo redesenhando o background por cima de tudo, desenhamos a nave novamente só que no novo lugar e damos um 'refresh' na tela, sacou? O mesmo com o K_RIGHT.Já com o K_SPACE, que é quando o usuário apertar espaço, nós setamos a posição do tiro que vai partir da nave (ou seja, tem que estar na mesma posição da nave que é x_position e y_position) e fazemos um while dizendo que enquanto a posição do tiro no eixo Y for maior que 0 (ou seja, enquanto o tiro não encostar na aresta superior da tela) o jogo precisa desenhar o background, desenhar a nave, desenhar o tiro e diminuir 1 pixel da posição atual do tiro, que é pra fazer ele subir. Dessa forma, uma hora o tiro vai chegar no topo da tela e sair fora do while. Aí o joguinho redesenha o background e a nave só e dá uma atualizada na tela pra que o tiro suma.O ultimo evento é só pra o X do canto superior direito da tela funcionar.Algumas Observações: Existem várias coisas nesse código que precisam ser melhoradas. Esse while do tiro precisa ser refeito porque enquanto o tiro viaja pela telinha nossa nave fica presa, esperando o tiro sumir da tela para que retomemos o controle dela. Isso é um erro.Outra coisa que preciso aprender é a atualização (flip) da tela. Existe um outro método mais eficiente que é o update(), e usamos ele quando queremos atualizar apenas partes da tela. Essa atualização por partes é chamada de dirty-rect, e ela desenha apenas retângulos de background onde aconteceram movimentos.No geral é mais ou menos isso. O código completo está aqui e se você quiser ver esse código funcionando pegue as imagens aqui. Não esqueca de modificar o caminho das imagens no comecinho do código. Quando eu for fazendo as otimizações e adicionando funcionalidades ao código vou criando mais tutoriais como esse.