/*
==============================================================================
		      WordUp Graphics Toolkit Version 5.0                     
			     Demonstration Program 20                         
									      
 This program uses the same sprites as last time but                        
 this time in a shoot-em-up game.                                           
									      
 *** PROJECT ***                                                             
 This program requires the file WGT5_WC.LIB to be linked.                    
									      
 *** DATA FILES ***                                                          
 Make sure that SPACE.SPR is in your executable directory.                   
							   WATCOM C++ VERSION 
==============================================================================
*/

#include <wgt5.h>

/* Large example demonstrating many functions from WGT  */

#define MAXEXPLOS 20
#define MAXALIEN 70


block workscreen, backgroundscreen;
block sprites[21];

typedef struct {
	 short x, y;
	 short dirx, diry;
	 short shootx, shooty;
	 short power;
	} spaceship;

typedef struct {
	short x, y;
	short num;
	} explosion;
explosion explos[MAXEXPLOS];

spaceship aliens[70];
short numaliens, aliensleft;

short oldmode;
short shoot[10], sx[10], sy[10];
short ship;                        /* Sprite to show */
short shipx[50], shipy[50];        /* Ship coordinates */
float incx, incy, yourx, youry;

short i, j, k;                    /* Loop control */
short scrolloffset = 1;           /* A counter for the scroll offset */
short ix = 0, iy = 0, 
      ix2 = 319, iy2 = 199;       /* coords of scrolling area */
short speed;                      /* the scrolling speed */
				  /* try changing speed and sign */
short nextlevel;                  /* Performing level change = 1 */
short leveltextx;                 /* X coordinate of next level text */
short level;

color palette[256];


void show_opening_screen (void)
/* Displays a title screen */
{
short colordraw;
int i;  
  
  for (i = 0; i < 256; i++)
    wsetrgb (i, 0, 0, 0, palette);      /* Make a black palette */
  
  wsetpalette (0, 255, palette);
  
  wnormscreen ();
  wtextcolor (1);
  wtextbackground (0);

  colordraw = 2;
  /* draw a pattern on the screen */
  for (i = 0; i < 320; i++) 
    { 
     colordraw++;
     if (colordraw > 105)
	 colordraw = 2;
    
     wsetcolor (colordraw);  
     wfline (160, 100, i, 0);  
    }
  
  for (i = 0; i < 200; i++) 
    { 
     colordraw++;
     if (colordraw > 105)
	 colordraw = 2;
    
     wsetcolor (colordraw);  
     wfline (160, 100, 319, i);
    }
  
  for (i = 319; i >= 0; i--) 
    { 
     colordraw++;
     if (colordraw > 105)
	 colordraw = 2;
    
     wsetcolor (colordraw);  
     wfline (160, 100, i, 199);
    }
  
  for (i = 199; i >= 0; i--) 
    { 
     colordraw++;
     if (colordraw > 105)
	 colordraw = 2;
    
     wsetcolor (colordraw);  
     wfline (160, 100, 0, i);  
    }

  
  /* Set up the initial palette */
  wsetrgb (0, 0, 0, 0, palette);
  for (i = 2; i < 54; i++) 
    wsetrgb (i, i, 0, 0, palette);
  for (i = 54; i < 106; i++) 
    wsetrgb (i, 105 - i, 0, 0, palette);
  wsetrgb (253, 60, 60, 60, palette);
  wsetrgb (254, 45, 45, 45, palette);
  wsetrgb (255, 30, 30, 30, palette);
  wsetrgb (1, 63, 63, 63, palette);

  wouttextxy (50, 20, NULL, "Shoot 'Em Up sprite example");
  wouttextxy (50, 28, NULL, "showing what YOU could do with");
  wouttextxy (50, 36, NULL, "the WordUp Graphics Toolkit!");
  wouttextxy (50, 44, NULL, "Use the mouse to move");
  wouttextxy (50, 52, NULL, "Left button shoots");
  wouttextxy (50, 60, NULL, "Right button quits");
  wouttextxy (50, 68, NULL, "Press any key to start");
  wsetrgb (1, 63, 63, 63, palette);
  wfade_in (0, 255, 1, palette);
  
  do 
   {
    wcolrotate (2, 106, 0, palette);    /* Rotate the red background */
    wsetpalette (2, 106, palette);
    wretrace ();
   } while (!kbhit ());
  
  while (kbhit ()) getch ();            /* Clear the keyboard buffer */
  wcls (0);
}



