/* This program draws Lissajous curves.  It is taken directly from the
 * chapter 3 exercises in a book called _Computer Graphics: The Principles
 * Behind the Art and Science_.  That book is written by Pokorny &
 * Gerald.
 *
 * Believe it or not the Amiga is actually mentioned in that book! ;^)
 */

#include <stdio.h>
#include <math.h>
#include <ezlib.h>

#define MAX 320

double sin_tab[360], cos_tab[360];

/* first we allocate two screens, set up some colors and make sure that
 * all worked.
 *
 * Then we fill in a table so we don't have keep calling the sin() function
 * when draw the actual curves.
 *
 * Finally we scroll the picture off the screen using a simple double
 * buffering technique.
 */

main()
{
 register int i;
 int j, count = 0;
 double ang, step, hold_x, hold_y;
 struct Screen *screen1, *screen2;
 struct BitMap *bm1, *bm2;
 struct RastPort *rp, *rp2;

 screen2 = makescreen(HIRES, 3);
 if (screen2 == NULL)
   exit(10L);

 setcolor(screen2, 0, BLACK); setcolor(screen2, 1, WHITE);
 setcolor(screen2, 2, BLUE);  setcolor(screen2, 5, GREEN);
 setcolor(screen2, 3, PINK);  setcolor(screen2, 4, ORANGE);
 setcolor(screen2, 6, GREY);  setcolor(screen2, 7, RED);

 screen1 = makescreen(HIRES, 3);
 if (screen1 == NULL)
   { killscreen(screen2); exit(10L); }

 setcolor(screen1, 0, BLACK); setcolor(screen1, 1, WHITE);
 setcolor(screen1, 2, BLUE);  setcolor(screen1, 5, GREEN);
 setcolor(screen1, 3, PINK);  setcolor(screen1, 4, ORANGE);
 setcolor(screen1, 6, GREY);  setcolor(screen1, 7, RED);

 rp = &screen1->RastPort;  rp2 = &screen2->RastPort;
 bm1 = &screen1->BitMap;   bm2 = &screen2->BitMap;

 /* this loop fills up a table with a sine curve	 */
 /* the magic number 0.01745 is radians per degree	 */
 for(i=0; i < 360; i++) {
   sin_tab[i] = sin(0.01745 * (double)i);
   cos_tab[i] = cos(0.01745 * (double)i);
 }

 step = (double)360 /  (double)MAX;
 Move(rp, 320, 100+90);
 for(j=90; j > 30; j -= 2) {
   ang = 0.0;
   for(i=0; i < MAX; i++) {
     hold_x =  sin_tab[ (2 * (int)ang) % 360] * (double)j * 2.0;
     hold_y =  cos_tab[ (3 * (int)ang) % 360] * (double)j;
     Draw(rp, 320+ (int)hold_x, 100+(int)hold_y);
     ang = ang + step;
   }
   SetAPen(rp, (count++ % 8));
 }

 Delay(125);

 /* now the curve has been fully drawn to the screen.
  * First we'll copy it to the second screen behind this one, then
  * we'll double buffer it off the screen
  */

 /* scroll curve smoothly off the screen using double buffering */
 for(i=140; i > 4; i-=8) {
   WaitTOF();
   BltBitMap(bm1, i,0,  bm2, i-4,0,  380,200,  0x0c0,0xff);
   ScreenToFront(screen2);
   WaitTOF();
   BltBitMap(bm2, i-4,0,  bm1, i-8,0,  380,200,  0x0c0,0xff);
   ScreenToFront(screen1);
 }

 /* reached left edge, so from here we do things slightly different
  * than above
  */
 for(i=2; i < 70 ; i++) {
   WaitTOF();
   BltBitMap(bm1, i,0,  bm2, 0,0,  380-i,200,  0x0c0,0xff);
   ScreenToFront(screen2);
   WaitTOF();
   BltBitMap(bm2, i,0,  bm1, 0,0,  380-i,200,  0x0c0,0xff);
   ScreenToFront(screen1);
 }

 /* de-allocate everything and exit.  Simple eh? ;^) */
 killscreen(screen1);
 killscreen(screen2);

 closelibs();
 exit(0L);
}

