# Invasores
# Escrito por: Nilo Menezes (nilo at nilo dot pro dot br)
# This file is part of Invasores.
#
# Invasores is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Invasores is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Invasores; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import naleatorios
from video import *
from typing import List, Dict, Tuple, Callable
from objetodojogo import ObjetoDoJogo
[documentos]class Universo:
"""
Responsável pela manutenção do conjunto de objetos do jogo (:py:class:`objetodojogo.ObjetoDoJogo`).
Esta classe varre sua lista de objetos, chamando o método de respiração
de cada objeto, rotina de cálculo de pontos e também gerando o fundo de estrelas.
"""
def __init__(self, dimensao: Tuple[int, int], quadros: int=60) -> None:
"""
Inicializa o universo com valores
:param tuple dimensao: tupla com a largura e altura da tela em pixels
:param int quadros: quadros por segundo
"""
#: lista de objetos do jogo
self.objetos = [] # type: List[ObjetoDoJogo]
self.colisoes = {} # type: Dict[str,List]
self.video = Video(dimensao)
self.video.adicione(self.reconfigura_video)
self.quadros = quadros
self.largura = dimensao[0]
self.altura = dimensao[1]
self.score = 0
self.calcule_pontos = None # type: Callable[[ObjetoDoJogo, ObjetoDoJogo], int]
self.gere_estrelas()
self.intensidade_estrelas = 0
self.clock = pygame.time.Clock()
[documentos] def reconfigura_video(self, mensagem: int):
"""Usado para trocar de resolução. Atualiza os limites do universo,
gera novas estrelas."""
if mensagem == 0:
# Mudança de resolução
self.largura = self.video.dimensao[0]
self.altura = self.video.dimensao[1]
self.gere_estrelas()
[documentos] def gere_estrelas(self) -> None:
"""Gera aleatoriamente as estrelas do fundo.
As coordenadas x e y de cada estrela são escolhidas aleatoriamente e representão a posição da estrela.
z é o tamanho da estrela.
"""
self.estrelas = [] # type: pygame.Rect
for i in range(60):
x = naleatorios.faixa(1, self.largura)
y = naleatorios.faixa(1, self.altura)
z = naleatorios.faixa(2, 6)
rect = pygame.Rect(x, y, z, z)
self.estrelas.append(rect)
[documentos] def adicione(self, objeto: ObjetoDoJogo):
"""Adiciona um objeto à lista de desenho."""
self.objetos.append(objeto)
objeto.universo = self
if objeto.tipo is not None:
if objeto.tipo in self.colisoes:
self.colisoes[objeto.tipo].append(objeto)
else:
self.colisoes[objeto.tipo] = [objeto]
[documentos] def remova(self, objeto: ObjetoDoJogo):
"""Retira um objeto da lista de desenho e da lista de colisões"""
if objeto.tipo is not None:
self.colisoes[objeto.tipo].remove(objeto)
self.objetos.remove(objeto)
def __centraliza_x(self, imagem) -> int:
"""Centraliza imagem na tela"""
return (self.largura - imagem.get_width()) / 2
def __centraliza_y(self, imagem) -> int:
"""Centraliza imagem verticalmente na tela"""
return (self.altura - imagem.get_height()) / 2
[documentos] def desenhe(self, posicao: List[int], imagem):
"""Desenha a imagem na posição x, y indicada"""
if posicao[0] == -1:
posicao[0] = self.__centraliza_x(imagem)
if posicao[1] == -1:
posicao[1] = self.__centraliza_y(imagem)
self.video.desenhe(imagem, posicao)
[documentos] def escreva(self, posicao: List[int], texto, cor, tamanho=None):
"""Escreve uma mensagem de texto na posição x, y passada.
Se uma das posições for igual a -1, centraliza no eixo específico"""
if tamanho is not None:
self.video.fonte(tamanho)
imagem = self.video.texto(texto, cor)
if posicao[0] == -1:
posicao[0] = self.__centraliza_x(imagem)
if posicao[1] == -1:
posicao[1] = self.__centraliza_y(imagem)
self.desenhe(posicao, imagem)
[documentos] def desenhe_fundo(self):
"""Apaga a tela e desenha as estrelas"""
self.video.limpe()
for estrela in self.estrelas:
intensidade = 100 + self.intensidade_estrelas * 2 % 50
cor = [intensidade, intensidade, intensidade]
# (255,255,100)
pygame.draw.rect(self.video.tela, cor, estrela, 0)
# Mode a estrela para baixo para dar ideia de movimento
estrela.y += 3
# Se a estrela estiver fora da tela, reposiciona na primeira linha
if estrela.y > self.altura:
estrela.y = 0
self.intensidade_estrelas = self.intensidade_estrelas + 1
[documentos] def desenhe_objetos(self):
"""Desenha a lista de objetos na tela"""
[self.video.tela.blit(objeto.imagem, objeto.pos)
for objeto in self.objetos if objeto.visivel]
self.teste_colisao()
[documentos] def atualize(self):
"""Atualiza o estado do jogo, chamando o método :meth:`ObjetoDoJogo.respire`
de todos os objetos na lista de desenho."""
[objeto.respire() for objeto in self.objetos]
self.video.atualize()
[documentos] def finalize_sincronia(self):
"""Espera o fim do frame atual."""
self.clock.tick_busy_loop(self.quadros)
[documentos] def teste_colisao(self):
"""Verifica se objetos de classes diferentes colidem uns com os outros"""
colisoes = list(self.colisoes.keys())
while colisoes:
A = colisoes.pop()
for objetoA in self.colisoes[A]:
for B in colisoes:
for objetoB in self.colisoes[B]:
if objetoA.rect.colliderect(objetoB.rect):
self.score += self.calcule_pontos(objetoA, objetoB)