Alguém
se lembra desse tipo de imagem aí ao lado? Não?
Bem, então provavelmente tem menos de 20 anos.
Quem tem um pouco mais que isso e descobriu o fantástico
mundo dos computadores quando o mercado era dominado
pelos micros da era MSX ou ainda antes, na era
ZX Spectrum, então irá reconhecer
aqui uma das cenas do clássico jogo Knightlore.
Aquele
precursor do Indiana Jones que, em noites de lua cheia
(todas eram) se transformava em um lobisomem, por conta
de um feitiço que precisava ser desfeito através
de uma "caldeirada", cuja receita incluia sapato velho,
garrafas vazias, taças, bolas e mais um monte
de objetos estranhos. Eram os primórdios da criação
de jogos com qualidade gráfica excepcional. Todos
originários de uma técnica chamada, na
época, de Filmation II.
A Filmation
II fez a cabeça de muitos programadores, que
ainda estão na ativa. Ela data de 1985 e em 1987
a revista Micro Sistemas publicou uma extensa
matéria, dando inclusive alguns macetes da sua
estrutura. Muito do que foi tratado alí ainda
é usado hoje e reproduzimos na íntegra
(inclusive para os saudosistas dos tempos dourados)
a referida matéria. Ela está aqui, no
club TILT, na seção
Reprint.
Mas o que
nos interessa não são propriamente as
técnicas de impressão de figuras, que
tanto sucesso faziam naquela época, mas tratar
de um tipo de estrutura de construção
de jogos que é muito usada hoje em dia. E elas
nasceram, de certa forma, do saudoso Knightlore e da
Filmation II. Trata-se dos jogos que usam e abusam da
perspectiva isométrica para criar o seu espaço
funcional.
Neste tipo
de jogo, o observador encontra-se geralmente num ponto
ligeiramente acima da linha do horizonte, permitindo
então que os objetos sejam criados em três
dimensões. Como o ângulo de visão
é bem aberto, são raras as situações
onde o jogador não vê determinadas partes
deste universo, por estarem encobertas por outros objetos.
Muitos jogadores chamam a este estilo de "jogo
de chão inclinado".
Listar
aqui os jogos atuais que se valem desta estrutura iria
consumir todo o nosso espaço só com os
nomes. Apenas como registro, lembro que os mais famosos,
além é claro do tradicional SimCity, temos
atualmente o Warcraft, Diablo, Ages of Empire (um dos
mais recentes) etc. O que talvez você não
saiba é que esse tipo de estrutura é extremamente
simples de ser construída. O maior trabalho fica
mesmo por conta da criação gráfica
e da arte dos elementos.
O que vou
mostrar nesta matéria é um dos métodos
que pode ser usado para a montagem do mundo, definido
para um jogo qualquer. Classificamos como mundo um cenário
estruturado por completo em um dado momento (por exemplo
numa fase). A base de todo esse mecanismo é definir
uma matriz de elementos (ou objetos) que irá
determinar o que tem e o que não tem em cada
"metro quadrado" do mundo. É claro que não
precisa ser necessariamente "metro". Isso é apenas
uma referência.
Então, lápis e papel na mão, digo:
Delphi carregado, vamos montar a parte dos objetos tomando
como ponto de partida um mundo baseado numa matriz de
10 por 10 células. Cada célula pode conter
um objeto. No caso, usarei apenas cubos, que formarão
uma espécie de lego digital (ei, outra idéia
muito interessante para este tipo de construção:
um programa educativo para a criançada construir
coisas, como o pequeno arquiteto, feito com blocos de
madeira).
implementation
{$R
*.DFM}
var
Blocos:
array[0..9,0..9] of byte;
Aqui está
a matriz principal, onde definiremos a existência
ou não dos cubos (objetos). Nosso mundo é
visualizado através de uma TImage que já
possui um diagrama das células.
procedure
MontaMundo;
var
Lin,Col,PosL,PosC: integer;
begin
ApagaCursor;
HTel:= Form1.Image1.Canvas.Handle;
for Lin:= 0 to
9 do begin
for Col:= 0 to
9 do begin
if Blocos[Lin,Col]
<> 0 then begin
case Blocos[Lin,Col]
of
1: HFig:= Form1.Cubo1.Canvas.Handle;
2: HFig:= Form1.Cubo2.Canvas.Handle;
3: HFig:= Form1.Cubo3.Canvas.Handle;
4: HFig:= Form1.Cubo4.Canvas.Handle;
5: HFig:= Form1.Cubo5.Canvas.Handle;
end;
PosL:= Lin * 10 + 31 - 30 + (Col * 10);
PosC:= Col * 20 + 181 - (Lin * 20);
BitBlt(HTel,PosC,PosL,40,41,HFig,40,0,SRCAND);
BitBlt(HTel,PosC,PosL,40,41,HFig,00,0,SRCPAINT);
end;
end;
end;
Form1.Image1.Repaint
end;
A montagem
do mundo ocorre dentro de dois loopings (colunas/linhas)
onde cada byte é testado em relação
a seu conteúdo. Se o valor encontrado for zero,
então na célula correspondente não
existe nada. Se o valor estiver entre 1 e 5 (inclusive)
então naquela célula existe um cubo.
Os
cubos são definidos cada um em uma TImage
distinta, que servirá de matriz para a impressão
na TImage principal.
Cada TImage de cubo
já carrega consigo a sua respectiva máscara
de impressão (já vimos em diversas matérias,
aqui na TILT, a impressão com máscaras
- BitBlt/SRCAND/SRCPAINT). Do Delphi 3 em diante existe
uma função que cria esta máscara
(Canvas.Mask), mas definindo a máscara como TImage
dispomos de um maior controle sobre a qualidade das
figuras e mantemos nosso sistema compatível com
os outros Delphis (1 e 2).
Os cálculos de PosL e PosC são
óbvios (estamos tomando como base as indicações
na figura acima). Já sei, "+ 31 - 30" é
redundante. Podia ser "+1", mas deixei a expressão
por completo para que o leitor pudesse perceber melhor
os valores envolvidos no cálculo.
Não
vou detalhar aqui a impressão do cursor, afinal
ele não é muito importante e pode ser
compreendida diretamente do fonte completo. Sua mecânica
não é muito diferente da impressão
dos blocos. Também dispensa comentários
a definição do cubo a ser impresso. Coisa
que um evento onClick na respectiva
TImage e uma var global resolve de maneira
rápida e eficiente.
O que importa
destacar nesta estrutura é que o tal mundo não
passa de uma matriz das mais simples. Num nível
simplificado como este, basta verificar cada elemento
se ele contém um objeto ou se está "vazio".
Estando "vazio" então um personagem poderia "passar"
por ele.
Este truque,
mais alguns elementos que mudam de célula (ou
de posição) de forma ordenada e um evento
OnTimer são mais do que suficientes para
montar um jogo com animação e tudo mais.
Um Knightlore moderno.
Meu propósito
aqui não era criar um jogo específico,
mas mostrar como esse tipo de sistema funciona. Usar
essas estruturas depende do que cada um deseja criar.