/*
 *    Example program for the Allegro library, by Shawn Hargreaves.
 *
 *    This program demonstrates how to use an offscreen part of the 
 *    video memory to store source graphics for the hardware accelerated 
 *    VBE/AF driver.
 */


#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#include "allegro.h"



#define MAX_IMAGES      256


/* structure to hold the current position and velocity of an image */
typedef struct IMAGE
{
   float x, y;
   float dx, dy;
} IMAGE;



/* initialises an image structure to a random position and velocity */
void init_image(IMAGE *image)
{
   image->x = (float)(random() % 704);
   image->y = (float)(random() % 568);
   image->dx = (float)((random() % 255) - 127) / 32.0;
   image->dy = (float)((random() % 255) - 127) / 32.0;
}



/* called once per frame to bounce an image around the screen */
void update_image(IMAGE *image)
{
   image->x += image->dx;
   image->y += image->dy;

   if (((image->x < 0) && (image->dx < 0)) ||
       ((image->x > 703) && (image->dx > 0)))
      image->dx *= -1;

   if (((image->y < 0) && (image->dy < 0)) ||
       ((image->y > 567) && (image->dy > 0)))
      image->dy *= -1;
}



int main(int argc, char *argv[])
{
   char buf[256];
   PALETTE pal;
   BITMAP *image;
   BITMAP *page[2];
   BITMAP *vimage;
   IMAGE images[MAX_IMAGES];
   int num_images = 4;
   int page_num = 1;
   int done = FALSE;
   int i;

   srandom(time(NULL));

   allegro_init(); 
   install_keyboard(); 
   install_timer();

   /* video mode with room for two 1024x768 pages plus a 320x200 graphic */
   if (set_gfx_mode(GFX_VBEAF, 1024, 768, 1024, 768+768+200) != 0) {
      allegro_exit();
      printf("Error setting graphics mode\n%s\n\n", allegro_error);
      printf("This program requires a hardware accelerated VBE/AF driver\n");
      printf("and a graphics card with at least 2 meg of video memory.\n\n");
      return 1;
   }

   /* read in the source graphic */
   replace_filename(buf, argv[0], "mysha.pcx", sizeof(buf));
   image = load_bitmap(buf, pal);
   if (!image) {
      allegro_exit();
      printf("Error reading %s!\n", buf);
      return 1;
   }

   set_palette(pal);

   /* initialise the images to random positions */
   for (i=0; i<MAX_IMAGES; i++)
      init_image(images+i);

   /* create two video memory bitmaps for page flipping */
   page[0] = create_video_bitmap(SCREEN_W, SCREEN_H);
   page[1] = create_video_bitmap(SCREEN_W, SCREEN_H);

   /* create a video memory bitmap to store our picture, and copy it there */
   vimage = create_video_bitmap(image->w, image->h);
   blit(image, vimage, 0, 0, 0, 0, image->w, image->h);

   while (!done) {
      /* clear the screen */
      clear(page[page_num]);

      /* draw onto it */
      for (i=0; i<num_images; i++)
	 blit(vimage, page[page_num], 0, 0, images[i].x, images[i].y, vimage->w, vimage->h);

      text_mode(-1);
      textprintf(page[page_num], font, 0, 0, 255, "Images: %d (arrow keys to change)", num_images);

      /* tell the user which functions are being done in hardware */
      if (gfx_capabilities & GFX_HW_FILL)
	 textout(page[page_num], font, "Clear: hardware accelerated", 0, 16, 255);
      else
	 textout(page[page_num], font, "Clear: software (urgh)", 0, 16, 255);

      if (gfx_capabilities & GFX_HW_VRAM_BLIT)
	 textout(page[page_num], font, "Blit: hardware accelerated", 0, 32, 255);
      else
	 textout(page[page_num], font, "Blit: software (urgh)", 0, 32, 255);

      /* page flip */
      show_video_bitmap(page[page_num]);
      page_num = 1-page_num;

      /* deal with keyboard input */
      if (keypressed()) {
	 switch (readkey()>>8) {

	    case KEY_UP:
	    case KEY_RIGHT:
	       if (num_images < MAX_IMAGES)
		  num_images++;
	       break;

	    case KEY_DOWN:
	    case KEY_LEFT:
	       if (num_images > 0)
		  num_images--;
	       break;

	    case KEY_ESC:
	       done = TRUE;
	       break;
	 }
      }

      /* bounce the images around the screen */
      for (i=0; i<num_images; i++)
	 update_image(images+i);
   }

   destroy_bitmap(image);
   destroy_bitmap(vimage);
   destroy_bitmap(page[0]);
   destroy_bitmap(page[1]);

   return 0;
}

