sexta-feira, 19 de junho de 2009

Adicionando tela de fundo.

Olá! Continuando nosso pequeno joguinho, esta semana vamos fazer a tela de fundo um pouco mais interessante que apenas um fundo preto e opaco... Vamos adicionar estrelas, com movimento!

Abaixo está o código da classe "Background", que devemos salvar no arquivo "background.py".

# coding: utf8
# background.py

import pygame
import random

class Background(object):
    
    def __init__(self, max_stars=100):
        self.max_speed = 6
        screen = pygame.display.get_surface()
        size = screen.get_size()
        back = pygame.Surface(size).convert()
        back.fill( (0,0,0) )
        self.image = back
        self.stars = []
        for _ in range(max_stars):
            rand = random.randint
            self.stars.append( [rand(0, size[0]), rand(0, size[1]), rand(1, self.max_speed)])
    
    def update(self):
        size = pygame.display.get_surface().get_size()
        for star in self.stars:
            star[1] += star[2]
            if star[1] >= size[1]:
                star[1] = 0
                star[0] = random.randint(0, size[0])
                star[2] = random.randint(1, self.max_speed)
    
    def draw(self, screen):
        image = self.image
        image.fill( (0, 0, 0) )
        for star in self.stars:
            image.set_at(star[:2], (255, 255, 255))
        
        screen.blit(self.image, (0, 0))

Como vocês podem ver, a classe é bem simples. Inicializamos a o objeto background com um número máximo padrão de 100 estrelas, cada estrela irá se mover de cima para baixo na tela, dando a impressão que estamos percorrendo o espaço. Atribuímos também a velocidade máxima com que cada estrela poderá se movimentar.

Preenchemos a tela com o tradicional fundo preto, criamos uma "Surface" que será onde iremos desenhar nossas estrelas e salvamos essa "Surface" na variável "self.image".

Agora a parte interessante. A criação das estrelas. Para nosso exemplo, faremos da forma mais simples possível: uma array com 3 números, representando a posição da estrela e sua velocidade (x, y, velocidade).

O método "update(self)" é onde ocorre a atualização do estado do nosso background. O que faremos aqui é simplesmente adicionar a velocidade (star[2]) à coordenada y da posição (star[1]). Caso após adicionarmos a velocidade a estrela suma, ou seja, sua cordenada y passe a ser maior que o tamanho da nossa tela na vertical, reposicionamos esta estrela, colocando-a no topo da tela, com novos valores para a coordenada x e para a velocidade. Note que para a velocidade sempre iremos desejar um valor >= 1, pois caso contrário teríamos uma estrela estática.

O método "draw(self)" é mais simples ainda. Preenchemos a nossa imagem com preto e então percorremos a lista de estrelas, adicionando um ponto branco para cada uma delas em sua posição atual. Após isso chamamos "blit" na variável "screen". O que está função faz é copiar o conteúdo de uma "Surface" para outra. Assim, ao copiarmos o fundo para a "Surface" screen, estaremos substituindo a imagem que será mostrada na tela na próxima atualização.

O que resta agora é apenas alterar a classe "Game" para utilizar o nosso background animado. Abaixo está o código da classe com as devidas alterações:

# coding: utf8
# game.py

import pygame
import random

from pygame.locals import *
import background

class Game(object):
    
    def __init__(self, size):
        pygame.init()
        flags = DOUBLEBUF
        self.screen = pygame.display.set_mode(size, flags)
        self.screen_size = self.screen.get_size()
        
        pygame.mouse.set_visible(False)
        pygame.display.set_caption('Meu Primeiro Jogo em Python')
        
        self.run = True
        self.list = {
            'player': pygame.sprite.RenderPlain(),
            'enemy': pygame.sprite.RenderPlain(),
            'fire': pygame.sprite.RenderPlain(),
            'enemy_fire': pygame.sprite.RenderPlain(),
        }
        self.player = None
        self.background = background.Background()
    
    def update_actors(self):
        if self.background is not None:
            self.background.update()
        
        for actor in self.list.values():
            actor.update()
    
    def draw_actors(self):
        if self.background is not None:
            self.background.draw(self.screen)
        else:
            self.screen.fill(0)
        
        for actor in self.list.values():
            actor.draw(self.screen)
    
    def act_actors(self):
        pass
    
    def manage(self):
        pass
    
    def handle_events(self):
        player = self.player
        for event in pygame.event.get():
            t = event.type
            
            if t in (KEYDOWN, KEYUP):
                k = event.key
            
            if t == QUIT:
                self.run = False
            elif t == KEYDOWN and k == K_ESCAPE:
                self.run = False
            elif t == KEYUP:
                pass
    
    def loop(self):
        clock = pygame.time.Clock()
        
        while self.run:
            clock.tick(1000)
            
            self.handle_events()
            self.manage()
            
            self.act_actors()
            self.update_actors()
            self.draw_actors()
            
            pygame.display.flip()

if __name__ == '__main__':
    game = Game( (640, 480) )
    game.loop()

Como você pode observar, com poucas linhas de código criamos um fundo de tela animado bem legal. No próximo post vou adicionar algumas naves. Até!

8 comentários:

Daniel Gerçossimo disse...

João muito bom mesmo, fiquei feliz de encontrar seu blog, pois uma das coisas que mais quero é trabalhar com criação de jogos e este blog está me ajudando muito.

Muito Obrigado mesmo!!

João Paulo Farias disse...

Valeu a força!

Já faz um tempo que não atualizo o blog, mas vou tentar voltar com mais novidades.

Fernando disse...

Oxe, e eu que vinha acompanhando as aulas... Abandonou o projeto do jogo de damas?

Unknown disse...

Oi João, estou precisando desenvolver um jogo para um trabalho da faculdade e o seu site está ajudando muito. Se vc pudesse terminar o jogo inserindo as naves e os "alienigenas" rsrsrs, junto com suas explicações iriam me ajudar bastante. Estou cursando sistemas de informação e confesso: estou com muita dificuldades nesse começo, com prog orientada a objetos.

pinna disse...

Muito boa mesmo! Explicação enxuta pena que vc não esta tendo tempo para continuar.

Rayane disse...

Joao meus parabéns! ótimo o blog, pena que tem muito tempo que você não atualiza.
Estou com um projeto para entregar, que eu preciso de fazer um joguinho
=/
e está bem dificil, se tiver como continuar o tutorial, e mostrar o codigo do jogo em damas, ou como faz, ficarei realmente muito grata!

SUCESSO! vc eh d+...!

Anônimo disse...

Amigo, gostei bastante do seu blog, e o conhecimento que vc está pssando aqui é muito plausivel, bom e aproveitavel, gostei muito sobre essa introdução sobre o PyGame, achei legal, mas queria q vc continuasse, tudo bem que já tem tempo e sei q vc é bastante ocupado, mas se vc puder postar todo o código do jogo, mesmo sem poder explicar, agradeço, mas parabéns pelo site e pela iniciativa

Anônimo disse...

olá meu nome é Adriana,e gostaria que vc me ajudasse se puder em um trabalho da faculdade que está valendo como prova, como posso te enviar o minimundo, eu começei a fazer mais sou bem iniciante e tenho dificuldades?
Att.
Adriana