circulos y lineas en c=64 y msx.

Si tienes alguna duda y crees que alguien podría resolverla, ponla aquí. || If you have any doubt about programming, post it here.

Moderador: CEZ

Responder
alex
16 bits
16 bits
Mensajes: 128
Registrado: 08 Abr 2008 09:50

circulos y lineas en c=64 y msx.

Mensaje por alex »

Me gustaría saber como se hacen circulos y lineas en commodore 64 y en msx.
Avatar de Usuario
mcleod_ideafix
16 bits
16 bits
Mensajes: 85
Registrado: 05 Mar 2008 19:46
Ubicación: Sevilla
Contactar:

Re: circulos y lineas en c=64 y msx.

Mensaje por mcleod_ideafix »

Si sabes dibujar puntos en cualquier coordenada X,Y, entonces puedes dibujar líneas y círculos.
Independientemente de que la ROM de estos micros ya lleve una rutina que los haga (habría que consultar la documentación técnica en ambos casos), para las líneas se usa el algoritmo de Bresenham (creo que se escribe así). A continuación tienes una implementación en un BASIC muy sencillo, que seguro podrás portar a ensamblador o cualquier otro dialecto BASIC. Viene del ZX81:

Código: Seleccionar todo

THE LINE-DRAWING SUBROUTINE
This subroutine is called by DRAW to draw an approximation to a straight line from the point X0, Y0 
held in COORDS to the point X0+X, Y0+Y, where the increments X and Y are on the top of the calculator stack. 
The subroutine was originally intended for the ZX80 and ZX81 8K ROM, and it is described in a BASIC program 
on page 121 of the ZX81 manual. It is also illustrated here in the Circle program in the appendix.
The method is to intersperse as many horizontal or vertical steps as are needed among a basic set of diagonal steps, 
using an algorithm that spaces the horizontal or vertical steps as evenly as possible.
DRAW (A,B)-(C,D)
1000 LET U=C-A
1005 REM U SHOWS HOW MANY STEPS ALONG WE NEED TO GO
1010 LET V=D-B
1015 REM V SHOWS HOW MANY STEPS UP
1020 LET D1X=SGN U
1030 LET D1Y=SGN V
1035 REM (D1X,D1Y) IS A SINGLE STEP IN A DIAGONAL DIRECTION
1040 LET D2X=SGN U
1050 LET D2Y=0
1055 REM (D2X,D2Y) IS A SINGLE STEP LEFT OR RIGHT
1060 LET M=ABS U
1070 LET N=ABS V
1080 IF M>N THEN GOTO 1130
1090 LET D2X=0
1100 LET D2Y=SGN V
1105 REM NOW (D2X,D2Y) IS A SINGLE STEP UP OR DOWN
1110 LET M=ABS V
1120 LET N=ABS U
1130 REM M IS THE LARGER OF ABS U & ABS V, N IS THE SMALLER
1140 LET S=INT (M/2)
1145 REM WE WANT TO MOVE FROM (A,B) TO (C,D) IN M STEPS USING N UP- DOWN OR RIGHT-LEFT STEPS D2, & M-N DIAGONAL STEPS D1, DISTRIBUTED AS EVENLY AS POSSIBLE
1150 FOR I=0 TO M
1160 PLOT A,B   <--- aqui debes usar tu propia versión para pintar píxeles
1170 LET S=S+N
1180 IF S<M THEN GOTO 1230
1190 LET S=S-M
1200 LET A=A+D1X
1210 LET B=B+D1Y
1215 REM A DIAGONAL STEP
1220 GOTO 1250
1230 LET A=A+D2X
1240 LET B=B+D2Y
1245 REM AN UP-DOWN OR RIGHT-LEFT STEP
1250 NEXT I
1260 RETURN
Para dibujar círculos hay varias técnicas: unas aproximan un círculo mediante un polígono regular de muchos lados. A mi se me ocurrió este algoritmo, que dibuja círculos muy rápidamente, incluso aunque se necesitan multiplicaciones en algunos sitios (no sé si tiene un nombre o si ya estaba inventado de antes...).
Se basa, primero en la simetría que muestra una circunferencia en los 4 ejes principales (horizontal, vertical, diagonal, diagonal inversa). Así, sólo es necesario calcular los puntos de la circunferencia entre los angulos 0 y 45 grados. Para ello nos servimos de la ecuación de la circunferencia: x^2+y^2=r^2.
Para una circunferencia de radio R, que supondremos centrada en el origen, comenzamos calculando puntos de la circunferencia a partir del punto (R,0), es decir, X=R, Y=0. Como estamos subiendo desde el angulo 0 al 45, sabemos que el siguiente punto tendrá como coordenada Y'=1, pero no sabemos a ciencia cierta cuál es su coordenada X'. Lo que está claro es que sólo puede haber dos posibilidades para esa coordenada: que X'=X o que X'=X-1. Así, para estas dos posibilidades se calcula la expresión: V=X'^2+Y^2 y se escoge aquella X' que haga |V-R^2| mínima.
Para las nuevas coordenadas X',Y' se dibujan 8 puntos, aprovechándose de la simetría de la circunferencia. El bucle acaba cuando Y>X, ya que cuando eso ocurre, el ángulo ha llegado a 45 grados.

Te paso la versión en C que escribí para el Spectrum:

Código: Seleccionar todo

void circle (BYTE xc, BYTE yc, BYTE r)
{
  BYTE x,y;
  int norma,norma1,norma2;

  x=xc+r;
  y=yc;
  norma=r*r;

  plot(x,y);
  plot(2*xc-x,y);
  plot(x,2*yc-y);
  plot(2*xc-x,2*yc-y);
  plot(xc+(y-yc),yc+(x-xc));
  plot(xc-(y-yc),yc+(x-xc));
  plot(xc+(y-yc),yc-(x-xc));
  plot(xc-(y-yc),yc-(x-xc));

  while (abs(x-xc)>=abs(y-yc))
  {
    y--;
    norma1=(x-xc)*(x-xc)+(y-yc)*(y-yc);
    norma2=(x-1-xc)*(x-1-xc)+(y-yc)*(y-yc);

    if (abs(norma-norma2)<abs(norma-norma1))
      x--;

  plot(x,y);
  plot(2*xc-x,y);
  plot(x,2*yc-y);
  plot(2*xc-x,2*yc-y);
  plot(xc+(y-yc),yc+(x-xc));
  plot(xc-(y-yc),yc+(x-xc));
  plot(xc+(y-yc),yc-(x-xc));
  plot(xc-(y-yc),yc-(x-xc));
  }
}
No hay virginidad que aguante tres martinis.
Imagen
Avatar de Usuario
Guillian
32 bits
32 bits
Mensajes: 626
Registrado: 02 Ene 2005 02:40

Re: circulos y lineas en c=64 y msx.

Mensaje por Guillian »

En MSX puedes usar desde el BASIC:
CIRCLE(x,y),radio,color
y
LINE(x1,y1)-(x2,y2),color

Por ejemplo:
10 screen 2
20 circle(128,106),50,15
30 line(0,0)-(255,211),8
40 A$=input$(1)
alex
16 bits
16 bits
Mensajes: 128
Registrado: 08 Abr 2008 09:50

Re: circulos y lineas en c=64 y msx.

Mensaje por alex »

Muchas gracias por las explicaciones tan detalladas.
Un saludo.
Responder