SiegeLord / DAllegro5

D binding to the Allegro5 game development library
Other
42 stars 15 forks source link

Handy stuff #39

Closed joelcnz closed 5 years ago

joelcnz commented 7 years ago

The functions and stuff below are handy so you can put in your main program loop, for example:

poll_input();
if (key[ALLEGRO_KEY_Q])
    return 0;

I found them in an Allegro demo that came with the library, and made them work in D.

import std.stdio;
import std.range;
import core.stdc.string;

const MAX_KEYBUF = 16;

int[ALLEGRO_KEY_MAX] key;
static int[MAX_KEYBUF] keybuf;
static int keybuf_len = 0;
static ALLEGRO_MUTEX* keybuf_mutex;

/**
 * Eg.
 * ---
 * scope(exit) Deinit();
 * ---
*/
void Deinit( string message = "" ) {
    shutdown_input;

    if ( ! message.empty )
        writeln( message );
}

/** initialises the input emulation */
void init_input()
{
   keybuf_len = 0;
   keybuf_mutex = al_create_mutex();
   assert(keybuf_mutex);
}

/** closes down the input emulation */
void shutdown_input()
{
    scope( success )
        writeln( "shutdown_input successfully" );
   al_destroy_mutex(keybuf_mutex);
   keybuf_mutex = null;

   g_queue = null;
}

/** helper function to add a keypress to a buffer */
static void add_key(ALLEGRO_KEYBOARD_EVENT* event)
{
   if ((event.unichar == 0) || (event.unichar > 255))
      return;

   al_lock_mutex(keybuf_mutex);

   if (keybuf_len < MAX_KEYBUF) {
      keybuf[keybuf_len] = event.unichar | ((event.keycode << 8) & 0xff00);
      keybuf_len++;
   }

   al_unlock_mutex(keybuf_mutex);
}

/** emulate poll_keyboard() and poll_joystick() combined */
void poll_input()
{
   ALLEGRO_EVENT event;

   while (al_get_next_event(g_queue, &event)) {

      switch (event.type) {

     case ALLEGRO_EVENT_KEY_DOWN:
        key[event.keyboard.keycode] = 1;
        break;

     case ALLEGRO_EVENT_KEY_UP:
        key[event.keyboard.keycode] = 0;
        break;

     case ALLEGRO_EVENT_KEY_CHAR:
        add_key(&event.keyboard);
        break;

     case ALLEGRO_EVENT_TIMER:
        /* retrace_count incremented */
        break;

     case ALLEGRO_EVENT_DISPLAY_EXPOSE:
        break;
      default:
      break;
      }
   }
}

/** blocking version of poll_input(), also wakes on retrace_count */
void poll_input_wait()
{
   al_wait_for_event(g_queue, null );
   poll_input();
}

/** emulate keypressed() */
int keypressed()
{
   poll_input();

   return keybuf_len > 0;
}

//#works differently than I was expecting
/** emulate readkey(), except this version never blocks */
int readkey()
{
   int c = 0;

   poll_input();

   al_lock_mutex(keybuf_mutex);

   if (keybuf_len > 0) {
      c = keybuf[0];
      keybuf_len--;

      memmove(keybuf.ptr, keybuf.ptr + 1, keybuf[0].sizeof * keybuf_len);
   }

   al_unlock_mutex(keybuf_mutex);

   return c;
}

/** emulate clear_keybuf() */
void clear_keybuf()
{
   al_lock_mutex(keybuf_mutex);

   keybuf_len = 0;

   al_unlock_mutex(keybuf_mutex);
}
joelcnz commented 5 years ago

I think I crashed my macOS system with this, mind. Fine on Windows.