Gerenciador de Ações
Você está em: MarMSX >> Cursos >> Jogos >> Alcatraz
A sub-rotina chamada de "aguarda movimento" é responsável por gerenciar os comandos vindos do usuário. É o loop principal quando o jogo inicia.
O código completo dessa sub-rotina é:
330 REM ♦♦♦♦♦ AGUARDA MOVIMENTO ♦♦♦♦♦
340 I$=INKEY$:IFI$=""THEN340
350 GOSUB1390
360 IF(I$>="A"ANDI$<="Z")OR(I$>="a"ANDI$<="z")THENFR$="":I=0:PSET(16,8),15:
GOTO970
370 MO=0:Q=ASC(I$)
380 IFQ=24THEN820
390 IFQ=27THEN890
400 IFQ=38THENSTOP
410 Q=STICK(0)
420 IFQ=1THENMO=1
430 IFQ=5THENMO=2
440 IFQ=3THENMO=3
450 IFQ=7THENMO=4
460 IFMO=0THEN340
470 I$=MID$(PO$(PC,PL),MO,1)
O comando INKEY$ capta uma tecla pressionada. Diferente do INPUT$(n), que só prossegue quando a tecla é pressionada, o INKEY$ capta a tecla no exato momento que a instrução é executada. Dessa forma, a linha 330 deve ficar em loop até que uma tecla seja pressionada.
Assim que uma tecla é pressionada, a variável I$ recebe o código dessa tecla. A partir desse momento, a sub-rotina irá:
- Linha 350: chamar a sub-rotina de apagar os comandos escritos em 1390.
- Linha 360: se tecla é uma letra, desviar para a sub-rotina de receber os comandos escritos em 970.
- Linha 370: passar o código ASCII da tecla pressionada para a variável Q.
- Linha 380: se o "SELECT" foi pressionado, desviar para a sub-rotina que mostra os objetos do local, em 820.
- Linha 390: se o "ESC" foi pressionado, desviar para a sub-rotina que mostra os objetos com o jogador, em 890.
- Linha 400: se o "&" foi pressionado, pára a execução do jogo.
- linhas 410-460: utiliza o comando STICK para filtrar a tecla direcional pressionada, uma vez que o comando INKEY$ aceita as diagonais. Além disso, codifica a direção escolhida.
- Obs: os valores do STICK são: 1 para norte, 2 para nordeste, 3 para leste, etc.
- Linha 470: se o personagem foi movimentado, passa para I$ qual é o objeto localizado na posição futura dele, através de leitura no mapa do labirinto "PO$".
- O programa segue para a rotina que verifica a posição futura do personagem, em 500.
Sub-rotina para apagar comandos escritos
Esta sub-rotina já foi vista no capítulo de desenho na tela. Serve para limpar a área onde o jogador escreve os comandos.
1380 REM ♦ APAGA 3 LINHAS SUPERIORES ♦
1390 LINE(0,8)-(255,23),15,BF
1400 PSET(0,8),15:RETURN
Sub-rotina para receber comandos escritos
A sub-rotina "aguarda movimento" verifica se a tecla pressionada é um caractere entre "a" e "z", e também entre "A" e "Z". Caso seja verdade, isto significa que o jogador está entrando com um comando por escrito. Então, o programa é desviado para a sub-rotina que recebe o comando escrito, na linha 970.
910 REM ♦♦♦ ENTRA COMANDO ESCRITO ♦♦♦♦
920 I$=INKEY$:IFI$=""THEN920
930 PSET(I*8+16,8),15
940 IFASC(I$)=8ANDI>0THENI=I-1:FR$=LEFT$(FR$,I):LINE(8*I+16,8)-(8*I+23,15),15,BF:
GOTO920
950 IFASC(I$)=13THEN1010
960 Q=STICK(0):IFQ<>0THENGOSUB1390:GOTO 420
970 IF I$>="a" AND I$<="z" THEN I$=CHR$(ASC(I$)-32)
980 IF(I$<"A"ORI$>"Z")ANDI$<>" "THEN920
990 PRINT#1,I$;:FR$=FR$+I$:I=I+1:IFI=30THEN1010
1000 GOTO920
1010 GOSUB1390:IFFR$=""THENGOTO340
Esta sub-rotina também possui um loop aguardando uma tecla ser digitada (linha 920). É uma nova rotina de tratamento de eventos de teclado, só que exclusiva para comandos escritos.
Como a primeira tecla já havia sido pressionada na sub-rotina anterior, ele vai direto para o trecho de código que converte letra minúscula em maiúscula e segue adiante.
O funcionamento da sub-rotina:
- O comando digitado pelo jogador é salvo na string FR$. Ela é limpa na linha 360, da sub-rotina "aguarda movimento".
- A variável I é usada aqui para contar o tamanho de FR$. Ela também é zerada na linha 360.
- Linha 920: aguarda tecla ser pressionada.
- Linha 930: posiciona o cursor para escrever na tela, de acordo com o número de caracteres de FR$.
- Linha 940: se tecla pressionada for backspace (8) e o tamanho da string FR$ for maior que zero, apaga um caractere de FR$ e na área da comandos na tela.
- Linha 960: se a tecla for uma seta direcional, apaga a área de desenho e vai direto para o tratamento de setas direcionais da sub-rotina "aguarda movimento".
- Linha 970: se a tecla for uma letra, verifica se é minúscula. Caso verdadeiro, converte para maiúscula.
- Linha 980: caso o caractere seja diferente de uma letra ou espaço, volta para 920.
- Linha 990: ao final, imprime o caractere na tela, atualiza FR$ e I. Caso o número de caractere seja igual a 30, encerra a edição de comando. Do contrário, volta para 920.
- Linha 950: se a tecla for o enter (13), fecha a edição de comando e desvia para a linha 1010.
- Linha 1010: ao final da edição, chama a sub-rotina de apagar a área de digitação e testa para ver se FR$ está vazio. Se sim, volta para a sub-rotina principal.
- Ao encerrar a edição com FR$ válida, o programa continua em uma sub-rotina de análise de comando (linha 1020), que será vista no próximo capítulo.
Sub-rotina para mostrar objetos no local
Esta rotina interpreta um código de dois caracteres colocado antes de cada substantivo, no qual é a localização do objeto no mapa do jogo. Ex:
JJCOMIDA
JJ - Código do local no mapa do objeto
COMIDA - Objeto
Sub-rotina que mostra os objetos no local.
810 REM ♦♦ MOSTRA OBJETOS NO LOCAL ♦♦♦
820 PRINT#1,"Aqui tem: ";:I$=CHR$(PC+60)+CHR$(PL+60)
830 M=0:FORN=0TONS
840 IFI$=LEFT$(SU$(N),2)THENPRINT#1,MID$(SU$(N),3);" ";:M=1
850 NEXT:IFM=0THENPRINT#1,"Nada Importante";
860 GOTO340
O funcionamento da sub-rotina:
- Linha 820: cria um código de local para a posição atual em I$.
- Linhas 830-860: varre a lista de substantivos SU$ em busca de um ou mais objetos que possuam o código igual a de I$, ou seja, os objetos do local.
- Imprime o resultado na área de comandos.
- É importante observar o uso da função MID$ para testar os dois primeiros caracteres e imprimir do terceiro caractere em diante.
- A variável "M" é utilizada como flag para testar se algo foi encontrado ali. Caso não haja objetos ali, imprime a mensagem "Nada importante.".
- Ao terminar, devolve o controle à sub-rotina "aguarda movimento".
A tabela a seguir, apresenta os códigos dos locais de cada objeto contido na lista de substantivos.
SU$(n) |
Código |
ASCII (Dec) |
Substantivo |
0 |
JJ |
74 74 |
COMIDA |
1 |
JJ |
74 74 |
TIRAS |
2 |
JJ |
74 74 |
CORDA |
3 |
JJ |
74 74 |
CHAVE |
4 |
DC |
68 67 |
LENCOL |
5 |
IG |
73 71 |
DINHEIRO |
6 |
AE |
65 69 |
LANTERNA |
7 |
E? |
69 63 |
SERRA |
8 |
D? |
68 63 |
PILHA |
9 |
EE |
69 69 |
FOSFOROS |
10 |
AG |
65 71 |
JORNAL |
11 |
CB |
67 66 |
COBERTOR |
12 |
<G |
60 71 |
AGUA |
13 |
AE |
65 69 |
REVOLVER |
14 |
<B |
60 66 |
FITA |
15 |
>@ |
62 64 |
GRAVADOR |
16 |
G@ |
71 64 |
PA |
17 |
>D |
62 68 |
OSSO |
18 |
D? |
68 63 |
BARALHO |
19 |
FA |
70 65 |
ROUPA |
20 |
GC |
71 67 |
BEBIDA |
21 |
CF |
67 70 |
ESPELHO |
22 |
CC |
67 67 |
GUARDA |
23 |
DC |
68 67 |
CAMA |
24 |
.. |
46 46 |
GRADES |
25 |
CB |
67 66 |
PRESIDIARIO |
26 |
B@ |
66 64 |
TOMADA |
27 |
.. |
46 46 |
PORTA |
28 |
?E |
63 69 |
FOGO |
29 |
IC |
73 67 |
POCO |
30 |
G> |
71 62 |
CARCEREIRO |
31 |
IE |
73 69 |
TERRA |
32 |
EG |
69 71 |
CAES |
33 |
AA |
65 65 |
ALARME |
34 |
A> |
65 62 |
LUZ |
A posição original do jogador é PC=8 e PL=7. Utilizando a equação da linha 820
I$=CHR$(60+PC)+I$(60+PL)
para a posição inicial, temos I$=CHR$(68)+CHR$(67) = DC. Observe na tabela acima, que o local cujo código é DC possui o "lençol".
A área possível do labirinto é de 60,62 a 73,71.
Sub-rotina para mostrar objetos com o jogador
Essa sub-rotina funciona em conjunto com a sub-rotina de objetos no local.
880 REM ♦♦MOSTRA OBJETOS COM JOGADOR♦♦3008
890 PRINT#1,"Voce tem: ";:I$="**":GOTO830
900 REM
Quando o jogador pega ou obtém um objeto, o código desse objeto no vetor de substantivos SU$ é modificado para "**". Por exemplo:
AELANTERNA
PEGUE LANTERNA
**LANTERNA
O papel da sub-rotina objetos com o jogador é somente fazer com que a variável I$ receba "**" em vez do código do local. Depois, continua em 830.
A seguir, serão apresentadas algumas sub-rotinas do jogo que alteram a posse dos objetos.
1. Sub-rotina que trata da ação "PEGUE".
2520 IF J>21 THEN PRINT#1,"Nao da'":RETURN
2530 Q=0:FORN=0TONS:IFLEFT$(SU$(N),1)="*"THENQ=Q+1
2540 NEXT
2550 IFQ>5THENPRINT#1,"Nao da' para pegar mais nada.":RETURN
2560 IF LEFT$(SU$(J),1)="*" THEN PRINT#1,"Voce ja' esta' carregando este objeto.":
RETURN
2570 SU$(J)="**"+FNS$(J):PRINT#1,"Ok."
A função FN S$ (mostrada no capítulo de preparação de dados) retorna o nome do substantivo, de acordo com a posição em S$, eliminando o cóidigo de local. Ex:
PRINT FNS$(0)
COMIDA
2. Quando o jogador rasga o lençol, as tiras (substantivo com índice igual a 1) vêm para a mão do jogador.
1630 PRINT#1,"Esta' bem. Ficou em tiras."
1640 X(1)=0:X(0)=0:SU$(1)="**"+FNS$(1):GOTO 1590
3. Igualmente acontece com a corda (2) quando as tiras são amarradas:
1680 PRINT#1,"As ";MID$(SU$(J),3);" transformaram-se numa ";FNS$(2);"!"
1690 SU$(2)="**"+FNS$(2):GOTO 1590
4. Quando um objeto é solto em um local, o programa substitui o código "**" pelo código do local:
1230 P$=CHR$(PC+60)+CHR$(PL+60)
...
1710 X(0)=1:SU$(J)=P$+FNS$(J):RETURN
5. Há objetos que somem do jogo, como, por exemplo, o lençol que é rasgado. Nesse caso, o código utilizado é " ".
J=4 : ' Lençol
...
1630 PRINT#1,"Esta' bem. Ficou em tiras."
1640 X(1)=0:X(0)=0:SU$(1)="**"+FNS$(1):GOTO 1590
...
1580 REM ♦♦ DESAPARECE OBJETO CITADO ♦♦
1590 SU$(J)=" "+FNS$(J):RETURN
6. Outro código utilizado é o "JJ" (74 74), que é uma posição fora dos limites do labirinto, assim como dois caracteres em branco (32 32).
2680 IF I$="C7H" THEN PRINT#1,"Ele aceitou e deixou voce passar":SU$(5)="IG"+FNS$(5):
SU$(22)="JJ"+FNS$(22):VPOKEED+32,0:PO$(PC,PL)="1040":GOTO3240
O dinheiro (5) dado ao guarda (22) é colocado na última posição do mapa ("IG" ou 73,71). Já o guarda é colocado para fora do mapa ("JJ" ou 74 74).
7. Como o programa sabe os objetos que ele pode pegar ou não ?
Simples. Os substantivos de 0 a 21 podem ser pegos. Do 22 em diante, não podem. Veja a linha 2520 da sub-rotina da ação de pegar (mostrada no item 1).
2520 IF J>21 THEN PRINT#1,"Nao da'":RETURN
Sub-rotina para verificar o que há na nova posição do jogador
A variável I$ recebe o código do objeto existente no novo local do labirinto, a partir do mapa PO$. De acordo com o objeto existente nessa posição, dispara uma ação.
490 REM ♦♦♦♦ MENSAGENS DOS LOCAIS ♦♦♦♦
500 IFI$="0"THEN690
510 IFI$="1"THEN340
520 IFI$="2"THENPRINT#1,"As grades da cela impedem sua passagem.":GOTO340
530 IFI$="3"THENPRINT#1,"O guarda esta aqui e nao deixa voce passar.":GOTO340
540 IFI$="4"THENPRINT#1,"Aqui ha uma cadeira eletrica. Voce foi eletrocutado."
550 IFI$="5"THENPRINT#1,"Ha uma porta fechada aqui.":GOTO340
560 IFI$="6"ANDX(7)=1ANDLEFT$(SU$(6),1)="*"THEN690
570 IFI$="6"THENPRINT#1,"Esta muito escuro aqui. Voce tropecou e quebrou
a perna."
580 IFI$="7"THENPRINT#1,"Voce caiu no fogo que restou. Que modo horrivel de
morrer!"
590 IFI$="8"THENPRINT#1,"Voce disparou um alarme!Os guar-das o pegaram! Voce foi
fuzilado"
600 IFI$="9"THENPRINT#1,"Voce passou por um feixe de luz que disparou outro alarme!"
610 IFI$="A"ANDX(9)=1ANDLEFT$(SU$(15),1)="*"THENPRINT#1,"Os caes dormem...":GOTO690
620 IFI$="A"THENPRINT#1,"Ha cinco caes aqui. Voce foi horrivelmente devorado!"
630 IFI$="B"THENPRINT#1,"A passagem aqui esta bloqueada por terra.":GOTO340
640 IFI$="C"THENPRINT#1,"Voce deu de cara com o carcerei-ro e ele o denunciou."
650 IFI$="D"THENPRINT#1,"Conseguimos sair do predio, mas ainda falta transpor o
patio...":GOTO690
660 GOTO1430
670 REM
Cada uma dessas ações só é disparada, se a nova posição do jogador for exatamente a mesma desses objetos no mapa. Ele pode tranquilamente ficar ao lado desses objetos.
Se o próximo objeto for um tijolo, grade, porta, terra ou guarda, o personagem não avança, retornando direto para a linha 340.
Caso não caia em nenhuma armadilha, a rotina de desenho do labirinto é chamada (linha 690) e o personagem avança.
Quando cai em uma armadilha, o fluxo segue até a linha 660, onde o programa é desviado para uma sub-rotina de "fim de jogo" para o insucesso.
Obs: a sub-rotina de "fim de jogo" possui um opção escondida: a tecla "W", que serve para continuar o jogo.