[A86] Re: line draw sub


[Prev][Next][Index][Thread]

[A86] Re: line draw sub




I'm assuming you need to draw a line from a point using a specified angle
and length.  To do this, you need trig.  Precalculate a table with all the
values of sine from 0 to 90 degrees multiplied by suitable value so that it
fits in a byte.  I included some C code below taken from a quick prog
written to generate such a table for a Game Boy game (pong) I wrote a while
ago.  When your program starts, you'll want to mirror the table for the
other three quandrants, and maybe also mirror the entire thing for cosine.
Assuming even distribution, you can add 64 to the table.  Ideally, you want
the table to be between 0 and 127 for values of 0 and 1 (assuming you were
dealing with radians).  Values between -1 and 0 should be between 128 and
255.  As mentioned before, you only need to store sine, not cosine, and only
the first quarter of the full table.  The thing to remember is that your
degrees are going to go from 0 to 256 instead of 0 to 360.  So 64 would be
90, and so on.  This really doesn't matter, and makes things a lot easier.
To get a cosine value from the table, add 64 to the angle before looking it
up.  Since it all fits within a byte, angle automatically wrap.

Now, on to using this with lines.  Y values correspond to cosine, and X
values correspond to sine.  Lookup the angle in the table for the line you
want.  Remember that the angle goes from 0 to 255, not 0 to 360.  Then
multiply times the length of the line.  But, won't that give very long
lines?  For even a length of 1, that is going to give you values around 128
for the length.  So, what you want to do is to use 16 bit values.  You do
everything in 16 bits, and then discard the lower half (or however many bits
you want).  This is known as fixed point math, and was used heavily even on
PC's until recently (nowaday it is more efficient to simply use floating
point, which is almost as fast as integer calculations, and can be done in
parallel to integer ops).  The thing to remember is that when you are
discarding the lower half, you need to sign extend the value, since the sign
bit is always the most significant bit (which will be different depending on
whether you are using 8 or 16 bit numbers).  I included a routine from pong
that will load a value from the sine table as a 16 bit sign extended number.

Once you have the X and Y values, you can use a normal line drawing routine
to draw between the two points.  Jimmy Mardell wrote an efficient version
based on bresenham's algorithm, that you can find on ticalc.org.  You an
probably just borrow the sine table and code from Matthew Shepcar's peaworm
game.  That game is a good, simple example of how to use trig.

for(i = 0; i < 360; i += (360.0 / 256.0))
{
  if (n % 10 == 0)
    fprintf(fp, "\n .db");
  fprintf(fp, " %3i", (unsigned char)(((sin((i / 180.0) * 3.14159265359)
    / 3.14159265359) * 180.0)* 2.2));
  if ((n % 10 != 9) && (i + (360.0 / 256.0) < 360))
    fprintf(fp, ",");
  n++;
}

; SineTable is a full 256 bytes
; inputs: a = angle (add 64 beforehand to get cosine)
; returns: de = sine (or cosine) value as sign extended 16 bit value
LoadSine16:
 ld d,0
 ld e,a
 ld hl,SineTable
 add hl,de
 ld a,(hl)
 ld e,a
 rla
 jr nc,@notneg
 dec d
 res 7,e
@notneg:
 ret

(Hmm, would be cool if Assembly Studo 8x supported local labels like my Game
Boy assembler does :)

> I need a quick way to draw lines at a angle from point to point, and I
cant
> quite figure out how to it.






References: