Bem Vindos ao Circo Voador da Programação Python

Aqui vamos ter uma introdução rápida de como programar jogos para Web usando Python. Na verdade vamos usar o Brython que é o Python que funciona dentro de um navegador web como o Firefox.

http://s19.postimg.org/ufgi8eztf/PPFC.jpg

Sumário

Como brincar com os desafios

Entre na plataforma <nome do seu projeto>.is-by.us. Clique no projeto determinado pelo instrutor. Vamos começar importando o circus para criar um jogo. Você faz a sua implementação e depois invoca o circus para conferir o resultado.

from _spy.circus.circus import circus
# faça aqui a sua implementação do desafio
if __name__ == "__main__":
    #circus(<ponha aqui o número do desafio e descomente a linha>, <parâmetro indicado>)

Note

Procure ser cooperativo com a sua equipe.

Criando uma Câmara com Constantes

Uma constante é um valor que não se modifica ao longo de um programa. Em Python a constante é escrita com todas as letras maiúsculas como no nome TOPO_ESQUERDA abaixo.

Use os ladrilhos nomeados de A a L para montar a câmara mostrada à direita.

_images/desafio_a.png
from _spy.circus.circus import circus

TOPO_ESQUERDA = "AN"
TOPO_DIREITA = "AN"
TOPO_CENTRO = "AN"
MEIO_ESQUERDA, CENTRO, MEIO_DIREITA = "AN", "AN", "AN"
FUNDO_ESQUERDA, FUNDO_CENTRO, FUNDO_DIREITA =  "AN", "AN", "AN"

# O comando abaixo voce vai entender no próximo desafio
circus(1, [[TOPO_ESQUERDA, TOPO_CENTRO, TOPO_DIREITA], [MEIO_ESQUERDA, CENTRO,
        MEIO_DIREITA], [FUNDO_ESQUERDA, FUNDO_CENTRO, FUNDO_DIREITA]])

Note

No texto “AN” a primeira letra determina o ladriho e a segunda se está girada para Norte, Leste, Sul ou Oeste.

Criando uma Câmara com Listas

Uma lista é um conjunto de coisas, pode ser um conjunto de números, letras, palavras ou qualquer outro objeto. Em Python a lista é escrita assim: [<uma coisa>, <outra coisa>].

Use os ladrilhos nomeados de A a L para montar a câmara mostrada abaixo, consulte o exercício anterior.

_images/masmorra.jpg
from _spy.circus.circus import circus

MASMORRA = [[ "AN", "AN", "AN", "AN", "AN", "AN"],
            [ "AN", "AN", "AN", "AN", "AN", "AN"],
            [ "AN", "AN", "AN", "AN", "AN", "AN"],
            [ "AN", "AN", "AN", "AN", "AN", "AN"],
            [ "AN", "AN", "AN", "AN", "AN", "AN"]
            ]

circus(2, MASMORRA)

Note

No texto “AN” a primeira letra determina o ladriho e a segunda se está girada para Norte, Leste, Sul ou Oeste.

Criando uma Câmara com Dicionário

Uma lista é um conjunto de coisas, pode ser um conjunto de números, letras, palavras ou qualquer outro objeto. Em Python a lista é escrita assim: {<umnome: umvalo>, <outronome: outrovalor>}.

Use os ladrilhos nomeados de A a L para montar a câmara mostrada abaixo, consulte o exercício A. Descubra quais posições os nomes misteriosos indicam.

_images/masmorra2.jpg
from _spy.circus.circus import circus

MASMORRA = {'Cahuitz': 'AN', 'Cauha': 'AN', 'Coycol': 'AN',
 'Huatlya': 'AN', 'Micpe': 'AN', 'Nenea': 'AN',
 'Pallotl': 'AN', 'Tetlah': 'AN', 'Zitllo': 'AN'}


circus(3, MASMORRA)

Note

No texto “AN” a primeira letra determina o ladrilho e a segunda se está girada para Norte, Leste, Sul ou Oeste.

Uma Câmara Instável

Esta câmara embaralha as posições se os ladrilhos não forem colocados corretamente. Você terá que usar uma estratégia para montar os ladrilhos antes que eles embaralhem.

Use os ladrilhos nomeados de A a L para montar a câmara mostrada abaixo, consulte o exercício A. Descubra quais posições os nomes misteriosos indicam.

_images/masmorra2.jpg
from _spy.circus.circus import circus