void initialize_aliens (short numaliens)
/* Sets the initial positions of the aliens when starting a level. */
{
short i;

  for (i = 0; i < numaliens; i++)
  {
    aliens[i].x = rand () % 200 + 30;
    aliens[i].y = rand () % 50;
    aliens[i].dirx = rand () % 8 - 4;
    aliens[i].diry = rand () % 8 - 4;
    aliens[i].power = numaliens / 3;
    aliens[i].shootx = -1;
  }
}


void make_starfield (void)
/* Gets two virtual screens and puts the star sprites on them to make
   a starfield background. */
{
short i;

  workscreen = wnewblock (0, 0, 319, 199);      /* get two virtual screens */
  backgroundscreen = wnewblock (0, 0, 319, 199);
  wsetscreen (backgroundscreen);                /* go to second one */
  wcls (0);                                     /* clear it */

  for (i = 1; i < 300; i++)
    wputblock (rand() % 320, rand() % 200, sprites[5], 0);
  /* sprite[5] is small stars */

  for (i = 1; i < 5; i++)
    wputblock (rand () % 320, rand () % 200, sprites[6], 0);
  /* sprite[6] is a large star */
  wnormscreen ();
}


void scrolldown(void)
{
/* With a bit of work, you could make this routine scroll in
   four directions and make new graphics come on as it scrolls!
   Of course, we've already gone and done that for you!
   Check out wscr_wc.lib... */

  wcopyscreen (ix, scrolloffset, ix2, iy2, backgroundscreen, 
	       ix, iy, workscreen);
  wcopyscreen (ix, iy, ix2, scrolloffset, backgroundscreen, 
	       ix, iy2 - scrolloffset, workscreen); 
  
  scrolloffset += speed;                /* Adjust the scrolling offset */
  if ((scrolloffset < iy) && (speed < 0))
    scrolloffset = iy2 + 1 - abs (scrolloffset);
  if ((scrolloffset > iy2) && (speed > 0))
    scrolloffset = abs (iy2 - scrolloffset);
}






