Skip to content

Example: al_exkeys

Console
ts
/*
 *    Example program for the Allegro library, by Shawn Hargreaves.
 *
 *    This program demonstrates how to access the keyboard. The
 *    first part shows the basic use of readkey(). The second part
 *    shows how to extract the ASCII value. Next come the scan codes.
 *    The fourth test detects modifier keys like alt or shift. The
 *    fifth test requires some focus to be passed. The final step
 *    shows how to use the global key array to read simultaneous
 *    key presses.
 *    The last method to detect key presses are keyboard callbacks.
 *    This is demonstrated by by installing a keyboard callback,
 *    which marks all pressed keys by drawing to a grid.
 */

import "allegro-ts/global";
import { screen } from "allegro-ts";

const key_names = [
  "(none)",
  "KEY_A",
  "KEY_B",
  "KEY_C",
  "KEY_D",
  "KEY_E",
  "KEY_F",
  "KEY_G",
  "KEY_H",
  "KEY_I",
  "KEY_J",
  "KEY_K",
  "KEY_L",
  "KEY_M",
  "KEY_N",
  "KEY_O",
  "KEY_P",
  "KEY_Q",
  "KEY_R",
  "KEY_S",
  "KEY_T",
  "KEY_U",
  "KEY_V",
  "KEY_W",
  "KEY_X",
  "KEY_Y",
  "KEY_Z",
  "KEY_0",
  "KEY_1",
  "KEY_2",
  "KEY_3",
  "KEY_4",
  "KEY_5",
  "KEY_6",
  "KEY_7",
  "KEY_8",
  "KEY_9",
  "KEY_0_PAD",
  "KEY_1_PAD",
  "KEY_2_PAD",
  "KEY_3_PAD",
  "KEY_4_PAD",
  "KEY_5_PAD",
  "KEY_6_PAD",
  "KEY_7_PAD",
  "KEY_8_PAD",
  "KEY_9_PAD",
  "KEY_F1",
  "KEY_F2",
  "KEY_F3",
  "KEY_F4",
  "KEY_F5",
  "KEY_F6",
  "KEY_F7",
  "KEY_F8",
  "KEY_F9",
  "KEY_F10",
  "KEY_F11",
  "KEY_F12",
  "KEY_ESC",
  "KEY_TILDE",
  "KEY_MINUS",
  "KEY_EQUALS",
  "KEY_BACKSPACE",
  "KEY_TAB",
  "KEY_OPENBRACE",
  "KEY_CLOSEBRACE",
  "KEY_ENTER",
  "KEY_COLON",
  "KEY_QUOTE",
  "KEY_BACKSLASH",
  "KEY_BACKSLASH2",
  "KEY_COMMA",
  "KEY_STOP",
  "KEY_SLASH",
  "KEY_SPACE",
  "KEY_INSERT",
  "KEY_DEL",
  "KEY_HOME",
  "KEY_END",
  "KEY_PGUP",
  "KEY_PGDN",
  "KEY_LEFT",
  "KEY_RIGHT",
  "KEY_UP",
  "KEY_DOWN",
  "KEY_SLASH_PAD",
  "KEY_ASTERISK",
  "KEY_MINUS_PAD",
  "KEY_PLUS_PAD",
  "KEY_DEL_PAD",
  "KEY_ENTER_PAD",
  "KEY_PRTSCR",
  "KEY_PAUSE",
  "KEY_ABNT_C1",
  "KEY_YEN",
  "KEY_KANA",
  "KEY_CONVERT",
  "KEY_NOCONVERT",
  "KEY_AT",
  "KEY_CIRCUMFLEX",
  "KEY_COLON2",
  "KEY_KANJI",
  "KEY_EQUALS_PAD",
  "KEY_BACKQUOTE",
  "KEY_SEMICOLON",
  "KEY_COMMAND",
  "KEY_UNKNOWN1",
  "KEY_UNKNOWN2",
  "KEY_UNKNOWN3",
  "KEY_UNKNOWN4",
  "KEY_UNKNOWN5",
  "KEY_UNKNOWN6",
  "KEY_UNKNOWN7",
  "KEY_UNKNOWN8",
  "KEY_LSHIFT",
  "KEY_RSHIFT",
  "KEY_LCONTROL",
  "KEY_RCONTROL",
  "KEY_ALT",
  "KEY_ALTGR",
  "KEY_LWIN",
  "KEY_RWIN",
  "KEY_MENU",
  "KEY_SCRLOCK",
  "KEY_NUMLOCK",
  "KEY_CAPSLOCK",
  "KEY_MAX",
];