MASMORRA = {'Cahuitz': 'AN', 'Cauha': 'AN', 'Coycol': 'AN',
 'Huatlya': 'AN', 'Micpe': 'AN', 'Nenea': 'AN',
 'Pallotl': 'AN', 'Tetlah': 'AN', 'Zitllo': 'AN'}


circus(4, MASMORRA)

Note

No texto “AN” a primeira letra determina o ladrilho e a segunda se está girada para Norte, Leste, Sul ou Oeste.

Uma Câmara Muito Instável

Esta câmara embaralha as posições e as direçoes se os ladrilhos não forem colocados corretamente. Você terá que usar uma estratégia para montar os ladrilhos antes que eles embaralhem.

Use os ladrilhos nomeados de A a L para montar a câmara mostrada abaixo, consulte o exercício A. Descubra quais posições os nomes misteriosos indicam.

_images/masmorra2.jpg
from _spy.circus.circus import circus

MASMORRA = {'Cahuitz': 'AN', 'Cauha': 'AN', 'Coycol': 'AN',
 'Huatlya': 'AN', 'Micpe': 'AN', 'Nenea': 'AN',
 'Pallotl': 'AN', 'Tetlah': 'AN', 'Zitllo': 'AN'}


circus(5, MASMORRA)

Note

No texto “AN” a primeira letra determina o ladrilho e a segunda se está girada para Norte, Leste, Sul ou Oeste.

Uma Câmara Extremamente Instável

Esta câmara embaralha as posições e as direções dependem das posições. Se os ladrilhos não forem colocados corretamente tudo será embaralhado. Você terá que usar uma estratégia para montar os ladrilhos antes que eles embaralhem.

Use os ladrilhos nomeados de A a L para montar a câmara mostrada abaixo, consulte o exercício A. Descubra quais posições os nomes misteriosos indicam.

_images/masmorra2.jpg
from _spy.circus.circus import circus

MASMORRA = {'Cahuitz': 'AN', 'Cauha': 'AN', 'Coycol': 'AN',
 'Huatlya': 'AN', 'Micpe': 'AN', 'Nenea': 'AN',
 'Pallotl': 'AN', 'Tetlah': 'AN', 'Zitllo': 'AN'}


circus(6, MASMORRA)

Note

No texto “AN” a primeira letra determina o ladrilho e a segunda se está girada para Norte, Leste, Sul ou Oeste.

Primeiro Cenário do Jogo

Vamos começar importando o módulo Circus para criar um jogo baseado na biblioteca Phaser. Vamos criar uma organização em Python chamada class que vai ter duas operações preload e create. O objetivo é mostrar a imagem abaixo:

_images/masmorra.jpg
from _spy.circus.game import Circus


class Jogo(Circus):
    """Essa  é a classe Jogo que recebe os poderes da classe Circus de poder criar um jogo"""

    def preload(self):
        """Aqui no preload carregamos os recursos usados no jogo, neste caso a imagem masmorra"""
        self.image("fundo", "http://<descubra um jeito de achar a url que vai ser posta aqui>")

    def create(self):
        """Aqui colocamos a imagem masmorra na tela do jogo"""
        self.sprite("fundo")

if __name__ == "__main__":
    Jogo()

Note

Ainda é um programa bem simples.

Montando a Cena com Ladrilhos

Na maior parte dos jogos o cenário tem que ser montado a partir de uma folha de ladrilhos. As folhas de ladrilho são numeradas de 0 a n da esquerda para direita de cima para baixo. Esta é a folha de ladrilhos:

_images/DungeonWall.jpg

Procure reproduzir este labirinto:

_images/mosaico2x2.jpg
from _spy.circus.game import Circus


class Jogo(Circus):
    """Essa  é a classe Jogo que recebe os poderes da classe Circus de poder criar um jogo"""

    def preload(self):
        """Aqui no preload carregamos os recursos usados no jogo, neste caso a folha de ladrilhos"""
        self.spritesheet("ladrilho", "http://<advinha!>", 128, 128, 12)

    def create(self):
        """Aqui colocamos cada ladrilho indicando a posição na tela e depois selecionando o ladrilho"""
        um_ladrilho = self.sprite("ladrilho", 0, 0)
        um_ladrilho.frame = 5  # este número seleciona o ladrilho que vai ser colocado
        um_ladrilho = self.sprite("ladrilho", 0, 0)  # mude a posição do ladrilho
        um_ladrilho.frame = 5  # troque o ladrilho!
        # Coloque mais dois outros ladrilhos

if __name__ == "__main__":
    Jogo()

Note

Ainda é um programa bem simples.

Cena com Ladrilhos Girados

