Curso de Basic
Desenhando Estrelas com o Draw
Você está em: MarMSX >> Cursos >> BASIC
O programa que desenha estrelas apresentado nos capítulos 4 e 12, é flexível e bem pequeno. Entretanto, é bem mais lento para desenhar as estrelas do que através do comando LINE.
Isto se deve ao fato de que em cada iteração (volta do laço FOR) são feitas 8 contas envolvendo senos e cossenos, que levam um tempo considerável para serem realizadas através de um processador Z-80 de 3,58 MHz.
A proposta agora é utilizar o comando DRAW para desenhar a estrela, que será bem mais rápido do que o algoritmo atual.
O comando DRAW somente desenha linhas em ângulos de 45 ou 90 graus. Como a estrela de 5 pontos possui ângulos diferentes desses, teremos que utilizar o comando "m" do DRAW com deslocamentos para conseguir desenhá-la.
Por quê utilizar deslocamentos? Porque assim poderemos desenhar a estrela em qualquer lugar da tela, baseado apenas em uma coordenada de orientação. Caso fosse utilizado o "m" fixo, a estrela seria sempre desenhada no mesmo local, ou, então, teríamos que calcular sempre as coordenadas de todos os pontos.
O programa da estrela será útil para calcular as coordenadas das linhas e encontrar os deslocamentos entre cada linha traçada.
Modificando o programa para:
- Rotacionar a estrela para a ponta ficar ao norte (linha 140)
- Em vez de desenhar a estrela, imprimir as coordenadas
- Calcular e imprimir os deslocamentos entres os pontos adjacentes, formando um caminho fechado.
Temos:
10 SCREEN 0
20 X=128:Y=85:R=20:RI=10:CB=15:CP=4:GOSUB 100
50 GOTO 50
100 '
110 ' Desenha estrela
120 '
130 PI=3.14159:AN=PI*2/5
140 FOR A=PI/2 TO (2*PI-.1) + PI/2 STEP AN
150 X1= INT(X+R*COS(A)) : Y1= INT(Y-R*SIN(A))
160 X2= INT(X+RI*COS(A-AN/2)) : Y2= INT(Y-RI*SIN(A-AN/2))
170 X3= INT(X+R*COS(A)) : Y3= INT(Y-R*SIN(A))
180 X4= INT(X+RI*COS(A+AN/2)) : Y4= INT(Y-RI*SIN(A+AN/2))
190 D1 = X1-X2: D2 = Y1-Y2
200 D3 = X4-X3: D4 = Y4-Y3
210 PRINT "(";X1;",";Y1;")-(";X2;",";Y2;")"
220 PRINT "(";D1;",";D2;")"
230 PRINT "(";X3;",";Y3;")-(";X4;",";Y4;")"
240 PRINT "(";D3;","D4;")"
250 NEXT A
260 RETURN
Saída:
( 128 , 65 )-( 133 , 76 )
(-5 ,-11 )
( 128 , 65 )-( 122 , 76 )
(-6 , 11 )
( 108 , 78 )-( 122 , 76 )
(-14 , 2 )
( 108 , 78 )-( 118 , 88 )
( 10 , 10 )
( 116 , 101 )-( 118 , 88 )
(-2 , 13 )
( 116 , 101 )-( 127 , 94 )
( 11 ,-7 )
( 139 , 101 )-( 127 , 94 )
( 12 , 7 )
( 139 , 101 )-( 137 , 88 )
(-2 ,-13 )
( 147 , 78 )-( 137 , 88 )
( 10 ,-10 )
( 147 , 78 )-( 133 , 76 )
(-14 ,-2 )
A cada iteração, o algoritmo desenha uma ponta da estrela, sempre de A para B e de A para C.
A
+
/\
/ \
↙ / \ ↘
/ \
B + + C
Para formar um caminho, temos que considerar o desenho de C para A e de A para B. É isso que foi feito nas linhas 190 e 200.
O programa pode ser mais útil ainda, se escrever para a gente o código do DRAW. Vejamos como:
10 SCREEN 0
15 DEF FN CS$(N) = RIGHT$(STR$(N), LEN(STR$(N))-1)
16 DEF FN FS$(N) = CHR$(43-(N<0)*2) + FN CS$(N)
20 X=128:Y=85:R=20:RI=10:CB=15:CP=4:GOSUB 100
50 GOTO 50
100 '
110 ' Desenha estrela
120 '
130 PI=3.14159:AN=PI*2/5
140 FOR A=PI/2 TO (2*PI-.1) + PI/2 STEP AN
150 X1= INT(X+R*COS(A)) : Y1= INT(Y-R*SIN(A))
160 X2= INT(X+RI*COS(A-AN/2)) : Y2= INT(Y-RI*SIN(A-AN/2))
170 X3= INT(X+R*COS(A)) : Y3= INT(Y-R*SIN(A))
180 X4= INT(X+RI*COS(A+AN/2)) : Y4= INT(Y-RI*SIN(A+AN/2))
190 D1 = X1-X2: D2 = Y1-Y2
200 D3 = X4-X3: D4 = Y4-Y3
210 PRINT "m" + FN FS$(D1) + "," + FN FS$(D2);
220 PRINT "m" + FN FS$(D3) + "," + FN FS$(D4);
230 NEXT A
240 RETURN
Saída:
m-5,-11m-6,+11m-14,+2m+10,+10m-2,+13m+11,-7
m+12,+7m-2,-13m+10,-10m-14,-2
O programa a seguir desenha uma estrela, baseado nos comandos do DRAW calculados.
10 SCREEN 2
20 PRESET(128,95)
30 COLOR 15
40 DRAW"bu20m-6,11m-14,2m+10,10m-2,13m+11,-7
m+12,7m-2,-13m+10,-10m-14,-2m-5,-11"
50 GOTO 50
Obs:
- O usuário fornece a coordenada do centro da estrela, através do comando PRESET.
- O comando "bu20" foi introduzido, de modo que fosse deslocado o ponto atual do centro para a ponta norte da estrela.
- O deslocamento de C para A foi colocado ao final, para que se tivesse inicio am A-B e terminasse em C-A.
O programa a seguir irá fazer uma animação, onde a estrela sofre modificação na escala, dando a impressão de aproximar da tela.
10 SCREEN 5
15 SET PAGE 0,1
16 FOR F=1 TO 8
17 CLS
20 PRESET(128,95)
30 COLOR 15
35 DRAW"s"+STR$(F*2)
40 DRAW"bu20m-6,11m-14,2m+10,10m-2,13m+11,-7
m+12,7m-2,-13m+10,-10m-14,-2m-5,-11"
43 PAINT(128,95),12,15
44 COPY(0,0)-(255,211),1 TO (0,0),0
45 NEXT F
50 GOTO 50
O comando "s" do DRAW (linha 35) é responsável pela escala da estrela.
Considerações finais
Foi visto no capítulo 4 uma solução para melhorar o código para desenhar estrelas na tela do MSX. Essa melhoria trouxe um código mais limpo e mais flexível, pois ele era capaz de desenhar uma estrela de qualquer tamanho e em qualquer lugar da tela. Entretanto, esse código possui um desempenho bem inferior ao código que utiliza o comando LINE.
Resumindo, o código de LINE para subrotina proporcionou:
- Legibilidade - ✔
- Flexibilidade - ✔
- Desempenho - ✘
Ficou evidente que esse código era mais lento que o anterior. Então, seria necessário encontrar uma solução para otimizar esse processo.
O comando DRAW seria a solução para otimizar o desempenho, mas ele necessita de informações do formato genérico da estrela para atingir esse objetivo.
Como o programa da estrela que utiliza subrotinas calcula as coordenadas de uma estrela, ele serviu de subsídio para calcular o formato genérico da estrela. Esse processo de calcular a forma genérica da estrela é necessário apenas uma vez e, quando pronto, o resultado pode ser aplicado quantas vezes o necessário. A esse processo chamamos de "pré-processamento de dados".
O pré-processamento de dados não faz parte da rotina final que será executada. Dessa forma, não importa se ele é muito lento para processar, pois o que interessa para nós é o resultado por ele produzido.
Ao final, a evolução do código no sentido "LINE → subrotina de senos e cossenos → DRAW" proporcionou:
- Legibilidade - ✔
- Flexibilidade - ✔
- Desempenho - ✔