[AD] Updated exnew_events.c

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


While I was trying to get myself familiar with the codebase I updated the exnew_events.c file so it runs with the new api changes. I suppose this is the right place to post it.

You'll notice there is a bug on the printing of key.up. This is because the unicode character for ALLEGRO_EVENT_KEY_UP event.keyboard.unichar = null.
/*
 *    Example program for the Allegro library, by Peter Wang.
 *    Updated with to conform to new API by Ryan Dickie
 *
 *    This is a very simple program showing how to use the new event
 *    interface introduced in Allegro 4.9.0.
 *
 *    Everything is still subject to change, though the event interface is
 *    unlikely to change very much now.  The new display API is less stable.
 */
#include <allegro5/allegro5.h>
#include <allegro5/font.h>

#define WIDTH 640
#define HEIGHT 480

/* globals */
ALLEGRO_EVENT_QUEUE *event_queue;
ALLEGRO_DISPLAY     *display;
ALLEGRO_TIMER       *timer_a;
ALLEGRO_TIMER       *timer_b;
ALLEGRO_TIMER       *timer_c;
FONT                *myfont;
float          joys_x;
float          joys_y;
ALLEGRO_COLOR black;
ALLEGRO_COLOR white;


/* Print some text.
   borrowed and modified from exnew_bitmap_target.c
*/
static void print(int x, int y, char const *format, ...)
{
   va_list list;
   va_start(list, format);
   char message[1024];
   uvszprintf(message, sizeof message, format, list);
   va_end(list);

   al_set_blender(ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, &white);
   al_draw_rectangle(x, y, strlen(message)*25, 25, &black, ALLEGRO_FILLED);
   a5font_textout(myfont, message, x, y);
}

/* Display an error message and quit. */
void fatal_error(const char *msg)
{
   char buf[128];

   set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
   uszprintf(buf, sizeof(buf), "fatal_error: %s\n", msg);
   allegro_message(buf);
   exit(EXIT_FAILURE);
}



/*
 * The following functions deal with drawing some representation of the
 * keyboard, mouse, joystick and timer events on screen.
 * The interesting stuff doesn't really begin until main_loop(), below.
 */
void log_key_down(int keycode, int unichar, int modifiers)
{
   char buf[512];

   uszprintf(buf, sizeof(buf),
      "Down: %3d '%c' [%08x]", keycode, unichar, modifiers);
   print(5,0,buf);
}



void log_key_repeat(int keycode, int unichar, int modifiers)
{
   char buf[512];

   uszprintf(buf, sizeof(buf),
      "Rept: %3d '%c' [%08x]", keycode, unichar, modifiers);
   print(5,0,buf);
}



void log_key_up(int keycode, int unichar, int modifiers)
{
   char buf[512];

   uszprintf(buf, sizeof(buf),
      "Up: %3d '%c' [%08x]", keycode, unichar, modifiers);
   print(5,0,buf);
}



void draw_timer_tick(ALLEGRO_TIMER *timer, long count)
{
   int y;

   if (timer == timer_a) {
      y = 50;
   } else if (timer == timer_b) {
      y = 70;
   } else if (timer == timer_c) {
      y = 90;
   } else {
      fatal_error("draw_timer_tick");
      y = -1;
   }

   char buf[512];
   uszprintf(buf, sizeof(buf),"Timer: %ld", count);
   print(400, y, buf);
}



void draw_mouse_button(int but, bool down)
{
   const int offset[3] = {0, 70, 35};
   int x;
   int y;
   
   x = 400 + offset[but-1];
   y = 130;

   al_draw_rectangle(x,y,x+25,y+40,(down ? &white : &black), ALLEGRO_FILLED);
   al_draw_rectangle(x,y,x+25,y+40, &white, ALLEGRO_FILLED);
}



void draw_mouse_pos(int x, int y, int z)
{
   char buf[512];
   uszprintf(buf, sizeof(buf),"(%d, %d, %d) ", x, y, z);
   print(400, 180, buf);
}



void draw_joystick_axes(void)
{
   int x;
   int y;

   x = 470 + joys_x * 50;
   y = 300 + joys_y * 50;

   al_draw_rectangle(470-60, 300-60, 470+60, 300+60, &black, ALLEGRO_FILLED);
   al_draw_rectangle(470-60, 300-60, 470+60, 300+60, &white, ALLEGRO_OUTLINED);
   al_draw_rectangle(x-5,y-5,x+5,y+5,&white, ALLEGRO_FILLED); /* this makes up for lack of al_draw_circle */
}



void draw_joystick_button(int button, bool down)
{
   int x;
   int y;

   x = 400 + (button % 5) * 30;
   y = 400 + (button / 5) * 30;

   ALLEGRO_COLOR fill = (down?white:black);
   
   al_draw_rectangle(x, y, x + 25, y + 25, &fill , ALLEGRO_FILLED);
   al_draw_rectangle(x, y, x + 25, y + 25, &white, ALLEGRO_OUTLINED);
}