Vamos montar uma outra masmorrra, mas que agora requer que rotacionemos os ladrilhos. Veja os comando angle e anchor no código. A folha de ladrilhos continua esta:

_images/DungeonWall.jpg

Procure reproduzir este labirinto:

_images/masmorra2.jpg
from _spy.circus.game import Circus


class Jogo(Circus):
    """Essa  é a classe Jogo que recebe os poderes da classe Circus necessários para criar um jogo"""

    def preload(self):
        """Aqui no preload carregamos os recursos usados no jogo, neste caso a folha de ladrilhos"""
        self.spritesheet("ladrilho", "http://<advinha!>", 128, 128, 12)

    def create(self):
        """Aqui colocamos cada ladrilho indicando a posição na tela e depois selecionando o ladrilho"""
        um_ladrilho = self.sprite("ladrilho", 0, 0)
        um_ladrilho.frame = 5  # este número seleciona o ladrilho que vai ser colocado
        um_ladrilho.anchor.setTo(0.5, 0.5)  # este comando faz com que a rotação seja no centro do ladrilho
        um_ladrilho.angle = 90  # está é a rotação em graus do ladrilho
        um_ladrilho = self.sprite("ladrilho", 0, 0)  # mude a posição do ladrilho
        um_ladrilho.frame = 5  # troque o ladrilho!
        um_ladrilho.anchor.setTo(0.5, 0.5)
        um_ladrilho.angle = 90  # troque o ângulo!
        # Coloque aqui o resto dos ladrilhos

if __name__ == "__main__":
    Jogo()

Note

Observe que ao colocar a âncora no centro do ladrilho, este centro também servirá para posicionar o ladrilho. Ajuste as cordenadas para que tudo fique correto.

Cena com Mais Ladrilhos Girados

Vamos montar uma outra masmorrra, um pouco maior. Em vez de copiar várias vezes o código, vamos usar uma lista de tuplas e o comando for A folha de ladrilhos continua esta:

_images/DungeonWall.jpg

Procure reproduzir este labirinto:

_images/mosaico4x4.jpg
from _spy.circus.game import Circus


class Jogo(Circus):
    """Essa  é a classe Jogo que recebe os poderes da classe Circus necessários para criar um jogo"""
    MOSAICO = [
    [(5, 90), (5, 90), (5, 90), (5, 90)],
    [(5, 90), (5, 90), (5, 90), (5, 90)],
    [(5, 90), (5, 90), (5, 90), (5, 90)],
    [(5, 90), (5, 90), (5, 90), (5, 90)]
    ]  # esta é uma lista de listas. Cada lista é uma linha e cada tupla dá o ladrilho (5) e o ângulo (90)

    def preload(self):
        """Aqui no preload carregamos os recursos usados no jogo, neste caso a folha de ladrilhos"""
        self.spritesheet("ladrilho", "http://<advinha!>", 128, 128, 12)

    def create(self):
        """Aqui colocamos um for que varre cada linha e cada coluna da matriz"""
        azulejo = self.MOSAICO
        for y in range(4):
           for x in range(4):
              frame, angle = self.MOSAICO[y][x]  # este comando desmembra a tupla em duas variáveis, frame e angle
              um_ladrilho = self.sprite("ladrilho", 64+x*128, 64+y*128)  # cria e muda a posição do ladrilho
              um_ladrilho.frame = frame
              um_ladrilho.anchor.setTo(0.5, 0.5)
              um_ladrilho.angle = angle

if __name__ == "__main__":
    Jogo()

Note

Observe que ao colocar a âncora no centro do ladrilho, este centro também servirá para posicionar o ladrilho. Ajuste as cordenadas para que tudo fique correto.

Cena com Muitos Ladrilhos Girados

Vamos montar a masmorra original, bem maior. Em vez de copiar várias vezes o código, vamos usar um dicionário de tuplas e o comando for A folha de ladrilhos continua esta:

_images/DungeonWall.jpg

Procure reproduzir este labirinto:

_images/masmorra.jpg
from _spy.circus.game import Circus

A, B, C, D, E, F, G = 0, 128, 256, 256+128, 512, 512+128, 512+256


