#include <wgt5.h>

/*
==============================================================================
		      WordUp Graphics Toolkit Version 5.0
			     Demonstration Program 68b

 Same as wgt68a.c, but with shadows.

 *** PROJECT ***
 This program requires the WGT5_WC.LIB file to be linked.

 *** DATA FILES ***
 STREET.PAL, RUN.SPR
							   WATCOM C++ VERSION
==============================================================================
*/


unsigned char shadowtable[256]; /* Shadow table */

color pal[256];         /* The palette used for every graphic image */
block sprites[200];     /* Array of images for the running robot */

block background;       /* Holds the background scrolling image */
block work;             /* Page for constructing each frame */
int oldmode;

/* A structure which holds the scrolling values for each horizontal line */
typedef struct
 {
  int x;                /* Current x value, shifted by 8 */
  int increment;        /* fixed point increment */
 } line_scroll;
line_scroll lines[80];  /* 80 scrolling lines along the ground */

/* A simple sprite structure */
typedef struct
 {
  int x;
  int y;
  int anm;              /* Sprite number */
 } sprite;
sprite people[5];


int backx = 0;          /* X value for the scrolling rocks */
int backinc;            /* X increment for scrolling rocks */




/* Loads the graphics files, and allocates buffers */
void load_graphics (void)
{
 work = wallocblock (320, 200);
 /* Allocate a work buffer */

 wloadsprites (pal, "run.spr", sprites, 0, 199);
 background = wloadpak ("street.pak");
 wsetpalette (0, 255, pal);
}



/* Frees the buffers and sprites */
void free_graphics (void)
{
 wfreesprites (sprites, 0, 199);
 wfreeblock (background);
 wfreeblock (work);
}


/* Set up the initial scrolling values */
void init_lines (void)
{
int i;
int inc;

 inc = 128;     /* slowest scrolling speed (128/256 of a pixel */
 
 backx = 0;     /* rocks x value */
 backinc = inc; /* rocks same speed as the ground */

 for (i = 0; i < 80; i++)
  {
   lines[i].x = 0;              /* clear out the x value */
   lines[i].increment = inc;    /* set the scroll speed */
   inc += 32;                   /* Make the next row move faster */
  }

}



/* Construct the background image */
void animate_lines (void)
{
block source1, source2;
block dest1, dest2;
block origsource, origdest;
int i;
int x;

 wcopyscreen (0, 0, 319, 51, background, 0, 0, work);
 /* Draw the moon stationary */
 
 
 /* Scroll the rocks */
 backx += backinc;
 if (backx >= 81920)   /* 81920 is 320 << 8 */
     backx -= 81920;
 
 x = backx >> 8;
 
 /* Copy the rocks */
 wcopyscreen (x, 52, 319, 119, background, 0, 52, work);
 if (x > 0)
   wcopyscreen (0, 52, x-1, 119, background, 320 - x, 52, work);
 

 
 origdest = abuf + 120 * 320;           /* First row to copy */
 origsource = background + 120 * 320;   /* First row to copy */
 
 for (i = 0; i < 80; i++)
  {
   /* Scroll this line */
   lines[i].x += lines[i].increment;
   if (lines[i].x >= 81920)   /* 81920 is 320 << 8, wraps scroll around */
      lines[i].x -= 81920;

   
   x = lines[i].x >> 8;
   /* Get the x coord */

   dest1 = origdest + i * 320;
   dest2 = dest1 + (319 - x);
   source1 = origsource + i * 320;
   source2 = source1 + x;
   
   /* Copy the line in two steps */
   memcpy (dest1, source2, 320 - x);
   if (x > 0)
    memcpy (dest2, source1, x + 1);
   
  }

}



/* Animates and displays the running man */
void animate_man (void)
{
 people[0].anm++;
 if (people[0].anm > 29)
   people[0].anm = 0;
 
 wputblock_shade (people[0].x, 158, sprites[people[0].anm+30],
		  shadowtable, SHADE_SHADOW);
 wputblock (people[0].x, people[0].y, sprites[people[0].anm], 1);

}




void wcreate_shadow_table (color *palette)
{
float fr, fg, fb;
long ir, ig, ib;

long absr, absg, absb;


int r,g,b;

short col;
short findcol;

unsigned long lowest;
unsigned char bestfit;
unsigned long coldif;

 for (col = 0; col < 256; col++)
  {

   fr = (float)palette[col].r * (0.5);
   fg = (float)palette[col].g * (0.5);
   fb = (float)palette[col].b * (0.5);

   ir = fr;
   ig = fg;
   ib = fb;

   lowest = 655350;
   for  (findcol = 0; findcol < 256; findcol++)
    {
      absr = abs ( (long)palette[findcol].r - ir);
      absg = abs ( (long)palette[findcol].g - ig);
      absb = abs ( (long)palette[findcol].b - ib);

      coldif = absr + absg + absb;
      if  ((coldif < lowest) && (findcol != col))
      {
	lowest = coldif;
	bestfit = findcol;
      }
    }
   shadowtable[col] = bestfit;
  }

}




void main (void)
{
  oldmode = wgetmode ();
  if (!vgadetected ())
  {
    printf ("VGA is required to run this program...");
    exit (1);
  }

  printf ("WGT Example #68b\n\n");
  printf ("This example adds shadows to the running robot.\n");
  printf ("\nPress any key to begin.\n");
  getch ();

  vga256 ();

 load_graphics ();
 
 init_lines ();

 /* Set the position of the running man */
 people[0].x = 120;
 people[0].y = 50;
 people[0].anm = 0;

 wcreate_shadow_table (pal);

 do { 
  wsetscreen (work);
  animate_lines ();
  animate_man ();   
  wnormscreen ();
  wretrace ();
  wputblock (0, 0, work, 0);
  } while (!kbhit ());

 free_graphics ();
 wsetmode (oldmode);
}

