官术网_书友最值得收藏!

Using the keyboard input

LuaSDL offers a simple way of determining what key was pressed or released on your keyboard. Events with event types SDL.SDL_KEYDOWN and SDL.SDL_KEYUP can react to one keystroke at the time. This is usually fine during a game play. However, if you want to use keyboard shortcuts in a text input field, the previous approach would not be very efficient.

This recipe will show you how to manage keyboard input in a robust way that can be used for both situations—to control a game or to write text into an input field.

Getting ready

Let's say you need your game character to run when a Shift key is pressed. There are three key problems. The common PC keyboard has left and right Shift keys. These are two different keys with two different key symbol codes. The next thing is that you use these keys with another keyboard key which may or may not be the modifier key. The last problem is putting key states together, so you'll know if the player has pressed the Shift + W keys at the same time.

There are rare cases where you need to query key status multiple times in one frame. It wouldn't be very efficient to do this every time you need a current state of key modifier. A better solution is to cache key states into a Lua table. A key symbol code will be used as a table key and the value will indicate a key status (0 means released and 1 means pressed). You can assume that the key is released if there is no such entry in the key state table. This assumption doesn't apply to all modifier keys, for example, the Num Lock key, so make sure that you initialize modifier key states on application startup. The following code will define tables to store cached information about key states, along with a special table for the conversion of modifier key codes into scan code:

local keyStates = {}
local keyModStates = {}
-- a list of key modifiers paired with their scan codes
local modKeysScanCodes = {
  [SDL.KMOD_LSHIFT]=SDL.SDLK_LSHIFT, [SDL.KMOD_RSHIFT]=SDL.SDLK_RSHIFT,
  [SDL.KMOD_LCTRL]=SDLK_LCTRL, [SDL.KMOD_RCTRL]=SDL.SDLK_RCTRLT,
  [SDL.KMOD_LALT]=SDL.SDLK_LALT, [SDL.KMOD_RALT]=SDL.SDLK_RALT,
  [SDL.KMOD_LMETA]=SDL.SDLK_LMETA, [SDL.KMOD_RMETA]=SDL.SDLK_RMETA,
  [SDL.KMOD_NUM]=SDL.SDLK_NUMLOCK,
  [SDL.KMOD_CAPS]=SDL.SDLK_CAPSLOCK,
  [SDL.KMOD_MODE]=SDL.SDLK_MODE,
}

This code should be used before event processing takes place.

How to do it…

This recipe will be separated into two parts. This first part will deal with the storing states of normal keys. The second part will manage key modifier states as this is a bit more problematic.

Normal keys

Getting the states of normal keys is pretty straightforward. You just need to detect keyboard input events to store a key state into the keyState table. This part of the recipe will use the event functions stored in a table, which is explained in the previous recipe in detail:

local events = {
  -- a keyboard key was pressed down
  [SDL.SDL_KEYDOWN] = function(raw_event)
    local event = raw_event.key
    local keySym = event.keysym.sym
    keyStates[keySym] = true
  end,
  -- a keyboard key was released
  [SDL.SDL_KEYUP] = function(raw_event)
    local event = raw_event.key
    local keySym = event.keysym.sym
       keyStates[keySym] = false
  end,
}
Modifier keys

Modifier keys need to be processed separately because LuaSDL can't detect certain key combinations within the event processing mechanism. You can try to press both left and right Ctrl keys and you'll notice that the second modifier is not detected at all!

The modifier key state can be obtained with the SDL.SDL_GetModState function in the form of a bit mask. The following table shows all the modifier key codes:

The modifier key state will be processed in a function called processModKeys:

local function processModKeys()
  local modState = SDL.SDL_GetModState()
  for keyMod, keySym in pairs(modKeysScanCodes) do
    -- apply binary and operator to obtain modifier key state
    keyModStates[keySym] = (bit.band(modState, keyMod) > 0)
  end
end

This function needs to be called in every frame so that you always get the current state of the modifier keys.

How it works…

The second part of this recipe relies on using the binary and the operator to get the modifier key state. As mentioned earlier, the modifier key states are stored in a bit mask. Therefore, to get the actual scan code, it uses the conversion table called modKeysScanCodes. Modifier key states are stored in a local modState variable, which is used in the for loop to do binary tests for all modifier keys. If a modifier key is pressed, the binary AND operator returns nonzero value. The result of this operation is stored in the keyModState table.

Note that the key modifier values such as SDL.KMOD_SHIFT, SDL.KMOD_CTRL, SDL.KMOD_ALT, and SDL.KMOD_META are not included in the modKeysScanCodes table. You can obtain states for these modifier keys by using Boolean operators as follows:

local SHIFT_state = (keyModStates[SDL.SDLK_LSHIFT] or keyModStates[SDL.SDLK_RSHIFT])

This will return true if any of the Shift keys is pressed.

From this point, if you need to query the keyboard shortcut status for Shift + W, you can use the following code:

local SHIFT_W_state =
  (keyModStates[SDL.SDLK_LSHIFT] or 
   keyModStates[SDL.SDLK_RSHIFT]) and
   keyState[SDL.SDLK_w]

See also

主站蜘蛛池模板: 太仆寺旗| 慈利县| 县级市| 克拉玛依市| 响水县| 绥阳县| 枣庄市| 禄劝| 大悟县| 班玛县| 珠海市| 松溪县| 阿拉善盟| 叶城县| 肥东县| 桓台县| 平塘县| 梓潼县| 辽阳县| 永吉县| 连江县| 黔江区| 隆德县| 蒙自县| 平远县| 万宁市| 满城县| 曲水县| 奉节县| 会同县| 尼勒克县| 文山县| 宝坻区| 五指山市| 黎城县| 蕉岭县| 绿春县| 天祝| 桐庐县| 上栗县| 湘潭县|