class Jogo(Circus):
    """Essa  é a classe Jogo que recebe os poderes da classe Circus necessários para criar um jogo"""
    MOSAICO = {
    (A, A): (5, 90), (B, A): (5, 90), (C, A):(5, 90), (D, A):(5, 90), (E, A):(5, 90), (F, A):(5, 90), (G, A):(5, 90),
    (A, B): (5, 90), (B, B): (5, 90), (C, B):(5, 90), (D, B):(5, 90), (E, B):(5, 90), (F, B):(5, 90), (G, B):(5, 90),
    (C, C): (5, 90), (B, C): (5, 90), (C, C):(5, 90), (D, C):(5, 90), (E, C):(5, 90), (F, C):(5, 90), (G, C):(5, 90),
    (D, D): (5, 90), (B, D): (5, 90), (C, D):(5, 90), (D, D):(5, 90), (E, D):(5, 90), (F, D):(5, 90), (G, D):(5, 90),
    (E, E): (5, 90), (B, E): (5, 90), (C, E):(5, 90), (D, E):(5, 90), (E, E):(5, 90), (F, E):(5, 90), (G, E):(5, 90),
   }  # este é um dicionário de tuplas. Cada chave é a posição do ladrilho e cada tupla dá o ladrilho (5) e o ângulo (90)

    def preload(self):
        """Aqui no preload carregamos os recursos usados no jogo, neste caso a folha de ladrilhos"""
        self.spritesheet("ladrilho", "http://<advinha!>", 128, 128, 12)

    def create(self):
        """Aqui colocamos cada ladrilho indicando a posição na tela e depois selecionando o ladrilho"""
        for (x, y), (frame, angle) in self.MOSAICO.items():
           # coloque o resto aqui

if __name__ == "__main__":
    Jogo()

Note

Observe que ao colocar a âncora no centro do ladrilho, este centro também servirá para posicionar o ladrilho. Ajuste as cordenadas para que tudo fique correto.

Colocando Personagens

Vamos criar uma outra classe para um personagem monstro. O monstro vai ser criado na invocação __init__ do Jogo. Use a folha de ladrilhos para programar os monstros:

_images/monstersheets.png
from _spy.circus.game import Circus, Actor


class Jogo(Circus):
    """Essa  é a classe Jogo que recebe os poderes da classe Circus de poder criar um jogo"""
    def __init__(self):
        super().__init__()  # super é invocado aqui para preservar os poderes recebidos do Circus
        self.ladrilho_monstro = "monstro"
        self.monstro = Monstro(self.ladrilho_monstro, 0, 0, 0)

    def preload(self):
        """Aqui no preload carregamos a imagem masmorra e a folha de ladrilhos dos monstros"""
        self.image("fundo", "http://<descubra um jeito de achar a url que vai ser posta aqui>")
        self.spritesheet(self.ladrilho_monstro, "http://<advinha!>", 64, 63, 16*12)

    def create(self):
        """Aqui colocamos a imagem masmorra na tela do jogo"""
        self.sprite("fundo")


class Monstro(Actor):
    """Essa  é a classe Monstro que controla os personagens do jogo"""
    def __init__(self, nome, frame, x, y):
        super().__init__()
        self.nome, self.frame, self.x, self.y = nome, frame, x, y

    def create(self):
        """Aqui colocamos o sprite do monstro e selecionamos o frame que o representa"""
        self.monstro = "<troque isto pela criação do sprite, use self.nome, self.x e self.y>"
        "escolha aqui o frame e use self.frame"
        self.monstro.anchor.setTo(0.5, 0.5)

if __name__ == "__main__":
    Jogo()

Colocando Mais Personagens

Vamos criar outros monstros. A operação [f(x) for x in <Coleção>] gera uma lista varrendo a Coleção dada e executando a função f(x) para cada x na Coleção.

_images/monstersheets.png
from _spy.circus.game import Circus, Actor

MONSTROS = [(0, 0, 0), (0, 0, 0), (0, 0, 0)]


class Jogo(Circus):
   """Essa  é a classe Jogo que recebe os poderes da classe Circus de poder criar um jogo"""
   def __init__(self):
      super().__init__()  # super é invocado aqui para preservar os poderes recebidos do Circus
      self.ladrilho_monstro = "monstro"
      self.monstro = [Monstro(self.ladrilho_monstro, frame, x, y) for frame, x, y in MONSTROS]

   def preload(self):
      """Aqui no preload carregamos a imagem masmorra e a folha de ladrilhos dos monstros"""
      self.image("fundo", "http://<descubra um jeito de achar a url que vai ser posta aqui>")
      self.spritesheet(self.ladrilho_monstro, "http://<advinha!>", 64, 63, 16*12)

   def create(self):
      """Aqui colocamos a imagem masmorra na tela do jogo"""
      self.sprite("fundo")