/* Keyboard callback. We are very evil and draw to the screen from within
 * the callback. Don't do this in your own programs ;)
 */
function keypress_handler(scancode: number) {
  const str = "";
  const i = scancode & 0x7f;
  const x = SCREEN_W.value - 100 * 3 + (i % 3) * 100;
  const y = SCREEN_H.value / 2 + (i / 3 - 21) * 10;
  const color = scancode & 0x80 ? makecol(255, 255, 0) : makecol(128, 0, 0);
  rectfill(screen.value, x, y, x + 95, y + 8, color);
  textprintf_ex(screen.value, font, x + 1, y + 1, makecol(0, 0, 0), -1, "%s", str);
}
END_OF_FUNCTION(keypress_handler);

/* helper function for making more room on the screen */
function scroll() {
  blit(screen.value, screen.value, 0, 32, 0, 24, SCREEN_W.value / 2, SCREEN_H.value - 32);
  rectfill(screen.value, 0, SCREEN_H.value - 16, SCREEN_W.value / 2, SCREEN_H.value - 1, makecol(255, 255, 255));
}

async function main() {
  let buf = "";
  let k = 0;

  if (allegro_init() !== 0) return 1;
  install_keyboard();
  install_timer();

  if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) !== 0) {
    if (set_gfx_mode(GFX_SAFE, 640, 480, 0, 0) !== 0) {
      set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
      allegro_message("Unable to set any graphic mode\n%s\n", allegro_error);
      return 1;
    }
  }

  set_palette(desktop_palette);

  clear_to_color(screen.value, makecol(255, 255, 255));

  /* Draw the initial keys grid by simulating release of every key. */
  for (k = 0; k < KEY_MAX; k++) keypress_handler(k + 0x80);

  /* Install our keyboard callback. */
  LOCK_FUNCTION(keypress_handler);

  acquire_screen();
  textprintf_centre_ex(
    screen.value,
    font,
    SCREEN_W.value / 2,
    8,
    makecol(0, 0, 0),
    makecol(255, 255, 255),
    "Driver: %s",
    keyboard_driver.name,
  );

  /* keyboard input can be accessed with the readkey() function */
  textprintf_ex(
    screen.value,
    font,
    8,
    SCREEN_H.value - 16,
    makecol(0, 0, 0),
    makecol(255, 255, 255),
    "Press some keys (ESC to finish)",
  );
  scroll();

  do {
    release_screen();
    k = await readkey();
    acquire_screen();
    scroll();
    textprintf_ex(
      screen.value,
      font,
      8,
      SCREEN_H.value - 16,
      makecol(0, 0, 0),
      makecol(255, 255, 255),
      "readkey() returned %-6d (0x%04X)",
      k,
      k,
    );
    console.log(k >> 8);
  } while (k >> 8 !== KEY_ENTER);

  /* the ASCII code is in the low byte of the return value */
  scroll();
  scroll();
  scroll();
  textprintf_ex(
    screen.value,
    font,
    8,
    SCREEN_H.value - 16,
    makecol(0, 0, 0),
    makecol(255, 255, 255),
    "Press some more keys (ESC to finish)",
  );
  scroll();

  do {
    release_screen();
    k = await readkey();
    acquire_screen();
    scroll();
    textprintf_ex(
      screen.value,
      font,
      8,
      SCREEN_H.value - 16,
      makecol(0, 0, 0),
      makecol(255, 255, 255),
      "ASCII code is %d",
      k & 0xff,
    );
  } while (k >> 8 !== KEY_ENTER);

  /* the hardware scan code is in the high byte of the return value */
  scroll();
  scroll();
  scroll();
  textprintf_ex(
    screen.value,
    font,
    8,
    SCREEN_H.value - 16,
    makecol(0, 0, 0),
    makecol(255, 255, 255),
    "Press some more keys (ESC to finish)",
  );
  scroll();

  do {
    release_screen();
    k = await readkey();
    acquire_screen();
    scroll();
    textprintf_ex(
      screen.value,
      font,
      8,
      SCREEN_H.value - 16,
      makecol(0, 0, 0),
      makecol(255, 255, 255),
      "Scan code is %d (%s)",
      k >> 8,
      key_names[k >> 8],
    );
  } while (k >> 8 !== KEY_ENTER);

  /* key qualifiers are stored in the key_shifts variable. Note that this
   * version of the code uses ureadkey() instead of readkey(): that is
   * necessary if you want to access Unicode characters from outside
   * the normal ASCII range, for example to support Russian or Chinese.
   */
  scroll();
  scroll();
  scroll();
  textprintf_ex(
    screen.value,
    font,
    8,
    SCREEN_H.value - 16,
    makecol(0, 0, 0),
    makecol(255, 255, 255),
    "Press some more keys (ESC to finish)",
  );
  scroll();

  do {
    release_screen();
    k = await readkey();
    acquire_screen();
    buf = "";
    if (key_shifts.value & KB_SHIFT_FLAG) buf += "shift ";
    if (key_shifts.value & KB_CTRL_FLAG) buf += "ctrl ";
    if (key_shifts.value & KB_ALT_FLAG) buf += "alt ";
    if (key_shifts.value & KB_LWIN_FLAG) buf += "lwin ";
    if (key_shifts.value & KB_RWIN_FLAG) buf += "rwin ";
    if (key_shifts.value & KB_MENU_FLAG) buf += "menu ";
    if (key_shifts.value & KB_COMMAND_FLAG) buf += "command ";
    if (key_shifts.value & KB_CAPSLOCK_FLAG) buf += " caps";
    if (key_shifts.value & KB_NUMLOCK_FLAG) buf += " num";
    if (key_shifts.value & KB_SCROLOCK_FLAG) buf += " scrl";
    scroll();
    textprintf_ex(screen.value, font, 8, SCREEN_H.value - 16, makecol(0, 0, 0), makecol(255, 255, 255), buf);
  } while (k >> 8 !== KEY_ENTER);

  /* various scan codes are defined in allegro.h as KEY_* constants */
  scroll();
  scroll();
  scroll();
  textprintf_ex(screen.value, font, 8, SCREEN_H.value - 16, makecol(0, 0, 0), makecol(255, 255, 255), "Press F6");
  scroll();

  release_screen();
  k = await readkey();
  acquire_screen();

  while (k >> 8 !== KEY_F6 && k >> 8 !== KEY_ESC) {
    scroll();
    textprintf_ex(
      screen.value,
      font,
      8,
      SCREEN_H.value - 16,
      makecol(0, 0, 0),
      makecol(255, 255, 255),
      "Wrong key, stupid! I said press F6",
    );
    release_screen();
    k = await readkey();
    acquire_screen();
  }

  /* for detecting multiple simultaneous key presses, use the key[] array */
  scroll();
  scroll();
  scroll();
  textprintf_ex(
    screen.value,
    font,
    8,
    SCREEN_H.value - 16,
    makecol(0, 0, 0),
    makecol(255, 255, 255),
    "Press a combination of numbers",
  );
  scroll();
  scroll();

  release_screen();

  do {
    buf = "";
    if (key[KEY_0]) buf += "0";
    else buf += " ";
    if (key[KEY_1]) buf += "1";
    else buf += " ";
    if (key[KEY_2]) buf += "2";
    else buf += " ";
    if (key[KEY_3]) buf += "3";
    else buf += " ";
    if (key[KEY_4]) buf += "4";
    else buf += " ";
    if (key[KEY_5]) buf += "5";
    else buf += " ";
    if (key[KEY_6]) buf += "6";
    else buf += " ";
    if (key[KEY_7]) buf += "7";
    else buf += " ";
    if (key[KEY_8]) buf += "8";
    else buf += " ";
    if (key[KEY_9]) buf += "9";
    else buf += " ";
    textprintf_ex(screen.value, font, 8, SCREEN_H.value - 16, makecol(0, 0, 0), makecol(255, 255, 255), buf);
    await rest(1);
  } while (!key[KEY_ESC]);

  clear_keybuf();
  // keyboard_lowlevel_callback = null;
  return 0;
}
END_OF_MAIN();

// Start
export const run = () => {
  init_allegro_ts("canvas_id", main, {
    debug_element: "debug",
  });
};

View source on GitHub

Released under the MIT License.