/*
             >> Crazy-Wavy-Bouncy Six-Level Parallax Starfield <<

                        First DJGPP and Allegro demo
                                    by:
                   Garfield Benjamin   November 03, 1997                    */ 



/* no need to link with <stdlib.h> or <stdio.h> as allegro does this... */
#include <allegro.h>


/* define constants here... */
#define DISPLAY_WIDTH 320
#define DISPLAY_HEIGHT 200
#define STARFIELD_HEIGHT 365

#define MINSTARS 50
#define MAXSTARS 20000

#define INACTIVE 0
#define ACTIVE -1
#define FALSE 0
#define TRUE -1


int main()
{
   /* allocate a bitmap-structure for the starfieldbitmap... */
   BITMAP *starfieldbitmap;

   /* define our work-variables here... */
   int NumberOfStars, star, colreg;
   int starfieldypos, starfieldyspd, starfieldydir, starfieldspdtimer;
   int starfieldwave, starfieldbounce;
   int thekey, UserDone;

   /* define a star... and create an array of 20,000 stars... */
   struct stardef { int xpos, ypos, xspd; } ThisStar[20000];
 
 
   /* define our palette... */
   PALLETE starfieldpalette;

   /* black background... */
   starfieldpalette[0].r=0;
   starfieldpalette[0].g=0;
   starfieldpalette[0].b=0;

   /* next six colors are of increasing brightness... */
   for (colreg = 1; colreg < 7; colreg++)
   {
      starfieldpalette[colreg].r = 0;
      starfieldpalette[colreg].g = colreg;
      starfieldpalette[colreg].b = (colreg*10)+3;
   }



   /* A bit of a title... */            
   printf("\n\n              >> Crazy-Wavy-Bouncy Six-Level Parallax Starfield <<\n");
   printf("\n                      Garfield Benjamin  November 03, 1997\n");
   printf("\n\n          (In demo, press W for wave-mode, B to bounce and ESC to exit)\n");
   printf("\n\n                       *** READ THIS IMPORTANT MESSAGE ***\n");
   printf("           Do NOT blame me if this causes 'sea-sickness' or seizures!!\n");
   printf("           If you are prone to such effects, then do NOT view this demo.\n");
   printf("\n        To exit before the demo, enter 0 when asked for the number of stars.\n");


   /* allow the use to enter the number of stars... */
   printf("\n\n                How many stars would you like (50 to 20,000) ?");
   scanf("%d", &NumberOfStars);


   /* check for user aborting before he risks adverse side-effects... */
   if (NumberOfStars == 0)
   {
      printf("\n");
      for (star=1; star < 8; star++)
      { 
         printf("                              >> Aborting demo <<\n");
         delay(150);
      } 
      printf("\n                              DEMO HAS FINISHED!!\n");
      return 0; 
   }
   

   /* keep the number of stars within our previously defined limits... */
   if (NumberOfStars < MINSTARS) NumberOfStars=MINSTARS;
   if (NumberOfStars > MAXSTARS) NumberOfStars=MAXSTARS;


   /* initialize the allegro system... */
   allegro_init();

   /* create our bitmap, clear it, then define the video-display... */
   starfieldbitmap = create_bitmap(DISPLAY_WIDTH, STARFIELD_HEIGHT);
   clear(starfieldbitmap);
   set_gfx_mode(GFX_VGA, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0, 0);


   /* load the display with our starfield palette... */
   set_pallete(starfieldpalette);


   /* install the keyboard-handler... */
   install_keyboard();


   /* randomly define the stars' x&y-positions and speed (color/depth)... */
   for (star = 0; star < NumberOfStars; star++)
   {
      ThisStar[star].xpos = rand() % DISPLAY_WIDTH;
      ThisStar[star].ypos = rand() % STARFIELD_HEIGHT;
      ThisStar[star].xspd = rand() % 6 + 1;
   }


   /* initialize the starfield's "FX"... */
   starfieldypos=165; starfieldyspd=0;
   starfieldydir=1; starfieldspdtimer=0;
   starfieldbounce=INACTIVE;
   starfieldwave=INACTIVE;


   UserDone=FALSE;
   /* While No keys are being pressed execute this loop... */
   while (!UserDone) 
   {

      /* check keyboard... */
      if ( keypressed() )
      {
         /* a key was pressed, so we'll see what the user wants... */
         thekey=(readkey() >> 8);

         /* was it "b" (bounce-request)?... */
         if (thekey == KEY_B)
         {
            /* yes, so we set up the bounce-effect... */
            starfieldypos=165;
            starfieldyspd=-12;
            starfieldbounce=ACTIVE;
            starfieldwave=FALSE;
         }

         /* was it "w" (wave-request)?... */
         if (thekey == KEY_W)
         {
            /* yes, so we set up the wave-request... */
            starfieldypos=0;
            starfieldyspd=0;
            starfieldydir=1;
            starfieldspdtimer=0;
            starfieldwave=ACTIVE;
            starfieldbounce=FALSE;
         }

         /* we support one more key, so was it "Esc" (exit-request)?... */
         if (thekey == KEY_ESC) UserDone=TRUE;
      }


      /* update the entire starfield (one star at a time)... */
      for (star = 1; star < NumberOfStars; star++)
      {   
         /* move the star to the left... */
         /*   if the star has moved off the left side of the screen, we  */
         /*   reset the star back to the the right side of the screen... */
         /*     finally, we draw the star into the bitmap... */
         ThisStar[star].xpos-=ThisStar[star].xspd;
         if (ThisStar[star].xpos <= 0)  ThisStar[star].xpos = DISPLAY_WIDTH;
         _putpixel(starfieldbitmap,ThisStar[star].xpos,ThisStar[star].ypos,ThisStar[star].xspd);
      }


      /* update the starfield wave (if user selected wave-type)... */
      if (starfieldwave)
      {
         starfieldspdtimer++;
         if (starfieldspdtimer > 2)
         { 
            starfieldyspd+=starfieldydir;
            starfieldspdtimer=0;  
         }

         if (starfieldyspd > 7) 
         {
            starfieldyspd=7; starfieldydir=-1;
            starfieldspdtimer=2;
         }
         if (starfieldyspd < -7)
         {
            starfieldyspd=-7; starfieldydir=1;
            starfieldspdtimer=2;
         }
         starfieldypos+=starfieldyspd;
      }
     

      /* update the starfield bounce (if it's active)... */
      if (starfieldbounce)
      {
         starfieldyspd--; starfieldypos+=starfieldyspd;
         if (starfieldypos > 165)
         {
            starfieldypos=165 ; starfieldyspd=-1;
         }
         else
         {
            if (starfieldypos < 0)
            {
               starfieldypos=0; starfieldyspd=-(starfieldyspd * .8); 
               if (starfieldyspd < 1) starfieldbounce=INACTIVE;
            }
         }
      }
 
      /* synchronize with raster-beam... */
      vsync();

      /* load the video-display with our starfield-bitmap... */
      blit(starfieldbitmap, screen, 0, starfieldypos, 0, 0, 320, 200);

      /* stars have all been updated and the bitmap has been loaded into  */
      /* the video-display (memory) where it is currently being viewed,   */
      /* so we end this frame by clearing the bitmap so we can repeat the */
      /* whole procedure again next frame...                              */
      clear(starfieldbitmap);
    }


    /* user must have pressed a key, we're outta here... */
    return 0;
}