class Monstro(Actor):
   """Essa  é a classe Monstro que controla os personagens do jogo"""
   def __init__(self, nome, frame, x, y):
      super().__init__()
      self.nome, self.frame, self.x, self.y = nome, frame, x, y

   def create(self):
      """Aqui colocamos o sprite do monstro e selecionamos o frame que o representa"""
      self.monstro = "<troque isto pela criação do sprite, use self.nome, self.x e self.y>"
      "escolha aqui o frame e use self.frame"
      self.monstro.anchor.setTo(0.5, 0.5)

if __name__ == "__main__":
  Jogo()

Animando Personagens

Vamos criar uma animação para o monstro. Use os ladrilhos onde o monstro apresenta as diversas posições:

_images/monstersheets.png
from _spy.circus.game import Circus, Actor


class Jogo(Circus):
    """Essa  é a classe Jogo que recebe os poderes da classe Circus de poder criar um jogo"""
    def __init__(self):
        super().__init__()  # super é invocado aqui para preservar os poderes recebidos do Circus
        self.ladrilho_monstro = "monstro"
        self.monstro = Monstro(self.ladrilho_monstro, 0, 0, 0)

    def preload(self):
        """Aqui no preload carregamos a imagem masmorra e a folha de ladrilhos dos monstros"""
        self.image("fundo", "http://<descubra um jeito de achar a url que vai ser posta aqui>")
        self.spritesheet(self.ladrilho_monstro, "http://<advinha!>", 64, 63, 16*12)

    def create(self):
        """Aqui colocamos a imagem masmorra na tela do jogo"""
        self.sprite("fundo")


class Monstro(Actor):
    """Essa  é a classe Monstro que controla os personagens do jogo"""
    def __init__(self, nome, frame, x, y):
        super().__init__()
        self.nome, self.frame, self.x, self.y = nome, frame, x, y

    def create(self):
        """Aqui colocamos o sprite e o frame do monstro e acrescentamos a animação"""
        self.monstro = "<troque isto pela criação do sprite, use self.nome, self.x e self.y>"
        "escolha aqui o frame e use self.frame"
        self.monstro.anchor.setTo(0.5, 0.5)
        self.monstro.animations.add('mon', [self.frame, self.frame+1, self.frame+2,], 4, True)
        self.monstro.play('mon')

if __name__ == "__main__":
    Jogo()

Movimentando Personagens

Vamos movimentar monstros. Para isso é preciso acrescentar a função update na classe Monstro.

_images/monstersheets.png
from _spy.circus.game import Circus, Actor
from random import random

MONSTROS = [(100, 100, 100), (0, 200, 100), (50, 300, 100)]
DIR = [(1,0), (1,1), (0,1), (-1,1), (-1,0), (-1,-1), (0,-1), (1,-1)]


class Jogo(Circus):
   """Essa  é a classe Jogo que recebe os poderes da classe Circus de poder criar um jogo"""
   def __init__(self):
      super().__init__()  # super é invocado aqui para preservar os poderes recebidos do Circus
      self.ladrilho_monstro = "monstro"
      self.monstro = [Monstro(self.ladrilho_monstro, frame, x, y) for frame, x, y in MONSTROS]

   def preload(self):
      """Aqui no preload carregamos a imagem masmorra e a folha de ladrilhos dos monstros"""
      self.image("fundo", "http://<descubra um jeito de achar a url que vai ser posta aqui>")
      self.spritesheet(self.ladrilho_monstro, "http://<advinha!>", 64, 63, 16*12)

   def create(self):
      """Aqui colocamos a imagem masmorra na tela do jogo"""
      self.sprite("fundo")


 class Monstro(Actor):
     """Essa  é a classe Monstro que controla os personagens do jogo"""
     def __init__(self, nome, frame, x, y):
         super().__init__()
         self.nome, self.frame, self.x, self.y = nome, frame, x, y
         self.first = True
         self.direction = 0

     def create(self):
         """Aqui colocamos o sprite do monstro e selecionamos o frame que o representa"""
         self.monstro = "<troque isto pela criação do sprite, use self.nome, self.x e self.y>"
         "bote aqui self.??o que??".frame = self.frame
         self.monstro.anchor.setTo(0.5, 0.5)
         "ponha aqui a animação"
         self.enable(self.monstro)

     def update(self):
         player = self.monstro
         def redirect():
             self.first = False
             self.direction = d = int(random() * 8.0)
             x, y = DIR[d]
             return x * 150, y * 150

         player.angle = (self.direction*45+270) % 360
         if int(random() + 0.02) or self.first:
             player.body.velocity.x, player.body.velocity.y = redirect()

if __name__ == "__main__":
  Jogo()

Indices e Tabelas