quarta-feira, 6 de junho de 2012

Programação: Jogos MSX1

Da primeira vez que possui um MSX 1.0, no final dos anos 80 e começo dos 90, sempre tentava programar jogos. Fazia varias telas com desenhos elaborado em modo screen 2, telas de apresentação, sprites em movimento. Porém, sempre esbarrava em três problemas: 1) quando movimentava o sprite do jogador com o teclado ou joystick, os sprites controlados pelo computador não se movimentavam, ou quando conseguia o contrario o jogador não se movia, ou quando conseguia os dois, o cenário ficava paralisado; 2) as figuras formadas por  mais de um sprite não se moviam juntas e sempre parecia que não estavam "coladas" uma nas outras; 3) as telas de cenários sempre eram mostradas sendo pintadas pela comando paint. Naquela época não havia internet e muito pouca informação havia nos manuais.

Depois de muito tempo, após fazer engenharia e aprender a programar para PC em 2D e 3D, voltei ao velho exercício em basic e descobri a solução para os problemas acima.

1) O loop básico de jogos:
    Para conseguir que tudo na tela se mova ao mesmo tempo é preciso implementar o conceito mais básico de loop de jogos eletrônicos:
  • Ler o input do usuário (joystick Teclado)
  • Atualizar as coordenadas X,Y ( e Z, se houver) do jogador segundo regras de movimentação ( física do jogador, etc.).
  • Atualizar a posição dos objetos do cenário
  • Atualizar a posição dos personagens controlados pelo computador
  • Verificar colisão de sprites e tomar as ações necessárias
  • Desenhar tudo na tela.
  • voltar p/ o 1o passo.
O loop básico pode apresentar algumas variações, mais esse o minimo necessário para fazer um jogo. Note que no MSX, provavelmente para a maioria dos jogos, não era feito contagem de tempo em cada interação do loop como nos PCs modernos, para que o jogo rode com a mesma velocidade em diferentes micros.

2) neste caso a melhor opção é codificar o jogo em assembler, pois é muito mais rápido do que o Basic, e há técnicas que não serão discutidas neste post para evitar o problema.

3) neste caso a saída e desenhar direto na memória de video usando comandos POKE ou assembler. Ñão seria possível usar a técnica conhecida como double buffer, muito usado para jogos de hoje. Esta técnica consiste em criar o desenho da tela em um porção de memória (buffer) e depois copiar o buffer na memória de video. Isso dado a limitação de memória do MSX1 ser de 32k para programas residentes na RAM e 16k para o VDP. Mesma questão dos video games de 8 bits da época.

No que dis respeito aos modos da VDP para o MSX1, as opções são:
  • Screen 1 (modo texto 2)
  • Screen 2 (modo gráfico 1)
Tanto no screen 1 como no 2 temos uma resolução de 256 por 192 pixels de imagem e até 32 sprites.

No screen 1 cada setor de 8 x 8 pixels pode usar 2 cores das 16 disponiveis. Sendo que cada grupo de 8 characteres na memoria de padrões devem usar somente duas cores.
No screen 2 cada linha de 8 pixels pode usar 2 cores das 16 disponiveis.

Parece que muitos jogos da época usavam o screen 1 ao invés do screen 2. Assim os desenhos dos plano de fundo eram construídos usando caracteres (tiles) redefinidos com até duas cores cada um. Na verdade ao inves de "escrever" texto na tela o código do jogo escrevia texto mas com os caracteres redefinidos como elementos gráficos. Depois era so desenhar os sprites e pronto.

Assim em resuma os jogos de MSX eram compostos de um plano de fundo (background) com 32 colunas x 24 linhas, assim como no modo texto, em cada posição era colocado um tile (caractere) de até duas cores, formando assim o cenário.

Em cima do plano de fundo eram desenhados os sprites de 8x8 ou 16x16 que eram monocromáticos. Assim muitos personagens eram compostos de vários sprites para se obter personagens coloridos.

O por quê desta diferença é que a VDP não faz verificação de colisão coms os tiles do background. Ao passo que para os sprites a VDP pode fazer o check de colisão. Então como restringir um sprite em relação ao background, isso pode ser limitado por um mapa de coordenadas mas não há verificação "gráfica" de sprites verus tiles na VDP.

Sabemos também que a limitação da VDP é de 5 sprites por linha. Então como havia jogos com muitos sprites. Para isso era usado uma técnica que consistia em desenhar até 5 sprites por linha em uma interação do loop básico e alternar os sprites que aparecia na tela nas prximas passagens do loop. como o olho humano não percebe o truque, temos a sensação de fluide s gráfica.´

Já quanto a divisão da memória da VDP para os modos 1 e 2 temos:
  • background map: 768 bytes (32 colunas * 24 linhas) onde cada posição aponta para um tile (caracter) na tabela de padrões (tile set)
  • tabela de padrões (tile set): 2048 bytes no screen 1 e 6144 bytes no screen 2. Lembre-se que no screen 1 cada conjunto de 8 tiles no tile set, pode ter no máximo duas cores (exemplo: os 8 primeiros tiles, no tile set, usam verde claro e verde escuro os próximo 8 amarelo e vermelho, os próximos 8 azul e branco e assim por diante). Ao passo que no screen 2 cada tile pode usar duas cores sem a amarração do grupo de 8 tiles no tile set e, por esse motivo, o screen 2 consome mais memória da VDP do que o screen1.
  • Tabela de atributos de sprites 128 bytes (32 sprites * 4 bytes) onde temos em cada bytes os parâmetros, X, Y, Cor , padrão do sprite na tabela de sprites

Bom, por hoje é só folks,
O Editor

Nenhum comentário:

Postar um comentário