void play (void)
{
  scrolldown ();                         
  /* Scroll the background screen by copying it to a different offset on
     workscreen.  This also erases the old frame. */
  
  wsetscreen (workscreen);
  
  if (mouse.but == 1)                   /* if you clicked the mouse */
    {                                   
     for (i = 0; i < 9; i++)
      if (shoot[i] == 0)                /* check to see if slot available */
	{
	 shoot[i] = 1;                  /* make it unavailable */
	 sx[i] = yourx + 9;             /* set coords for shot */
	 sy[i] = youry - 7;
	 break;
	}
    }
 
  for (i = 0; i < 9; i++)                         /* if shot is active */
    {
     if (shoot[i] == 1)                           /* then show the sprite */
       {
	wputblock (sx[i], sy[i], sprites[4], 0);  /* at the right coords */
	sy[i] -= 8;                               /* make it go up */
	if (sy[i] < 1)                            /* if it is at top, */
	    shoot[i] = 0;                         /* make it available again */

	/* Now check to see if it hit an alien by seeing if their
	   rectangular regions overlap. */
	for (j = 0; j < numaliens; j++)
	  if ((aliens[j].x != -255) &&
	   (sx[i] > aliens[j].x) && (sx[i] < aliens[j].x+25) &&
	   (sy[i] > aliens[j].y) && (sy[i] < aliens[j].y+20))
	     {
	      shoot[i] = 0;                       /* Turn off that missile */
	      aliens[j].power--;
	      if (aliens[j].power == 0)
		{
		 aliensleft--;
		 if (aliensleft == 0)
		   {
		    nextlevel = 1;
		    leveltextx = ix2 + 100;
		   }
		 for (k = 0; k < MAXEXPLOS; k++)  /* Add an explosion */
		    if (explos[k].num == 0)
		      {
		       explos[k].x = aliens[j].x;
		       explos[k].y = aliens[j].y;
		       explos[k].num = 8;
		       break;
		      }
	    
		 aliens[j].x = -255;
		}
	     }
       }
    }

  incx=(float)(mouse.mx - yourx) / 5.0;  /* Move your spaceship according to the */
  incy=(float)(mouse.my - youry) / 5.0;  /* position of the mouse. */
  yourx += incx;
  youry += incy;

  if (incx < 2 && incx > -2) 
    ship = 2;
  else if (incx > 5) 
    ship = 3;
  else if (incx < 5) 
    ship = 1;
  wputblock (yourx, youry, sprites[ship], 1); /* Put your ship on */


  for (i = 0; i < numaliens; i++)
    {
     if (aliens[i].x != -255) /* Alien is still alive */
       {
	aliens[i].x += aliens[i].dirx; /* Make them move */
	aliens[i].y += aliens[i].diry;

	/* Make them bounce off the walls if they go too far in one direction. */
	if (aliens[i].x <= ix) 
	  aliens[i].dirx = rand () % 4;
	else if (aliens[i].x > ix2 - 20) 
	  aliens[i].dirx = -(rand () % 4);
      
	if (aliens[i].y < 0) 
	  aliens[i].diry = rand () % 4;
	else if (aliens[i].y > 150) 
	  aliens[i].diry = -(rand () % 4);

	if ((aliens[i].shootx == -1) && (rand () % 10 == 1))  /* 1 in 10 chance of shooting */
	  {
	   aliens[i].shootx = aliens[i].x + 9;
	   aliens[i].shooty = aliens[i].y + 5;
	  }

	if (aliens[i].power > 0)
	  wputblock (aliens[i].x, aliens[i].y, sprites[7], 1);

	/* Display the alien's missile. */
	if (aliens[i].shootx != -1)
	  {
	   wputblock (aliens[i].shootx, aliens[i].shooty, sprites[8], 1);
	   aliens[i].shooty += 4;
	   if (aliens[i].shooty > 199) 
	     aliens[i].shootx = -1;
	  }
       }
    }

  /* Now draw any explosions on the screen. */
  for (i = 0; i < MAXEXPLOS; i++)
    if (explos[i].num > 0)
      {
       explos[i].num++;
       if (explos[i].num > 14)
	   explos[i].num = 0;
       else wputblock (explos[i].x, explos[i].y, sprites[explos[i].num], 1);
      }


  if (nextlevel == 1)
  {
    leveltextx -= 10;
    wgtprintf (leveltextx, 50, NULL, "LEVEL %i", level + 1);

    if (leveltextx < -100)
      {
       level++;
       if (level > MAXALIEN) 
	 level = MAXALIEN;
       numaliens = level + 5;
       aliensleft = numaliens;
       initialize_aliens (numaliens);
       nextlevel = 0;
      }
  }

  wretrace ();
  wretrace ();
  wcopyscreen (ix, iy, ix2, iy2, workscreen, ix, iy, NULL);    
  /* copy the first screen to the visual screen */
}






void main (void)
{
  if ( !vgadetected () )
    {
     printf("Error - VGA card required for any WGT program.\n");
     exit (0);
    }
  
  printf ("WGT Example #20\n\n");
  printf ("This is a small game which demonstrates the use of sprites and virtual\n");
  printf ("screens. The player cannot be hurt in this game, so it's not very exciting...\n");
  printf ("\n\nPress any key to continue.\n");
  getch ();

  oldmode = wgetmode ();
  vga256 ();

  minit ();             
  show_opening_screen ();
  
  wloadsprites (palette, "space.spr", sprites, 0, 20);   /* load sprites */
  wsetpalette (0, 255, palette);

  make_starfield ();

  wnormscreen ();                                /* go back to normal screen */
  wcls (0);                                      /* clear it */
  wbutt (0, 0, 29, 199);                         /* make some side panels */
  wbutt (252, 0, 319, 199);
  wtextbackground (0);
  wtextcolor (1);
  wtexttransparent (TEXTFG);

  yourx = 128;
  youry = 170;

  wsetscreen (workscreen);                       /* go to first screen */
  noclick ();
  msetbounds (ix, 150, ix2 - 20, 179);

  speed = -4;

  nextlevel = 0;
  level = 1;
  numaliens = level + 5;
  aliensleft = numaliens;

  initialize_aliens (numaliens);

  do {
    play ();
  } while (mouse.but != 2);                    /* until right button is pressed */
  
  mdeinit ();                   /* Deinitialize the mouse handler */
  wfreeblock (workscreen);
  wfreeblock (backgroundscreen);
  wfreesprites (sprites, 0, 20);
  wsetmode (oldmode);
}


