Переопределяемые клавиши

Материал из Клуб любителей рогаликов
Перейти к: навигация, поиск

Ваш друг является твердолобым rogue-игроком, клавиатурное распределение VI является его второй натурой. Вы только что закончили вашу roguelike игру, только она не поддерживает переопределение клавиш, поскольку Вы терпеть это не можете! Если Вы не хотите отчуждать некоторых игроков, Вы должны сделать их счастливыми. Вы нуждаетесь в переопределении клавиш. Это требует двухъярусного представления клавиш. Внутреннее (в вашей игре) и внешнее (ncurses, DOS, и т.д) представление.

В моей roguelike, я сделал такое перечисление.

enum InternalKeyBindings
{
  ik_NullKey=0,

  ik_KeyDown,
  ik_KeyLeft,
  ik_KeyRight,
  ik_KeyUp,

  ik_MAX_KEYS
};

Внешние величины клавиш затем отображаются на внутренние.

#define _ALIAS_COUNT 2
unsigned long lngKeyBinding[ik_MAX_KEYS][_ALIAS_COUNT];

_ALIAS_COUNT в определении массива показывает, что мы можем хранить до двух различных ключей во внутреннем представлении, например, Открыть Дверь и Ударить Дверь ('o' и 'b'), могут быть псевдонимами для одного ключа. Для того, чтобы это работало должным образом мы должны перевести наши нажатые клавиши из внешнего представления к внутреннему.

Приблизительно как с NCurses:

unsigned long ncurses_GetKey()
{
  return getch();
}

unsigned long TranslateKey()
{
  unsigned long lngKey;
  unsigned long lngReturnKey;
  unsigned long lngLoopCount;
  unsigned long lngAliasCount;

  lngKey=ncurses_GetKey();
  lngReturnKey=ik_NullKey;

  for(lngLoopCount=1; lngLoopCount&ltik_MAX_KEYS; lngLoopCount++)
  {
    for(lngAliasCount=1; lngAliasCount<_ALIAS_COUNT; lngAliasCount++)
    {
      if(lngKeyBinding[lngLoopCount][lngAliasCount]=lngKey)
      {
        lngReturnKey=lngLoopCount;
        /* break out of the loop faster/nicer */
        lngAliasCount=_ALIAS_COUNT;
        lngLoopCount=ik_MAX_KEYS;
      }
    }
  }

  return lngReturnKey;
}

Теперь мы имеем работающую трансляцию, и мы можем назначить свои любимые и нелюбимые клавиши!

void BindKeys(void)
{
  /* присоединить только символьные клавиши */
  lngKeyBidning[ik_KeyUp][0]='i';
  lngKeyBinding[ik_KeyUp][1]=0;
  lngKeyBidning[ik_KeyDown][0]='k';
  lngKeyBinding[ik_KeyDown][1]=0;
  lngKeyBidning[ik_KeyLeft][0]='j';
  lngKeyBinding[ik_KeyLeft][1]=0;
  lngKeyBidning[ik_KeyRight][0]='l';
  lngKeyBinding[ik_KeyRight][1]=0;

  /* KEY_* - NCurses константы */
  /* присоединить только клавиши управления курсором и числовве */
  lngKeyBidning[ik_KeyUp][0]=KEY_UP;
  lngKeyBinding[ik_KeyUp][1]='8';
  lngKeyBidning[ik_KeyDown][0]=KEY_DOWN;
  lngKeyBinding[ik_KeyDown][1]='2';
  lngKeyBidning[ik_KeyLeft][0]=KEY_LEFT;
  lngKeyBinding[ik_KeyLeft][1]='4';
  lngKeyBidning[ik_KeyRight][0]=KEY_RIGHT;
  lngKeyBinding[ik_KeyRight][1]='6';

  /* присоединить оба варианта */
  lngKeyBidning[ik_KeyUp][0]='i';
  lngKeyBinding[ik_KeyUp][1]=KEY_UP;
  lngKeyBidning[ik_KeyDown][0]='k';
  lngKeyBinding[ik_KeyDown][1]=KEY_DOWN;
  lngKeyBidning[ik_KeyLeft][0]='j';
  lngKeyBinding[ik_KeyLeft][1]=KEY_LEFT;
  lngKeyBidning[ik_KeyRight][0]='l';
  lngKeyBinding[ik_KeyRight][1]=KEY_RIGHT;
}

Теперь Вы должны не забыть работать с внутренними ключами вместо внешних. if (keypress == ik_KeyDown) - вместо клавиатурного скан-кода или константы NCurses. Есть другие вещи, которые Вы можете добавить к этому, типа проверки ключа, который связан два или больше раза. На следующем шаге нужно сохранять все ваши назначения клавиш в config-файл, который ваш roguelike читает при запуске. Для моей roguelike я позволил игроку связывать NCurses константы в config файле (KEY_UP, и т.д). Добавление мета-ключей CTRL и ALT - было бы также ценным нововведением.

Вышеупомянутый код был написан из головы на работе, но должен быть в значительной степени правилен. Достаточно для начала в любом случае.



Автор: Stuart George.
Источник: Redefinable Keyboard Bindings.
Перевел: Сергей В. Ждановских [Alchemist], 05.10.2005.