Como todos sabem (ou, ao menos eu e meu ego gostaríamos que soubessem) o Retromania foi o jogo que apresentei no Tenliner challenge do MSX Resource Center. Foram ao todo dezenove participantes e no final atingi a oitava colocação — razoável para minha primeira participação neste tipo de competição.
Mas agora uma parte que nem todo mundo sabe… Minha ideia era fazer uma espécie de Space Invaders mas conforme ia pensando a respeito de como fazer as coisas, constatava o quanto seria complicado de caber nas singelas dez linhas, assim mudei a inspiração para o Megamania.
Alguns comentários iniciais
O jogo foi sendo digerido na minha cabeça por cerca de dois dias, demorei outros dois para fazer os gráficos necessários — que foram feitos no GIMP, exportados e (re)coloridos manualmente no MSX –, o tanque (que é a parte superior de um FS A1GT), os retroinvasores e os blocos semigráficos para o desenho do nome (as letras eu já possuía). Para o código propriamente dito (as tais 10 linhas) eu demorei apenas um dia, mas levei mais alguns acertando “maluquices” e tentando deixá-lo o mais otimizado possível para modelos de MSX rodando a 3,54MHz.
Cada uma das linhas será exibida como se você estivesse visualizando o código na tela, justamente por conta dos caracteres redefinidos e também para dar a sensação de código sendo lido diretamente na tela do MSX.
A primeira parte
E aqui vão as primeiras cinco linhas do jogo.
LINHA 100
Aqui começa o programa, uso o BEEP para zerar todos os registradores do PSG de uma vez só (truque sujo mas incrivelmente prático), reservo 512 bytes para a área de strings e também digo ao BASIC que todas as variáveis numéricas serão inteiras. E aqui o Z80 agradece, pois é muito melhor manipular dois bytes do que executar o malabarismo de expoente e mantissa para trabalhar com valores numéricos (que sempre serão inteiros). Até poderia acrescentar o símbolo de “%” às variáveis pra indicar que são do INTEGER mas como só tenho 10 linhas não posso desperdiçar espaço. (aliás, viram que não há espaços entre os comandos?)
Removo as teclas de função no rodapé da tela, mudo as cores, entro na SCREEN 1 e fixo a largura da tela em 32 caracteres. Defino que uma das rotina do usuário (“USR0”) chamará a KILLBUFF (que zera o buffer do teclado) da BIOS e, finalmente, ajusto registradores do VDP para que tudo fique de acordo com minhas necessidades.
Como as regras diziam que eu poderia carregar algo do disco, mas não eram muito claras sobre quantas vezes poderia fazê-lo, preferi não arriscar muito e carregar o que precisava de uma vez só, um bloco de 2KB do disco (“RETROMAN.VDP”) para a VRAM a partir do endereço 0 (está lá definido no cabeçalho dele) e que corresponde às tabelas de padrões e de atributos da SCREEN 1. Também coloco a parte correspondente à tabela de atributos em seu lugar correto (a partir de 8192).
As variáveis aqui… (sempre em ordem alfabética)
- I$() — “Invader” — Um array de 8 elementos (de 0 até 7) que conterá as strings com os retroinvasores, o conteúdo será montado na próxima linha.
LINHA 110
Uma penca de definições de variáveis e definição do SPRITE 0 (para ter a forma de um ” | “). Os desenhos que se seguem ao DATA são respectivamente os caracteres: rst (ZX Spectrum), opq (TRS-80 Color), lmn (Amstrad CPC), ijk (Commodore 64), fgh (Apple II), cde (Atari ST), `ab (Amiga) e xyz (MSX). E quem se sentir ofendido em atirar em seu micro predileto pode simplesmente substituí-lo pelos caracteres uvw (Acorn) ficaram sobrando (nada contra Garrett!).
As variáveis aqui…
- F — “Fire”– É minha flag que verifica se o programa precisa, ou não, tratar o fato de que um disparo foi feito.
- L$ — “Locate” — É o começo da sequência de escape do terminal VT-52 para o posicionamento do cursor (ESC+Y+{32+linha}+{32+coluna}).
- I$ — “Invader” — Variável provisória onde eu leio o padrão correspondente ao retroinvasor antes de alimentar o array I$().
- IX( ) — “Invader X” — Um array que contém o deslocamento horizontal das hordas de retroinvasores e que tem correlação direta com o array I$(). É o que faz com que eles desçam sinuosamente pela tela, se descessem todos em uma fileira ficaria muito fácil.
- N$ — “New line” — É a sequência de escape do VT-52 para se inserir uma linha a partir do cursor (ESC+N).
- S$ –“Space” — São exatamente dois espaços, é ela quem define a distância entre os retroinvasores (poderia ser opcional mas resolvi deixar fácil de ajustar o espaçamento entre os carinhas).
- TK$ — “TanK” — É o meu tanque na batalha!
LINHA 120
Esta linha inteira faz a tela de abertura! O logotipo do jogo é formado por 256 caracteres que estão codificado dentro da tabela de padrões entre os endereços 0 e 127 da VRAM, cada byte contém dois caracteres (separados nos 4 bits mais e menos significativos), os desenhos correspondem aos caracteres de 16 até 31 (e imitando a mesma ordem dos blocos semi-gráficos no TRS-80 Color) e são desenhados a partir do endereço 6368 da VRAM (coluna 0 e linha 7 da tela — 6144+32.Y+X = 6144+7*32+0 = 6368). No PRINT seguinte o “/ ” posiciona o cursor na linha 15 e coluna 0 da tela.
Por último eu simulo um “DO … WHILE” pervertendo um “FOR … NEXT” que só sairá caso a tecla ENTER seja pressionada. Hoje eu poderia escrevê-lo assim:
(...) FOR I=USR0(0) to 2:I=-2*(INKEY$=CHR$(13)):NEXT
O truque é simples, sempre que o comando NEXT é encontrado o interpretador incrementa a variável em 1, ou o valor indicado em STEP, e verifica se atingiu o valor máximo indicado no FOR, em caso afirmativo ele sai do laço mas se ainda não alcançou ele o repetirá mais uma vez. Sendo assim o truque é GARANTIR de que só seja alcançado tal valor quando REALMENTE for o caso.
LINHA 130
Aqui finalmente começa o jogo! Faço a limpeza da tela (por razões óbvias), ajusto os valores do primeiro canal de áudio do PSG, na linha 22 e coluna 0 desenho o solo, escrevo a pontuação e na linha 23 e coluna 21 escrevo o nome do jogo.
E quanto aos VPOKE? O seguinte comando em MSX-BASIC:
PUT SPRITE 0,(128,95),15,0
Pode ser escrito como:
VPOKE 6912,95:VPOKE 6913,128:VPOKE 6914,15
Mas por que fiz assim? No final seria indiferente, pois queria apenas inicializar o sprite mas acabei deixando-o em VPOKE por questões puramente didáticas.
As variáveis aqui…
- AL — Sinceridade? Defini e não usei, está aqui só ocupando espaço. Mas suspeito que ela virou a variável IL!
- AW — Outra variável que defini e acabei não utilizando.
- SC — SCore — A pontuação.
- TK — TanK — Guarda a posição horizontal do tanque, ela sempre será X+32.
- NW — New Wave — Esta variável define a quantidade de tempo que deverá se passar antes de aparecer uma nova onda de retroinvasores na tela, quanto maior mais tempo demorará para uma nova onda surgir na tela.
- IW — Invaders Wave — É o contador que indica quando é hora de produzir uma nova onda de retroinvasores. Seu valor já é máximo para produzir uma nova onda logo no começo do jogo (assim o jogador não precisa esperar para iniciar a matança).
Linha 140
Aqui é temos uma o laço principal! Zero a variável de temporização do MSX-BASIC, a TIME. Leio o que está sendo feito no teclado e joystick (funções STICK e STRIG) e incremento a variável IW. Sempre que IW ultrapassar NW eu produzo uma nova onda de aterradores retroinvasores, ou seja, posiciono o cursor em 0,0 e mando o código VT-52 para inserir uma linha e, consequentemente, tudo que estiver abaixo ser deslocado rapidamente para baixo!
Mas e como é que o canhão, o solo e todo o resto não desaparecem na tela? Simples! O endereço &HF3B1 (-3151 pois é mais curto) da RAM, a variável LINLEN onde o interpretador armazena o número de linhas da tela. Logo, digo que são 21 linhas de tela, quando termino volto para as 24 de sempre e o MSX-BASIC nem percebe que foi enganado.
E claro, sempre que IW for a metade de NW, eu insiro uma linha em branco.
As variáveis aqui…
- IL — Invader Line — Armazena a linha atual de invasores que deverá ser desenhada, serve para fazer a alternância entre as linhas.
- JK — Joystick or Keyboard — O que? Você não sabia que o Retromania podia ser jogado também pelo joystick 1 do MSX?
- TG — TriGger — Registra a pressão da barra de espaço e/ou do botão A do joystick 1
Finalizando por enquanto…
E por enquanto é só, sábado tem mais!
Sensacional!!!
Muito de longe, sem a menor sombra de dúvidas… O melhor de todos os posts desse blog.
Parabéns!!
P.s: Qual foi o outro jogo que você fez para a MSXBr-l? Passou desapercebido por mim e você não me respodeu por lá.
Tenho dois joguinhos bem tosquinhos, um feito de direto para a MSXBR-L chamado “Bombway” e que teve a função de mostrar como é/era a dinâmica de um jogo em BASIC. E o outro é o “Isneiki” a minha versão para o popular jogo da cobrinha que habitava os celulares na época em que eles tinham teclado físico. Seriam estes?
O tópico não era exatamente sobre seus jogos. Alguém citou um deles, feito em torno de 2007 (ou seria 1997?), mas eu não lembro qual era tópico. 🙁
Como é esse Bombway? O de cobrinha, acho que não era.
Mas se você puder mandar os dois para quem perdeu ou para quem não estava por lá na época, seria legal. 🙂
Abraço.
Luiz, o ISNEIKI é parte integrante do FFYM# 2.5 e que saiu como parte do MSX Force #9. Aqui para baixo o Juan colocou o link para a página, quanto ao Bombway — https://docs.google.com/file/d/0B7M3NtvRHB9qVDNnVW83VVBOVEE/edit?usp=sharing — mas é um joguinho bem tosco, mas vale pelo código.
Legal !!! Gostei mesmo !!!
Kudos!!!
Ainda não rodei, nem li a segunda parte do “desmonte”, mas já achei sensacional! Parabéns!
Muito bom este post!
Curti a ideia do “locate” através de sequência de escape.
O “for” pervertido foi viajante demais! 😀
Abraços,
e1000
Usar a sequência de ESCAPE torna-se interessante quando você descobre que o MSX-BASIC kun — http://www.generation-msx.nl/software/ascii/msx-basic-kun/release/721/ — não suporta o LOCATE.
muitos kudos , essa matéria vem de encontro ao aniversário do MSX , abraços Giovanni!
links quebrados…
http://msxrio.cipsga.org.br/files/ffym25_dsk.lha
http://msxrio.cipsga.org.br/files/ffym25.lha
http://www.msxrio.com.br/msx-force/ffym/
Sensacional!
Fantástico! Esperando a segunda parte.