A nostalgia dos computadores da década de 80 é algo que nunca parei de ter. Quando criança, tive a sorte de utilzar 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 RETURNVejamos 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 RETURNBom, 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 pedeu
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.
Nenhum comentário:
Postar um comentário