Convertendo um jogo escrito em Basic para Python - Parte I
A nostalgia dos computadores da década de 80 é algo que nunca parei de
ter. Quando criança, tive a sorte de utilizar vários computadores de
8-bits, como ZX-81, ZX-Spectrum, Apple II e MSX, ou melhor, seus clones
nacionais (TK-85, TK-90X, TK2000), uma vez que o Brasil vivia a época da
Reserva do Mercado de Informática.
Numa época que não havia Internet, nós passávamos o tempo a digitar
programas. Uma série de livros sobre programação de jogos foi editada
pela editora Lutécia no Brasil, mas os originais americanos foram
liberados pela
Usborne.
Neste artigo, eu vou traduzir o jogo principal do Computer Battlegames,
chamado de Missile, de Apple II Basic para Python com Pyglet. A listagem
original está na página 34 do livro em inglês (ver pdf acima).
10 HOME
20 HGR
30 HCOLOR=3
40 DIM Y(3),F(3)
50 N=1 : MS=5
60 PS=INT(RND(1)*6+4)
70 P=INT(RND(1)*135+11)
80 GOSUB 400
90 FOR I=PS TO 265 STEP PS
100 X=I-PS : Y=159-P : C=0 : GOSUB 300
110 X=I : C=3: GOSUB 300
120 F$="" : IF PEEK(-16384)>127 THEN GET F$
130 IF F$="" OR N>3 THEN 160
140 F(N)=1
150 N=N+1
160 FOR J=1 TO 3
170 C=0 : GOSUB 350
180 IF F(J)=0 OR Y(J)>145 THEN 230
190 Y(J)=Y(J)+MS
200 C=3 : GOSUB 350
210 X=J*70-I : Y=P-Y(J)
220 IF X>-1 AND X<15 AND Y>-9 AND Y<5 THEN 270
230 NEXT
240 NEXT
250 VTAB 22 : PRINT "MISSED"
260 END
270 VTAB 22 : PRINT "HIT!!!"
280 END
300 HCOLOR=C
310 HPLOT X,Y TO X,Y-8
320 HPLOT TO X+3,Y-2 : HPLOT TO X+12, Y-2
330 HPLOT TO X+14,Y : HPLOT TO X,Y
340 RETURN
350 HCOLOR=C
360 HPLOT 70*J,158-Y(J) TO 70*J,154-Y(J)
340 RETURN
350 HCOLOR=C
360 HPLOT 70*J, 158-Y(J) TO 70*J,154-Y(J)
370 RETURN
400 FOR J=1 TO 3
410 HPLOT 70*J-5,159 TO 70*J+5,159
420 NEXT
430 RETURN
Vejamos o jogo rodando em um emulador:
{
Versão comentada:
# Limpa a tela
10 HOME
# Entra no modo de alta resolução 280x192
20 HGR
# Seleciona a cor 3 (purpura/magenta)
30 HCOLOR=3
# Cria dois vetores com 3 elementos cada
40 DIM Y(3),F(3)
# Inicializa N igual a 1 e MS igual a 5
50 N=1 : MS=5
# Gera um número aleatório entre 0 e 6 + 4
60 PS=INT(RND(1)*6+4)
# Gera um número aleatório entre 0 e 135 + 11
70 P=INT(RND(1)*135+11)
# Desvia para subrotina
80 GOSUB 400
# Loop: repete I de PS até 265, incrementando de PS
90 FOR I=PS TO 265 STEP PS
# Calcula os valores de X, Y e C. Desvia para subrotina em 300
100 X=I-PS : Y=159-P : C=0 : GOSUB 300
# Define X e C. Desvia para subrotina 300
110 X=I : C=3: GOSUB 300
# Verifica se uma tecla foi pressionada. Se foi, guarda em F
120 F$="" : IF PEEK(-16384)>127 THEN GET F$
# Se algo foi pressionado ou se N>3 desvia para 160
130 IF F$="" OR N>3 THEN 160
# F[N] = 1
140 F(N)=1
# N+=1
150 N=N+1
# Repete J de 1 até 3
160 FOR J=1 TO 3
# Zera C e desvia para subrotina da linha 350
170 C=0 : GOSUB 350
# Se F[J]==0 ou Y[J]>145 desvia para 230
180 IF F(J)=0 OR Y(J)>145 THEN 230
# Y[J]+=MS
190 Y(J)=Y(J)+MS
# C=3. Desvia para subrotina da linha 350
200 C=3 : GOSUB 350
# Calcula X e Y
210 X=J*70-I : Y=P-Y(J)
# Se X>-1 e X<15 e Y>-9 e Y<5 desvia para 270
220 IF X>-1 AND X<15 AND Y>-9 AND Y<5 THEN 270
# Fim do loop, volta para o for da linha 160
230 NEXT
# Fim do loop, volta para for da linha 90
240 NEXT
# Posiciona o cursor na linha 22 e imprime MISSED
250 VTAB 22 : PRINT "MISSED"
# Termina o programa
260 END
# Posiciona o cursor na linha 22 e imprime HIT!!!
270 VTAB 22 : PRINT "HIT!!!"
# Termina o programa
280 END
# Troca a cor de desenho para C
300 HCOLOR=C
# Traça uma linha de X,Y até X,Y-8
310 HPLOT X,Y TO X,Y-8
# Continua a linha
320 HPLOT TO X+3,Y-2 : HPLOT TO X+12, Y-2
330 HPLOT TO X+14,Y : HPLOT TO X,Y
# Retorno da subrotina
340 RETURN
# Troca a cor de desenho para C
350 HCOLOR=C
# Desenha linha
360 HPLOT 70*J,158-Y(J) TO 70*J,154-Y(J)
# Volta da subrotina
340 RETURN
# Troca a cor para C
350 HCOLOR=C
# Desenha linha
360 HPLOT 70*J, 158-Y(J) TO 70*J,154-Y(J)
# Volta da subrotina
370 RETURN
# Repete J de 1 à 3
400 FOR J=1 TO 3
# Desenha linha
410 HPLOT 70*J-5,159 TO 70*J+5,159
# Fim do loop, volta para linha 400
420 NEXT
# Retorna da subrotina
430 RETURN
Bom, como precisaremos desenhar, vamos instalar a Pyglet:
pip3 install pyglet
A primeira coisa a fazer é criar a janela da Pyglet e separar a janela
do jogo em si. No caso, a janela é responsável por receber os eventos do
teclado. A configuração do OpenGL também precisam ser feitas aqui. Como
a alta resolução do Apple II é muito pequena 280x192 pontos, eu estou
usando uma escala 4. Desta forma, as coordenadas permanecerão as mesmas,
mas os gráficos serão 4 vezes maiores. Se ficar muito grande em seu
monitor, você pode ajustar a escala.
Eu tentei manter os comentários originais para ficar mais fácil de
relacionar o código novo com o antigo.
Outra mudança são as coordenadas Y. No Apple II, Y = 0 é a primeira
linha e em OpenGL é a última.
Vejamos como ficou o código da janela:
class Missile(pyglet.window.Window):
# 20 HGR
def __init__(self):
self.scale = 4 # Escala os gráficos 4x
self.frames = 8 # Frames por segundo.
# Define quantas vezes vamos atualizar a tela por segundo
super(Missile, self).__init__(280 * self.scale,
192 * self.scale,
caption="Missiles")
self.set_mouse_visible(False)
self.game = Game(self)
self.schedule = pyglet.clock.schedule_interval(
func=self.update, interval=1.0 / self.frames)
def update(self, interval):
pass
def on_draw(self):
window.clear()
self.game.atualiza()
def on_resize(self, width, height):
# Inicializa a view
glViewport(0, 0, width, height)
glMatrixMode(gl.GL_PROJECTION)
glLoadIdentity()
# Inverte as coordenadas do eixo Y
glOrtho(0, width, height, 0, -1, 1)
# Aplica a escala
glScalef(self.scale, self.scale, 1.0)
glMatrixMode(gl.GL_MODELVIEW)
def on_key_press(self, symbol, modifiers):
# Verifica se uma tecla foi pressionada. Se foi, guarda em F
# 120 F$="" : IF PEEK(-16384)>127 THEN GET F$
self.game.pressionado = True
def crialabel(self, mensagem, x=None, y=None,
fonte='Times New Roman', tamanho=36):
"""Prepara uma mensagem de texto para ser exibida"""
x = x or self.width // 2
y = y or self.height // 2
return pyglet.text.Label(
mensagem, font_name=fonte, font_size=tamanho,
x=x, y=y, anchor_x='center', anchor_y='center')
Além disso, as cores do Apple II precisam ser definidas:
def rgb_to_f(r, g, b):
return(r / 255.0, g / 255.0, b / 255.0)
# Cores do modo de alta resolução HGR
# Fonte: https://github.com/AppleWin/AppleWin/issues/254
CORES = [(0.0, 0.0, 0.0), # Preto 0
rgb_to_f(20, 245, 60), # Verde 1
rgb_to_f(255, 68, 253), # Magenta 2
rgb_to_f(255, 255, 255), # Branco 3
rgb_to_f(255, 106, 60), # Laranja 5
rgb_to_f(20, 207, 253), # Azul médio 6
rgb_to_f(255, 255, 255), # Branco 7
]
e finalmente a classe Game com o jogo em si. Observar que os índices em Python começam em 0 e em Basic começam com 1. Primeiro passo da conversão:
class Game():
def __init__(self, parent):
self.cor = CORES
self.window = parent
# Cria dois vetores com 3 elementos cada
# 40 DIM Y(3),F(3)
self.Y = [0] * 3
self.F = [0] * 3
# Inicializa N igual a 1 e MS igual a 5
# 50 N=1 : MS=5
self.N = 0
self.MS = 5
# Gera um número aleatório entre 0 e 6 + 4
# 60 PS=INT(RND(1)*6+4)
self.PS = random.randint(0, 6) + 4
# Gera um número aleatório entre 0 e 135 + 11
# 70 P=INT(RND(1)*135+11)
self.P = random.randint(0, 135) + 11
self.estado = "jogando"
self.I = self.PS
self.pressionado = False
self.label = None
def atualiza(self):
if self.estado == "jogando":
self.jogue()
else:
if self.label:
glMatrixMode(gl.GL_PROJECTION)
glLoadIdentity()
glOrtho(0, self.window.width, 0, self.window.height, -1, 1)
glMatrixMode(gl.GL_MODELVIEW)
self.label.draw()
if self.pressionado:
pyglet.app.event_loop.exit()
def jogue(self):
# Desvia para subrotina
# 80 GOSUB 400
self.sub_400()
# Loop: repete I de PS até 265, incrementando de PS
# 90 FOR I=PS TO 265 STEP PS
if self.I > 265:
self.sub_250()
return
# Calcula os valores de X, Y e C. Desvia para subrotina em 300
# 100 X=I-PS : Y=159-P : C=0 : GOSUB 300
self.X = self.I - self.PS
self.y = 159 - self.P
self.C = 0
self.sub_300()
# Define X e C. Desvia para subrotina 300
# 110 X=I : C=3: GOSUB 300
self.X = self.I
self.C = 3
self.sub_300()
# Se algo foi pressionado ou se N>3 desvia para 160
# 130 IF F$="" OR N>3 THEN 160
if self.pressionado and self.N < 3:
# F[N] = 1
# 140 F(N)=1
self.F[self.N] = 1
# N+=1
# 150 N=N+1
self.N += 1
self.pressionado = False
# Repete J de 1 até 3
# 160 FOR J=1 TO 3
for self.J in range(0, 3):
# Zera C e desvia para subrotina da linha 350
# 170 C=0 : GOSUB 350
self.C = 0
self.sub_350()
# Se F[J]==0 ou Y[J]>145 desvia para 230
# 180 IF F(J)=0 OR Y(J)>145 THEN 230
if self.F[self.J] == 0 or self.Y[self.J] > 145:
continue
# Y[J]+=MS
# 190 Y(J)=Y(J)+MS
self.Y[self.J] += self.MS
# C=3. Desvia para subrotina da linha 350
# 200 C=3 : GOSUB 350
self.C = 3
self.sub_350()
# Calcula X e Y
# 210 X=J*70-I : Y=P-Y(J)
self.X = (self.J + 1) * 70 - self.I
self.y = self.P - self.Y[self.J]
# Se X>-1 e X<15 e Y>-9 e Y<5 desvia para 270
# 220 IF X>-1 AND X<15 AND Y>-9 AND Y<5 THEN 270
if self.X > -1 and self.X < 15 and self.y > -9 and self.y < 5:
self.sub_270()
# Fim do loop, volta para o for da linha 160
# 230 NEXT
# Fim do loop, volta para for da linha 90
# 240 NEXT
# 90 FOR I=PS TO 265 STEP PS
self.I += self.PS
def sub_250(self):
# Posiciona o cursor na linha 22 e imprime MISSED
# 250 VTAB 22 : PRINT "MISSED"
print("MISSED")
self.imprima("MISSED")
# Termina o programa
# 260 END
self.muda_estado("fimdejogo")
def sub_270(self):
# Posiciona o cursor na linha 22 e imprime HIT!!!
# 270 VTAB 22 : PRINT "HIT!!!"
print("HIT")
self.imprima("HIT!!!")
# Termina o programa
self.muda_estado("fimdejogo")
def sub_300(self):
# Troca a cor de desenho para C
# 300 HCOLOR=C
self.set_color(self.C)
# Traça uma linha de X,Y até X,Y-8
# 310 HPLOT X,Y TO X,Y-8
# Continua a linha
# 320 HPLOT TO X+3,Y-2 : HPLOT TO X+12, Y-2
# 330 HPLOT TO X+14,Y : HPLOT TO X,Y
pyglet.graphics.draw(6, pyglet.gl.GL_LINE_LOOP,
('v2i', (self.X, self.y,
self.X, self.y - 8,
self.X + 3, self.y - 2,
self.X + 12, self.y - 2,
self.X + 14, self.y,
self.X, self.y)))
# Retorno da subrotina
# 340 RETURN
def sub_350(self):
# Troca a cor para C
# 350 HCOLOR=C
self.set_color(self.C)
# Desenha linha
# 360 HPLOT 70*J, 158-Y(J) TO 70*J,154-Y(J)
J = self.J + 1
pyglet.graphics.draw(2, pyglet.gl.GL_LINES,
('v2i', (70 * J, 158 - self.Y[self.J],
70 * J, 154 - self.Y[self.J])))
# Volta da subrotina
# 370 RETURN
def sub_400(self):
self.set_color(3)
# 400 FOR J=1 TO 3
for J in range(1, 4):
# Desenha linha
# 410 HPLOT 70*J-5,159 TO 70*J+5,159
pyglet.graphics.draw(2, pyglet.gl.GL_LINES,
('v2i', (70 * J - 5, 159,
70 * J + 5, 159)))
# Fim do loop, volta para linha 400
# 420 NEXT
# Retorna da subrotina
# 430 RETURN
def set_color(self, color):
glColor3f(*self.cor[color])
def muda_estado(self, estado):
print("Mudança de Estado: {} --> {}".format(self.estado, estado))
self.estado = estado
def imprima(self, mensagem):
self.label = self.window.crialabel(mensagem)
Como em OpenGL limpamos a tela a cada frame, a rotina que apaga os
objetos pode ser apagada. No caso, a chamada a sub_300() com C=0.
O nome dos métodos ainda não foram mudados, vamos renomear:
sub_250 para perdeu
sub_270 para acertou
sub_300 para desenha_aviao
sub_350 para desenha_tiro
sub_400 para desenha_bases
Apagando os comentários com o código em Basic, temos:
import pyglet
from pyglet.gl import *
import random
def rgb_to_f(r, g, b):
return(r / 255.0, g / 255.0, b / 255.0)
# Cores do modo de alta resolução HGR
# Fonte: https://github.com/AppleWin/AppleWin/issues/254
CORES = [(0.0, 0.0, 0.0), # Preto 0
rgb_to_f(20, 245, 60), # Verde 1
rgb_to_f(255, 68, 253), # Magenta 2
rgb_to_f(255, 255, 255), # Branco 3
rgb_to_f(255, 106, 60), # Laranja 5
rgb_to_f(20, 207, 253), # Azul médio 6
rgb_to_f(255, 255, 255), # Branco 7
]
class Game():
def __init__(self, parent):
self.cor = CORES
self.window = parent
# Cria dois vetores com 3 elementos cada
self.Y = [0] * 3
self.F = [0] * 3
# Inicializa N igual a 1 e MS igual a 5
self.N = 0
self.MS = 5
# Gera um número aleatório entre 0 e 6 + 4
self.PS = random.randint(0, 6) + 4
# Gera um número aleatório entre 0 e 135 + 11
self.P = random.randint(0, 135) + 11
self.estado = "jogando"
self.I = self.PS
self.pressionado = False
self.label = None
def atualiza(self):
if self.estado == "jogando":
self.jogue()
else:
if self.label:
glMatrixMode(gl.GL_PROJECTION)
glLoadIdentity()
glOrtho(0, self.window.width, 0, self.window.height, -1, 1)
glMatrixMode(gl.GL_MODELVIEW)
self.label.draw()
if self.pressionado:
pyglet.app.event_loop.exit()
def jogue(self):
self.desenha_bases()
if self.I > 265:
self.perdeu()
return
self.X = self.I - self.PS
self.y = 159 - self.P
self.C = 0
self.desenha_aviao()
self.X = self.I
self.C = 3
self.desenha_aviao()
if self.pressionado and self.N < 3:
self.F[self.N] = 1
self.N += 1
self.pressionado = False
for self.J in range(0, 3):
if self.F[self.J] == 0 or self.Y[self.J] > 145:
continue
self.Y[self.J] += self.MS
self.C = 3
self.desenha_tiro()
self.X = (self.J + 1) * 70 - self.I
self.y = self.P - self.Y[self.J]
if self.X > -1 and self.X < 15 and self.y > -9 and self.y < 5:
self.acertou()
self.I += self.PS
def perdeu(self):
self.imprima("MISSED")
self.muda_estado("fimdejogo")
def acertou(self):
self.imprima("HIT!!!")
self.muda_estado("fimdejogo")
def desenha_aviao(self):
self.set_color(self.C)
pyglet.graphics.draw(6, pyglet.gl.GL_LINE_LOOP,
('v2i', (self.X, self.y,
self.X, self.y - 8,
self.X + 3, self.y - 2,
self.X + 12, self.y - 2,
self.X + 14, self.y,
self.X, self.y)))
def desenha_tiro(self):
self.set_color(self.C)
J = self.J + 1
pyglet.graphics.draw(2, pyglet.gl.GL_LINES,
('v2i', (70 * J, 158 - self.Y[self.J],
70 * J, 154 - self.Y[self.J])))
def desenha_bases(self):
self.set_color(3)
for J in range(1, 4):
pyglet.graphics.draw(2, pyglet.gl.GL_LINES,
('v2i', (70 * J - 5, 159,
70 * J + 5, 159)))
def set_color(self, color):
glColor3f(*self.cor[color])
def muda_estado(self, estado):
print("Mudança de Estado: {} --> {}".format(self.estado, estado))
self.estado = estado
def imprima(self, mensagem):
self.label = self.window.crialabel(mensagem)
class Missile(pyglet.window.Window):
def __init__(self):
self.scale = 4 # Escala os gráficos 4x
self.frames = 8 # Frames por segundo.
# Define quantas vezes vamos atualizar a tela por segundo
super(Missile, self).__init__(280 * self.scale,
192 * self.scale,
caption="Missiles")
self.set_mouse_visible(False)
self.game = Game(self)
self.schedule = pyglet.clock.schedule_interval(
func=self.update, interval=1.0 / self.frames)
def update(self, interval):
pass
def on_draw(self):
window.clear()
self.game.atualiza()
def on_resize(self, width, height):
# Inicializa a view
glViewport(0, 0, width, height)
glMatrixMode(gl.GL_PROJECTION)
glLoadIdentity()
# Inverte as coordenadas do eixo Y
glOrtho(0, width, height, 0, -1, 1)
# Aplica a escala
glScalef(self.scale, self.scale, 1.0)
glMatrixMode(gl.GL_MODELVIEW)
def on_key_press(self, symbol, modifiers):
self.game.pressionado = True
def crialabel(self, mensagem, x=None, y=None,
fonte='Times New Roman', tamanho=36):
"""Prepara uma mensagem de texto para ser exibida"""
x = x or self.width // 2
y = y or self.height // 2
return pyglet.text.Label(
mensagem, font_name=fonte, font_size=tamanho,
x=x, y=y, anchor_x='center', anchor_y='center')
window = Missile()
pyglet.app.run()
Bem melhor, mas ainda guarda várias características do programa em Basic. O nome das variáveis é uma catástrofe. Renomeando as variáveis e melhorando os comentários, o programa completo fica assim:
import pyglet
from pyglet.gl import *
import random
def rgb_to_f(r, g, b):
return(r / 255.0, g / 255.0, b / 255.0)
# Cores do modo de alta resolução HGR
# Fonte: https://github.com/AppleWin/AppleWin/issues/254
CORES = [(0.0, 0.0, 0.0), # Preto 0
rgb_to_f(20, 245, 60), # Verde 1
rgb_to_f(255, 68, 253), # Magenta 2
rgb_to_f(255, 255, 255), # Branco 3
rgb_to_f(255, 106, 60), # Laranja 5
rgb_to_f(20, 207, 253), # Azul médio 6
rgb_to_f(255, 255, 255), # Branco 7
]
class Game():
def __init__(self, parent):
self.cor = CORES
self.window = parent
# Cria dois vetores com 3 elementos cada
self.Y = [0] * 3 # Altura do tiro
self.F = [0] * 3 # Estado do tiro
self.tiros_disparados = 0 # tiros já disparados
self.velocidade_do_tiro = 5
# Gera um número aleatório entre 0 e 6 + 4
self.velocidade_aviao = random.randint(0, 6) + 4
# Gera um número aleatório entre 0 e 135 + 11
self.altura_do_aviao = random.randint(0, 135) + 11
self.estado = "jogando"
self.posicao_do_aviao = self.velocidade_aviao
self.pressionado = False
self.label = None
def atualiza(self):
if self.estado == "jogando":
self.jogue()
else:
if self.label:
glMatrixMode(gl.GL_PROJECTION)
glLoadIdentity()
glOrtho(0, self.window.width, 0, self.window.height, -1, 1)
glMatrixMode(gl.GL_MODELVIEW)
self.label.draw()
if self.pressionado:
pyglet.app.event_loop.exit()
def jogue(self):
self.desenha_bases()
if self.posicao_do_aviao > 265:
self.perdeu()
return
self.y = 159 - self.altura_do_aviao
self.X = self.posicao_do_aviao
self.C = 3
self.desenha_aviao()
if self.pressionado and self.tiros_disparados < 3:
self.F[self.tiros_disparados] = 1
self.tiros_disparados += 1
self.pressionado = False
self.processa_tiros()
self.posicao_do_aviao += self.velocidade_aviao
def processa_tiros(self):
for self.J in range(0, 3):
if self.F[self.J] == 0 or self.Y[self.J] > 145:
continue
self.Y[self.J] += self.velocidade_do_tiro
self.C = 3
self.desenha_tiro()
self.X = (self.J + 1) * 70 - self.posicao_do_aviao
self.y = self.altura_do_aviao - self.Y[self.J]
if self.X > -1 and self.X < 15 and self.y > -9 and self.y < 5:
self.acertou()
def perdeu(self):
self.imprima("MISSED")
self.muda_estado("fimdejogo")
def acertou(self):
self.imprima("HIT!!!")
self.muda_estado("fimdejogo")
def desenha_aviao(self):
self.set_color(self.C)
pyglet.graphics.draw(6, pyglet.gl.GL_LINE_LOOP,
('v2i', (self.X, self.y,
self.X, self.y - 8,
self.X + 3, self.y - 2,
self.X + 12, self.y - 2,
self.X + 14, self.y,
self.X, self.y)))
def desenha_tiro(self):
self.set_color(self.C)
J = self.J + 1
pyglet.graphics.draw(2, pyglet.gl.GL_LINES,
('v2i', (70 * J, 158 - self.Y[self.J],
70 * J, 154 - self.Y[self.J])))
def desenha_bases(self):
self.set_color(3)
for J in range(1, 4):
pyglet.graphics.draw(2, pyglet.gl.GL_LINES,
('v2i', (70 * J - 5, 159,
70 * J + 5, 159)))
def set_color(self, color):
glColor3f(*self.cor[color])
def muda_estado(self, estado):
print("Mudança de Estado: {} --> {}".format(self.estado, estado))
self.estado = estado
def imprima(self, mensagem):
self.label = self.window.crialabel(mensagem)
class Missile(pyglet.window.Window):
def __init__(self):
self.scale = 4 # Escala os gráficos 4x
self.frames = 8 # Frames por segundo.
# Define quantas vezes vamos atualizar a tela por segundo
super(Missile, self).__init__(280 * self.scale,
192 * self.scale,
caption="Missiles")
self.set_mouse_visible(False)
self.game = Game(self)
self.schedule = pyglet.clock.schedule_interval(
func=self.update, interval=1.0 / self.frames)
def update(self, interval):
pass
def on_draw(self):
window.clear()
self.game.atualiza()
def on_resize(self, width, height):
# Inicializa a view
glViewport(0, 0, width, height)
glMatrixMode(gl.GL_PROJECTION)
glLoadIdentity()
# Inverte as coordenadas do eixo Y
glOrtho(0, width, height, 0, -1, 1)
# Aplica a escala
glScalef(self.scale, self.scale, 1.0)
glMatrixMode(gl.GL_MODELVIEW)
def on_key_press(self, symbol, modifiers):
self.game.pressionado = True
def crialabel(self, mensagem, x=None, y=None,
fonte='Times New Roman', tamanho=36):
"""Prepara uma mensagem de texto para ser exibida"""
x = x or self.width // 2
y = y or self.height // 2
return pyglet.text.Label(
mensagem, font_name=fonte, font_size=tamanho,
x=x, y=y, anchor_x='center', anchor_y='center')
window = Missile()
pyglet.app.run()
Em um próximo artigo, vou continuar a refatorar o código. Tiro e Avião são claramente classes. Animação deixa a desejar. Mas é o divertido da programação, você sempre pode melhorar.