void draw_all(void)
{
   ALLEGRO_MSESTATE mst;
   
/*   al_clear(&black); */
   /* basically clear the screen minus the keyboard state printing */
   al_draw_rectangle(0,26,WIDTH,HEIGHT,&black, ALLEGRO_FILLED);
   

   al_get_mouse_state(&mst);
   draw_mouse_pos(mst.x, mst.y, mst.z);
   draw_mouse_button(1, al_mouse_button_down(&mst, 1));
   draw_mouse_button(2, al_mouse_button_down(&mst, 2));
   draw_mouse_button(3, al_mouse_button_down(&mst, 3));

   draw_timer_tick(timer_a, al_timer_get_count(timer_a));
   draw_timer_tick(timer_b, al_timer_get_count(timer_b));
   draw_timer_tick(timer_c, al_timer_get_count(timer_c));

   al_flip_display();
}


/* main_loop:
 *  The main loop of the program.  Here we wait for events to come in from
 *  any one of the event sources and react to each one accordingly.  While
 *  there are no events to react to the program sleeps and consumes very
 *  little CPU time.  See main() to see how the event sources and event queue
 *  are set up.
 */
void main_loop(void)
{
   ALLEGRO_EVENT event;

   while (true) {
      draw_all();
      /* Take the next event out of the event queue, and store it in `event'.
       * The third parameter is a time-out specification, allowing the function
       * to return even if no event arrives within the time period specified.
       * Zero represents infinite timeout.
       */
      al_wait_for_event(event_queue, &event, ALLEGRO_WAIT_FOREVER);

      /* Check what type of event we got and act accordingly.  ALLEGRO_EVENT is a
       * union type and interpretation of its contents is dependent on the
       * event type, which is given by the 'type' field.
       *
       * Each event also comes from an event source and has a timestamp.
       * These are accessible through the 'any.source' and 'any.timestamp'
       * fields respectively, e.g. 'event.any.timestamp'
       */
      switch (event.type) {

         /* ALLEGRO_EVENT_KEY_DOWN - a keyboard key was pressed.
          * The three keyboard event fields we use here are:
          *
          * keycode -- an integer constant representing the key, e.g.
          *             AL_KEY_ESCAPE;
          *
          * unichar -- the Unicode character being typed, if any.  This can
          *             depend on the modifier keys and previous keys that were
          *             pressed, e.g. for accents.
          *
          * modifiers -- a bitmask containing the state of Shift/Ctrl/Alt, etc.
          *             keys.
          */
         case ALLEGRO_EVENT_KEY_DOWN:
            if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) {
               return;
            }
            log_key_down(event.keyboard.keycode,
                  event.keyboard.unichar,
                  event.keyboard.modifiers);
            break;

         /* ALLEGRO_EVENT_KEY_REPEAT - a keyboard key was held down long enough to
          * 'repeat'.  This is a useful event if you are working on something
          * that requires typed input.  The repeat rate should be determined
          * by the operating environment the program is running in.
          */
         case ALLEGRO_EVENT_KEY_REPEAT:
            log_key_repeat(event.keyboard.keycode,
                  event.keyboard.unichar,
                  event.keyboard.modifiers);
            break;

         /* ALLEGRO_EVENT_KEY_UP - a keyboard key was released.
          * Note that the unichar field is unused for this event.
          */
         case ALLEGRO_EVENT_KEY_UP:
            log_key_up(event.keyboard.keycode,
                  event.keyboard.unichar,
                  event.keyboard.modifiers);
            break;

         /* ALLEGRO_EVENT_MOUSE_AXES - at least one mouse axis changed value.
          * The 'z' axis is for the scroll wheel.  We also have a fourth 'w'
          * axis for mice with two scroll wheels.
          */
         case ALLEGRO_EVENT_MOUSE_AXES:
            draw_mouse_pos(event.mouse.x, event.mouse.y, event.mouse.z);
            break;

         /* ALLEGRO_EVENT_MOUSE_BUTTON_UP - a mouse button was pressed. 
          * The axis fields are also valid for this event.
          */
         case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN:
            draw_mouse_button(event.mouse.button, true);
            break;

         /* ALLEGRO_EVENT_MOUSE_BUTTON_UP - a mouse button was released.
          * The axis fields are also valid for this event.
          */
         case ALLEGRO_EVENT_MOUSE_BUTTON_UP:
            draw_mouse_button(event.mouse.button, false);
            break;

         /* ALLEGRO_EVENT_TIMER - a timer 'ticked'.
          * The `source' field in the event structure tells us which timer
          * went off, and the `count' field tells us the timer's counter
          * value at the time that the event was generated.  It's not
          * redundant, because although you can query the timer for its
          * counter value, that value might have changed by the time you got
          * around to processing this event.
          */
         case ALLEGRO_EVENT_TIMER:
            draw_timer_tick(event.timer.source, event.timer.count);
            break;

         /* ALLEGRO_EVENT_JOYSTICK_AXIS - a joystick axis value changed.
          * For simplicity, in this example we only work with the first
          * 'stick' on the first joystick on the system.
          */
         case ALLEGRO_EVENT_JOYSTICK_AXIS:
            if (event.joystick.source == al_get_joystick(0) &&
               event.joystick.stick == 0)
            {
               switch (event.joystick.axis) {
                  case 0:
                     joys_x = event.joystick.pos;
                     break;
                  case 1:
                     joys_y = event.joystick.pos;
                     break;
               }
               draw_joystick_axes();
            }
            break;

         /* ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN - a joystick button was pressed.
          */
         case ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN:
            if (event.joystick.source == al_get_joystick(0)) {
               draw_joystick_button(event.joystick.button, true);
            }
            break;

         /* ALLEGRO_EVENT_JOYSTICK_BUTTON_UP - a joystick button was released.
          */
         case ALLEGRO_EVENT_JOYSTICK_BUTTON_UP:
            if (event.joystick.source == al_get_joystick(0)) {
               draw_joystick_button(event.joystick.button, false);
            }
            break;

         /* We received an event of some type we don't know about.
          * Just ignore it.
          */
         default:
            break;
      }
   }
}



