/*
==============================================================================
		      WordUp Graphics Toolkit Version 4.5
			     Demonstration Program 69

 This program uses the scrolling library to create a parallax scrolling
 world with two layers.  The background layer is a 640x400 bitmap, composed
 of 4 320x200 images.


 Use the arrow keys to move around and ESC will exit.                                                          
									      
 *** PROJECT ***                                                             
 This program requires the files WGT45.LIB and WGTSCROL.LIB to be linked.
									      
 *** DATA FILES ***                                                          
 PARAFRON.SPR, PARASPR.SPR, PARAMAPF.WMP, SHIP1.PCX, SHIP2.PCX, SHIP3.PCX,
 SHIP4.PCX
							   WATCOM C++ VERSION 
==============================================================================
*/

#include <stdlib.h>
#include <dos.h>
#include <wgt45.h>
#include <wgtscrol.h>


#define WIND_SIZEX 18           /* Set scrolling window dimensions (in tiles) */
#define WIND_SIZEY 12

#define SPEED 8                 /* Speed of scrolling */

#define LEFT 75                 /* Keyboard codes */
#define RIGHT 77
#define UP 72
#define DOWN 80
#define ESC 1
#define KEY_S 31
#define KEY_L 38


#define BACKWIN 0               /* The NORMAL layer */
#define FRONTWIN 1              /* The PARALLAX layer */

block fronttiles[256];          /* Tiles, objects and tiles types for the */
scrollsprite frontobject[200];  /* foreground window. */
short fronttypes[256];

block sprites[50];              /* The sprite images */

color pal[256];

short movex, movey;             /* Amount to scroll the front */
short backx, backy;             /* Coordinates of the background screen */

short x, y;                     /* Current viewing coordinates */
				/* The window tries to center itself on
				   this coordinate. */

short num_ball_behind;          /* Number of yellow balls behind front layer.
				   All yellow balls with object numbers 
				   100-199 are drawn between the background 
				   and foreground layers. */
short num_ball_infront;         /* Number of yellow balls in front of every layer */

short cloud_speed[100];         /* Movement speed and direction for clouds */

short oldmode;                  /* Old video mode */

wgtmap frontmap;                /* Holds the scrolling map */

float xscale, yscale;           /* Difference between size of map and size
				   of background picture */

block backgroundpic1;            /* A 320x200 picture */
block backgroundpic2;            /* A 320x200 picture */
block backgroundpic3;            /* A 320x200 picture */
block backgroundpic4;            /* A 320x200 picture */

void find_sprites (void)
/* Searches for the maximum object numbers for each of the three categories
   of wobjects. (clouds, ball behind, ball in front) */
{
 short i;

 num_ball_behind = 0;
 for (i = 100; i < 200; i++)
   if (frontobject[i].on)
      num_ball_behind = i;

 num_ball_infront = 0;
 for (i = 0; i < 100; i++)
   if (frontobject[i].on)
      num_ball_infront = i;
}




void move_balls (void)
/* Moves the balls around randomly */
{
  short i;
  short maxx, maxy;
 
  maxx = mapwidth[BACKWIN] * tilewidth[BACKWIN];
  maxy = mapheight[BACKWIN] * tileheight[BACKWIN];

  for (i = 0; i <= num_ball_infront; i++)
  {
    frontobject[i].x += (rand () % 17) - 8;    /* Randomly move the ball */
    frontobject[i].y += (rand () % 17) - 8;

    if (frontobject[i].x < 0)                   /* Check the X boundaries */
      frontobject[i].x = 0;
    else if (frontobject[i].x > maxx)
      frontobject[i].x = maxx;

    if (frontobject[i].y < 0)                   /* Check the Y boundaries */
      frontobject[i].y = 0;
    else if (frontobject[i].y > maxy)
      frontobject[i].y = maxy;
  }

  for (i = 100; i <= num_ball_behind; i++)
   /* Do the same with the balls behind the front layer. */
  {
    frontobject[i].x += (rand () % 17) - 8;
    frontobject[i].y += (rand () % 17) - 8;

    if (frontobject[i].x < 0)
      frontobject[i].x = 0;
    else if (frontobject[i].x > maxx)
      frontobject[i].x = maxx;
    if (frontobject[i].y < 0)
      frontobject[i].y = 0;
    else if (frontobject[i].y > maxy)
      frontobject[i].y = maxy;
  }
}


