#include <wgt5.h>
#include <math.h>

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

 Same as wgt68b.c, only the robot is partially transparent.

 *** 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 */
unsigned char *transparency_table; /* a 65536 byte table,
				      allocated dynamically */

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);

 transparency_table = (unsigned char *)malloc (65536);
}



/* Frees the buffers and sprites */
void free_graphics (void)
{
 free (transparency_table);
 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_shade (people[0].x, people[0].y, sprites[people[0].anm],
		transparency_table, SHADE_TRANSLUCENT);

}




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 wcreate_transparency_table (color *pal)
{
float lightlevel1;
float lightlevel2;
float fr, fg, fb;
float fr2, fg2, fb2;
long ir, ig, ib;

long absr, absg, absb;

short col, col2;
short findcol;

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


 lightlevel1 = 0.5;     /* Percent of color 1 */
 lightlevel2 = 0.5;     /* Percent of color 2 */

 /* Lightlevel1 and lightlevel2 must total to 1 */

 /* Transparency is created by taking two colors, multiplying the
 RGB values by a percentage, and adding the RGB values together.  The
 new color will contain a little bit of each oringal color. */


 /* For each of the 256 colors, we can mix with any other color, therefore
 we need a 256x256 table. */

 wtextcolor (15);
 wtexttransparent (TEXTFGBG);
 wgtprintf (0, 0, NULL, "Making transparency table...", col2);

 for (col2 = 0; col2 < 256; col2++)
 {
  for (col = 0; col < 256; col++)
  {
   fr = (float)pal[col].r * lightlevel1;
   fg = (float)pal[col].g * lightlevel1;
   fb = (float)pal[col].b * lightlevel1;

   fr2= (float)pal[col2].r * lightlevel2;
   fg2= (float)pal[col2].g * lightlevel2;
   fb2= (float)pal[col2].b * lightlevel2;

   ir = (fr + fr2);
   ig = (fg + fg2);
   ib = (fb + fb2);

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

      coldif = sqrt(absr*absr + absg*absg + absb*absb);
      if  (coldif < lowest)
      {
	lowest = coldif;
	bestfit = findcol;
      }
    }
   transparency_table[col2 * 256L + col] = bestfit;
  }

  wgtprintf (0, 8, NULL, "Color %03hi", col2);
 }
}



int load_table (char *filename, block table, int size)
{
FILE *in;

 in = fopen (filename, "rb");
 if (in == NULL)
   return 0;
 fread (table, size, 1, in);
 fclose (in);
 return 1;
}


void save_table (char *filename, block table, int size)
{
FILE *out;

 out = fopen (filename, "wb");
 fwrite (table, size, 1, out);
 fclose (out);

}



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

  printf ("WGT Example #68c\n\n");
  printf ("This example adds transparency 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);

 if (!load_table ("trans.dat", transparency_table, 65536))
  {
   wcreate_transparency_table (pal);
   save_table ("trans.dat", transparency_table, 65536);
  }


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

 free_graphics ();
 wsetmode (oldmode);
}