int main(void)
{


   int num;
   int i;

   /* Initialise Allegro. */
   al_init();

   /* Open a window. This function is part of the new display API and is
    * still in flux.
    */
   display = al_create_display(WIDTH, HEIGHT);
   if (!display)
   {
      fatal_error("al_create_display");
   }

   /* Install the keyboard handler.  In the new API, the install functions
    * return 'false' on error instead of 0.
    */
   if (!al_install_keyboard()) {
      fatal_error("al_install_keyboard");
   }

   /* Install the mouse handler. */
   if (!al_install_mouse()) {
      fatal_error("al_install_mouse");
   }

   /* Show the mouse cursor.  Currently this relies on the video card or
    * operating environment being able to overlay a mouse cursor on top of
    * the screen (or Allegro window).  If that is not possible then the user
    * would be responsible for drawing the mouse cursor himself.
    */
   al_show_mouse_cursor();

   myfont = a5font_load_font("font.tga", 0);
   al_map_rgb(&black, 0, 0, 0);
   al_map_rgb(&white, 255,255,255);

   /* Install the joystick routines. */
   al_install_joystick();

   /* Create three timer objects.  Unlike in the earlier API, these
    * automatically increment a counter every n milliseconds.  They no longer
    * run user-defined callbacks.
    */
   timer_a = al_install_timer(100);
   timer_b = al_install_timer(1000);
   timer_c = al_install_timer(5000);
   if (!timer_a || !timer_b || !timer_c) {
      fatal_error("al_install_timer");
   }

   /* Create an event queue. These collect events which are generated by
    * event sources.  In this example we demonstrate four types of event
    * sources: the keyboard, the mouse, joysticks and timers.
    */
   event_queue = al_create_event_queue();
   if (!event_queue) {
      fatal_error("al_create_event_queue");
   }

   /* To tell event sources where to deliver any events that they generate, we
    * 'register' event sources with event queues.  An event source can register
    * itself with multiple event queues at the same time.  An event generated
    * by such an event source would be delivered to each of those event queues.
    * Most of the time, you wouldn't need that feature.
    *
    * al_get_keyboard() and al_get_mouse() return objects which represent the
    * keyboard and mouse respectively.  For simplicity, the API assumes there
    * is only one of each on the system.  The timer objects were created
    * earlier with al_install_timer().
    *
    * The type-casts to ALLEGRO_EVENT_SOURCE* are unfortunately required.
    */
   al_register_event_source(event_queue, (ALLEGRO_EVENT_SOURCE *)al_get_keyboard());
   al_register_event_source(event_queue, (ALLEGRO_EVENT_SOURCE *)al_get_mouse());
   al_register_event_source(event_queue, (ALLEGRO_EVENT_SOURCE *)timer_a);
   al_register_event_source(event_queue, (ALLEGRO_EVENT_SOURCE *)timer_b);
   al_register_event_source(event_queue, (ALLEGRO_EVENT_SOURCE *)timer_c);

   /* Register all the joysticks on the system with the event queue as well. */
   num = al_num_joysticks();
   for (i = 0; i < num; i++) {
      ALLEGRO_EVENT_SOURCE *joysrc = (ALLEGRO_EVENT_SOURCE *)al_get_joystick(i);
      al_register_event_source(event_queue, joysrc);
   }

   /* Timers are not automatically started when they are created.  Start them
    * now before we enter the main loop.
    */
   al_start_timer(timer_a);
   al_start_timer(timer_b);
   al_start_timer(timer_c);

   /* Run the main loop. */
   main_loop();

   /* For now, Allegro still automatically registers allegro_exit() with
    * atexit() when you install it.  Further, all subsystems (keyboard, etc.)
    * are automatically shut down when Allegro is shut down.  All event queues
    * are also automatically destroyed.  So we don't actually need any
    * explicit shutdown code here.
    */

   return 0;
} END_OF_MAIN()

/* vi: set ts=8 sts=3 sw=3 et: */


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/