void main (void)
{
  float seconds, fps;
  int frames = 0;  

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

  printf ("WGT Example #69\n\n");
  printf ("This program uses the scrolling library to create a parallax scrolling\n");
  printf ("world with two layers.  The background layer is a 640x400 bitmap.\n");
  printf ("Use the arrow keys to move around and ESC will exit.\n");
  printf ("\nPress any key to begin.\n");
  getch ();

  vga256 ();

  wloadsprites (pal, "paraspr.spr", sprites, 0, 49);
  wloadsprites (pal, "parafron.spr", fronttiles, 0, 255);
  backgroundpic1 = wloadpcx ("ship1.pcx", pal);
  backgroundpic2 = wloadpcx ("ship2.pcx", pal);
  backgroundpic3 = wloadpcx ("ship3.pcx", pal);
  backgroundpic4 = wloadpcx ("ship4.pcx", pal);

  wsetpalette (0, 255, pal);

  winitscroll (BACKWIN, NORMAL, 0, WIND_SIZEX, WIND_SIZEY, fronttiles);
  /* Make a background window using the same tile sizes. 
     We won't use tiles on this layer but we still need to set up the
     window with the correct size. */

  winitscroll (FRONTWIN, PARALLAX, BACKWIN, WIND_SIZEX, WIND_SIZEY, fronttiles);
  /* Link this window to the background one */

  frontmap = wloadmap (FRONTWIN, "paramapf.wmp", fronttypes, frontobject);
  wcopymap (FRONTWIN, BACKWIN);
  /* Load the maps in for both windows */

  wshowwindow (FRONTWIN, 0, 0);
  /* Set the initial viewing coordinates. */
  x = 0; // * tilewidth[FRONTWIN];
  y = 0; // * tileheight[FRONTWIN];

  xscale = (float)(640 - 
	   windowmaxx [FRONTWIN] - 1) / (float)worldmaxx [FRONTWIN];
  yscale = (float)(400 -
	   windowmaxy [FRONTWIN] - 1) / (float)worldmaxy [FRONTWIN];

  find_sprites ();
  
  installkbd ();                 /* Install the custom keyboard handler */

  do {
    move_balls ();

    if (kbdon[LEFT])             /* Change the viewing coordinates */
    {
      x -= 8;
      if (x < 0)
	x = 0;
    }
    if (kbdon[RIGHT])
    {
      x += 8;
      if (x > worldmaxx[FRONTWIN]) 
	x = worldmaxx[FRONTWIN];
    }
    if (kbdon[UP])
    {
      y -= 8;
      if (y < 0) 
	y = 0;
    }
    if (kbdon[DOWN])
    {
      y += 8;
      if (y > worldmaxy[FRONTWIN]) 
	y = worldmaxy[FRONTWIN];
    }

    /* Move the foreground by finding the difference between the actual
       world coordinates and the desired world coordinates.  This will
       make sure the window is centered on the (x,y) coordinate. */
    movex = x - worldx[FRONTWIN]; 
    movey = y - worldy[FRONTWIN];

    
    
    backx = x * xscale;
    backy = y * yscale;

    wsetscreen (scrollblock [BACKWIN]);
    wputblock (-backx, -backy, backgroundpic1, 0);
    wputblock (-backx + 320, -backy, backgroundpic2, 0);
    wputblock (-backx, -backy + 200, backgroundpic3, 0);
    wputblock (-backx + 320, -backy + 200, backgroundpic4, 0);
    
    wshowobjects (BACKWIN, 100, num_ball_behind, sprites, frontobject);
    /* Show the balls that are behind the front layer. (They will be just in 
       front of the clouds) */
   
    wscrollwindow (FRONTWIN, movex, movey);
    /* Display the foreground layer */

    wshowobjects(FRONTWIN, 0, num_ball_infront, sprites, frontobject);
    /* Show the balls that are in front of everything else. */

    wnormscreen ();
    /* Uncomment the following line to time with the vertical retrace */
    //wretrace();
    
    wputblock (0, 0, scrollblock[BACKWIN], 0);
    /* Once the image is built, display the whole thing on the visual screen. */
    
    
    frames++;
  } while (kbdon[ESC] == 0);

  /* Now clean up everything */
  wendscroll (FRONTWIN);
  wendscroll (BACKWIN);

  uninstallkbd ();
  wfreeblock (backgroundpic1);
  wfreeblock (backgroundpic2);
  wfreeblock (backgroundpic3);
  wfreeblock (backgroundpic4);
  wfreesprites (fronttiles, 0, 255);
  wfreesprites (sprites, 0, 49);
  wfreemap (frontmap);
  wsetmode (oldmode);
}
