// GameTest1.cpp
// This game requires a small bitmap named "test.bmp" in the same folder as the
// program to run. Other than that, it should work fine for anyone. Press the
// arrow keys to move around, and Esc to quit.

#define ALLEGRO_STATICLINK
#include <allegro.h>

// here's a class for managing the player. It manages its own data as well as
// input and drawing.

class CPlayer
{
   public:
      int     xpos, ypos, speed;
      BITMAP *sprite;

      // all the constructor does is set some variables and load a bitmap

      CPlayer(): xpos(0), ypos(0), speed(5) { sprite = load_bitmap("test.bmp", NULL); }

      // unload the bitmap loaded in the constructor

     ~CPlayer() { destroy_bitmap(sprite); }

      // check for player input and act on it

      void GetControls()
      {
         if(key[KEY_UP])    { if(ypos - speed < 0)                    ypos = 0;                    else ypos -= speed; }
         if(key[KEY_DOWN])  { if(ypos + speed + sprite->h > SCREEN_H) ypos = SCREEN_H - sprite->h; else ypos += speed; }
         if(key[KEY_LEFT])  { if(xpos - speed < 0)                    xpos = 0;                    else xpos -= speed; }
         if(key[KEY_RIGHT]) { if(xpos + speed + sprite->w > SCREEN_W) xpos = SCREEN_W - sprite->w; else xpos += speed; }
      }

      // draw the player

      void Draw(BITMAP* b)
      {
         draw_sprite(b, sprite, xpos, ypos);
      }
};

// timer variable and function. The volatile keyword is needed for variables
// incremented in a timer (otherwise the program WILL crash). Likewise, for
// functions used for timing, the END_OF_FUNCTION() macro is essential too.

volatile int game_time = 0;

void Timer(void)
{
     game_time++;
}
END_OF_FUNCTION(Timer); // end Timer()

// and here's the main loop

int main()
{

   // standard Allegro initialization

   allegro_init();
   install_keyboard();
   set_color_depth(16);
   set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);

   // install the timer. We will use this to regulate game speed

   LOCK_VARIABLE(game_time);
   LOCK_FUNCTION((void*)Timer);
   install_int_ex(Timer, BPS_TO_TIMER(60));

   // create the double buffer

   BITMAP* buffer = create_bitmap(640, 480);

   // create the player

   CPlayer MyPlayer;

   // the game loop. Remeber; game_time automatically increments 60 times a second
   // becuause of the timer!

   do{

      // perform logic until game_time <= 0

      while(game_time > 0)
      {

         // *** ALL LOGIC CODE GOES IN HERE *** //

         // get and act on player input

         MyPlayer.GetControls();

         // necessary for keeping time

         game_time--;
      }

      // *** ALL DRAWING CODE GOES IN HERE *** //

      // clear the buffer; otherwise the old image remains and we leave a trail of them

      clear(buffer);

      // draw the player (and anything else in your game) to the buffer

      MyPlayer.Draw(buffer);

      // after ALL drawing is completed, draw the buffer to the screen

      blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);

      // delay until game_time automatically increments

      while(game_time <= 0){rest(1);}

   }
   while(!key[KEY_ESC]);

   // end of game loop. Game ends if you press Esc.

   // we allocated a bitmap above; now we have to destroy it

   destroy_bitmap(buffer);

   // end the program

   return 0;
}
END_OF_MAIN();
