Neste número: Impressão de Tela Gráfica no MSX, jogo Missão Estelar, dicas: Trava e Destrava e Caracteres Gigantes
Impressão de Telas Gráficas
Artigo Original: Pierluigi Piazzi e Milton Maldonado Jr., Digitação: Wilson Pilon
Estude agora a tabela de padrões dos micros da linha MSX e veja como tirar uma cópia da tela gráfica na impressora.
A tela gráfica dos micros da linha MSX está organizada em setores distintos para as suas diversas partes: tabela de padrões, cores, nomes e sprites. Neste artigo, estudaremos particularmente a tabela de padrões, que serve para indicar se um dado "pixel" está aceso ou apagado.
Uma aplicação interessante para isto é a possibilidade de se tirar uma cópia da tela gráfica na impressora, e é isto que faremos a partir de agora.
A VRAM (Vídeo RAM), quando em modo SCREEN 2 (alta resolução), está organizada da seguinte maneira:
- 0000H-1800H - Tabela de padrões da tela gráfica.
- 1800H-1B00H - Tabela de nomes da tela gráfica.
- 1B00H-1B80H - Tabela de atributos dos sprites.
- 2000H-3800H - Tabela de cores da tela gráfica.
- 3800H-4000H - Tabela de padrões dos sprites.
Estas áreas são assim delimitadas quando o computador é ligado, mas podem ser reposicionadas com o auxílio do comando BASE. Entretanto, não devemos alterar estas posições ao usarmos o programa fornecido neste artigo.
A tabela de padrões da tela gráfica está organizada em 32 colunas e 24 linhas. Cada linha tem sua altura correspondente a 8 bytes (veja figura abaixo), portanto esta tela ocupará na VRAM um espaço de memória correspondente a 32x24x8 = 6Kb.
O Programa
A sub-rotina de cópia (da linha 50000 a 50140 da listagem única) nada mais faz do que consultar a tabela de padrões da tela gráfica e transformá-la em códigos reconhecíveis pela impressora (que deve ser do padrão EPSON).
Quando se quer enviar um comando de controle para a impressora, costuma-se usar o comando LPRINT CHR$(27), seguido dos comandos de controle. A primeira coisa que o programa faz, então, é especificar a "altura" (em número de bits) de cada linha de texto. No nosso caso usamos 8, pois para esse valor as linhas ficam sem espaçamento, propiciando o modo gráfico. Assim:
LPRINT CHR$(27);CHR$(65);8;
O segundo comando de controle é mais complicado, pois, além de indicar que a impressora deve passar para o modo gráfico propriamente dito, indica também a quantidade de bytes que devem ser entendidos como dados gráficos. Por uma facilidade de operação, a cópia feita no papel sai deitada, logo, a largura da impressão é 192 (24x8), que corresponde à altura do vídeo na SCREEN 2. Assim, o comando de controle fica:
LPRINT CHR$(27);CHR$(75);CHR$(LSB);CHR$(MSB);
onde MSB (Most Significant Byte) e LSB (Less Significant Byte) compõem o número que indica a largura da impressão. No nosso caso, a largura é 192, então, temos LSB=192 e MSB=0.
Isso deve-se ao fato de que a largura de impressão é definida por:
LSB + 256 * MSB
Após este comando, os próximos 192 bytes enviados à impressora serão impressos como um dado gráfico - e não como um caractere - podendo-se então usar o comando LPRINT para enviar estes bytes. Quem conhece a "Lei de Murphy" sabe que, nessa altura, alguma coisa tem que dar errado. Realmente, o programa não funciona com o código 9. Isto ocorre porque, no BASIC MSX este código significa o caractere TAB, e o equipamento não o envia para a impressora. Em seu lugar, envia seis espaços, produzindo estranhos deslocamentos (observe a figura abaixo).
Uma primeira solução para este problema é fazer um teste que troque o código 9 por 17, que graficamente é quase idêntico ao primeiro. Não se trata, propriamente, de uma definitiva, mas serve para atenuar bastante essa deficiência (veja figura abaixo).
Não utilize este programa para copiar figuras em que tenha sido usado o comando PAINT, pois ele não altera a tabela de padrões da tela gráfica, mas sim a de atributos. Consequentemente, todas as áreas pintadas não saem impressas, dando assim um efeito inusitado na impressão (cheio de buracos).
10 COLOR 10,1:SCREEN 2:P=3.1415926#:C=2*P:I=P/20:FOR F=1 TO 5:READ X(F),Y(F):NEXT:DATA 0,100,35,35,100,0,35,-35,0,-100:FOR H=0 TO 1:FOR A=0 TO P STEP I:FOR F=1 TO 5:X=X(F)*COS(A):Y=Y(F):S=X:X=-X*(H<>1)-Y*(H=1):Y=-Y*(H<^gt;1)-S*(H=1):X=INT(X):Y=INT(Y):GOSUB 20:NEXT F,A,H
20 IF H=2 THEN 30 ELSE U=X*.9+128:V=Y*.9+85:IF F=1 THEN K=U:L=V:RETURN:ELSE LINE(K,L)-(U,V):K=U:L=V:RETURN
30 GOSUB 50000:END
50000 REM Sub-Rotina de Copia
50010 REM
50020 LPRINT CHR$(27);CHR$(65);CHR$(8);
50030 FOR C=0 TO 31
50040 LPRINT CHR$(27);CHR$(75);CHR$(192);CHR$(0);
50050 FOR L=23 TO 0 STEP -1
50060 FOR X=7 TO 0 STEP -1
50070 U=VPEEK((C*8+256*L)+X)
50080 IF U=9 THEN U=17
50090 LPRINT CHR$(U);
50100 NEXT X
50110 NEXT L
50120 LPRINT CHR$(10);
50130 NEXT C
50140 RETURN
Missão Estelar
Artigo Original: Luiz Alberto Castrucci Moysés e Fernando Leibel
Nós estamos no final do século XXV, o planeta Terra sofreu terrível ataque das forças imperiais e sucumbiu.
Você é o último guerreiro das estrelas e sua missão é destruir o máximo de astronaves imperiais. É uma missão sem volta, pois quando o combustível de sua nave terminar, o último guerreiro das estrelas não mais existirá.
O Programa
Levando-se em conta ser um programa de ação escrito em BASIC, a velocidade de processamento é bastante rápida.
Missão Estelar trabalha em SCREEN 1,1 e todos os efeitos visuais são conseguidos através de redefinição e troca de cores de caracteres. Para jogá-lo, use o teclado ou um dos joysticks ligados a uma das entradas do micro.
Estrutura do Programa
Para que os leitores compreendam o funcionamento do programa, faremos, a seguir, uma descrição das partes que o compõe.
- 30-60 - Inicialização de uma nova nave.
- 60 - Som intermitente, perceptível apenas quando a nave está na tela.
- 70-160 - Leitura do stick e movimentação da nave.
- 170 - Se a nave sair da tela aparece outra (rotina 280).
- 180 - Desenha a nave na tela.
- 190-200 - Determina a cor da mira.
- 210 - Verifica se é nave ou bomba.
- 220 - Verifica mudança de sprite da nave.
- 230 - Verifica se a nave vai virar bomba (rotina 290).
- 240 - Fecha o laço.
- 250 - Idem a linha 220, para a bomba (note que a bomba vem mais rápida).
- 260 - Verifica se houve colisão (rotina 300).
- 270 - Idem a linha 240.
- 280 - A nave saiu da tela, som intermitente desaparece, mira para de piscar, temos uma pausa e começa tudo de novo (goto 30).
- 290 - Parâmetros da bomba.
- 300-320 - Colisão da bomba.
- 330-350 - Fim de jogo.
- 360 - Rotina de tiro.
- 370-390 - Rotina de acerto.
- 400-420 - Rotina de interval.
- 430-440 - Preparativos iniciais.
- 450-480 - Prepara sprites (nave, bomba e mira).
- 490 - Define funções.
- 500 - Prepara as estrelas (redefine caracteres).
- 510 - Imprime as estrelas.
- 520 - Imprime os caracteres de tiro.
- 530 - Imprime a mira e faz a energia inicial igual a 1000.
- 540 - Imprime o painel da nave.
- 550 - Som de fundo.
- 560 - Começa tudo.
1 '*********************************
2 '* *
3 '* MSX - Missao Estelar *
4 '* *
5 '* por *
6 '* *
7 '* Fernando Leibel *
8 '* & *
9 '* Luiz Alberto Castrucci Moyses *
10 '* *
11 '* *
12 '* *
13 '*********************************
20 DEFINT A-Z:GOTO 430
30 K=0:E=0:X=FNW(0):Y=FNZ(0):E1=0
40 X1=FNT(0):IF X1=0 THEN 40
50 Y1=FNT(0):IF Y1=0 THEN 50
60 SOUND 3,1:SOUND 9,16:SOUND 12,8:SOUND 13,14
70 K=K+1:S=STICK(0) OR STICK(1) OR STICK(2):ON S+1 GOTO 160,80,90,100,110,120,130,140,150
80 Y=Y+4:GOTO 160
90 Y=Y+4:X=X-4:GOTO 160
100 X=X-4:GOTO 160
110 Y=Y-4:X=X-4:GOTO 160
120 Y=Y-4:GOTO 160
130 Y=Y-4:X=X+4:GOTO 160
140 X=X+4:GOTO 160
150 Y=Y+4:X=X+4
160 X=X+X1:Y=Y+Y1
170 IF X <-8 OR X> 255 OR T <-8O RY> 160 THEN 280
180 PUTSPRITE 1,(X,Y),14,E
190 IF V1>8 THEN VPOKE&amo;H1B03,0 ELSE VPOKE&amo;H1B03,8
200 V1=V1+1:IF V1=12 THEN V1=1
210 IF E1=1 THEN 250
220 IF K=42 OR K=72 OR K=84 THEN E=E+1
230 IF K>94 THEN 290
240 GOTO 70
250 IF K=15 OR K=36 THEN E=E+1
260 IF K>42 THEN 300
270 GOTO 70
280 SOUND 9,0:VPOKE &amo;H1B06,10:VPOKE &amo;H1B03,15:FOR T2=1 TO 5000:NEXT:VPOKE &amo;H1B03,8:GOTO 30
290 K=1:E=4:E1=1:GOTO 70
300 VPOKE &amo;H2004,&amo;H77:VPOKE &amo;H2003,&amo;H77:VPOKE &amo;H200C,&amo;H77:VPOKE &amo;H200D,&amo;H77:VPOKE &amo;H200E,&amo;H77:FOR J=1 TO 500:NEXT
310 VPOKE &amo;H2004,&amo;HF4:VPOKE &amo;H2003,&amo;H44:VPOKE &amo;H200C,&amo;H44:VPOKE &amo;H200D,&amo;H44:VPOKE &amo;H200E,&amo;H44
320 SOUND 6,25:SOUND 12,100:SOUND 10,16:SOUND 13,0:FOR T3=1 TO 2000:NEXT:SOUND 6,5:SOUND 10,0:C=C-100:IF C>0 THEN 280
330 LOCATE 9,10:PRINT "FIM DE JOGO";:LOCATE 8,12:PRINT "PARA RECOMECAR";:LOCATE 9,14:PRINT "TECLE ESPACO";
340 SOUND 8,0:SOUND 9,0:SOUND 10,0
349 STRIG(0) ON:ON STRIG GOSUB 351:GOTO 349
351 RUN:STRIG(0) OFF:RETURN 1
360 SPRITE ON:SOUND 10,16:SOUND 12,19:SOUND 13,0:VPOKE &amo;H2003,&amo;HB4:FOR J=1 TO 50:NEXT:VPOKE &amo;H2003,&amo;H44:SPRITE OFF:C=C-10:SOUND 10,0:SOUND 12,8:SOUND 13,144:IF T1=1 THEN T1=0:RETURN 280 ELSE RETURN
370 STRIG(0) OFF:STRIG(1) OFF:STRIG(3) OFF: SPRITE OFF:INTERVAL OFF:VPOKE &amo;H2004,&amo;HB8:VPOKE &amo;H2003,&amo;H88:VPOKE &amo;H200C,&amo;H88:VPOKE &amo;H200D,&amo;H88:VPOKE &amo;H200E,&amo;H88:SOUND 6,25:SOUND 10,16:SOUND 12,40:SOUND 13,0:FOR J=1 TO 1000:NEXT
380 T1=1:P=P+100-E1*90:LOCATE 12,23:PRINT P;
390 VPOKE &amo;H2004,&amo;HF4:VPOKE &amo;H2003,&amo;H44:VPOKE &amo;H200C,&amo;H44:VPOKE &amo;H200D,&amo;H44:VPOKE &amo;H200E,&amo;H44:INTERVAL ON:STRIG (0) ON:STRIG (1) ON:STRIG (3) ON:SOUND 6,5:RETURN
400 C=C-1:T=T+1:VPOKE &amo;H200C+R,&amo;H44:R=R+1:IF R=3 THEN R=0
410 IF C<0 THEN 330
420 VPOKE &amo;H200C+R,&amo;HA4:LOCATE 2,23:PRINT C;:LOCATE 23,23:PRINTT;:RETURN
430 SCREEN 1,1:KEY OFF:COLOR ,4,14:VPOKE &amo;H2003,&amo;H44:STRIG (0) ON:STRIG (1) ON:STRIG(3) ON:ON STRIG GOSUB 360,360,,360:ON SPRITE GOSUB 370:ON INTERVAL=60 GOSUB 400
440 WIDTH(32):R=RND(-TIME):RESTORE 460
450 FOR J=0 TO 8:S$="":FOR I=0 TO 7:READ A$:S$=S$+CHR$(VAL("&amo;H"+A$)):NEXT:SPRITE$(J)=S$:NEXT
460 DATA 0,0,0,8,0,0,0,0, 0,0,0,18,18,0,0,0, 0,0,24,3c,3c,24,0,0, 81,99,a5,ff,ff,99,81,81
470 DATA 0,0,0,10,0,0,0,0, 0,0,10,38,10,0,0,0, 0,10,38,7c,38,10,0,0, 10,38,7c,fe,7c,38,10,0
480 DATA 8,8,8,7f,8,8,8,0
490 DEFFNW(X)=INT(RND(1)*256):DEFFNZ(Y)=INT(RND(1)*160):DEFFNT(X)=INT(RND(1)*5-2)
500 FOR J=0 TO 2:RESTORE 460:FOR I=8 TO 15:READ A:VPOKE I+J*64+768,A:NEXT:NEXT
510 FOR J=0 TO 2:FOR I=1 TO 20:X=FNW(0)/8:Y=FNZ(0)/8:LOCATE X,Y:PRINT CHR$(J*8+97);:NEXT:NEXT
520 FOR I=0 TO 10:LOCATE 15-I,10+I:PRINT"]";:LOCATE 16+I,10+I:PRINT "^":NEXT
530 PUTSPRITE 0,(119,72),8,8:C=1000
540 LOCATE 0,21:PRINT STRING$(95,255);:VPOKE &amo;H201F,&amo;HEE:LOCATE 2,22:PRINT "ENERGIA PONTOS TEMPO";
550 SOUND 6,5:SOUND 8,8:SOUND 7,21
560 INTERVAL ON:GOTO 280
Dicas
Trava e Destrava
Dica Original: Eduarto Toledo Santos, Digitação: Wilson Pilon
Use:
POKE 64683,X
onde:
- 1 <= X <= 254 → trava o teclado em maiúsculas.
- X = 0 → destrava o teclado em minúsculas.
- X = 255 → destrava o teclado em maiúsculas.
Caracteres Gigantes
Dica Original: Clodoaldo Pinto Neto, Digitação: Wilson Pilon
Coloque quaisquer caracteres na linha 80 e veja-os "agigantados" na tela. Esta dica serve para telas de apresentação, evitando a construção de uma tabela de caracteres.
O formato e o tamanho dos caracteres podem ser modificados nas linhas 50 e 60 (X e Y), e o número por linha é definido em X1. Nessa versão, o número máximo por linha é de 17 caracteres (256/15 = 17,07).
10 READ N$:SCREEN 2:FOR A=1 TO LEN(N$)
20 C=&H1BBF+8 * ASC(MID$(N$,A,1))
30 Y=60:FOR C=C TO C+7:X=X1
40 B$=BIN$(256+PEEK(C)):FOR B=2 TO 9
50 IF VAL(MID$(B$,B,1)) THEN LINE (X,Y)-(X+2,Y+4),8,BF
60 X=X+2:NEXT B:Y=Y+5:NEXT C
70 X1=X1+15:NEXT A:B$=INPUT$(1)
80 DATA "Micro Sistemas 59"
WebMSX
- ms-59.dsk: Rode os programas pelo WebMSX