- Lua Game Development Cookbook
- Mário Ka?uba
- 861字
- 2021-07-16 13:23:08
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
- For a complete list of SDLK_ key symbol constants, you can browse a header file
SDK_keysym.h
from libSDL 1.2, which is also available in the GitHub repository at https://github.com/soulik/LuaSDL/blob/master/src/binding/orig/SDL_keysym.h
- 數據庫系統原理及MySQL應用教程(第2版)
- Flask Web全棧開發實戰
- UI圖標創意設計
- Android Studio Essentials
- Machine Learning with R Cookbook(Second Edition)
- Java入門很輕松(微課超值版)
- Selenium Design Patterns and Best Practices
- Python完全自學教程
- 深入淺出Serverless:技術原理與應用實踐
- Unity 5 for Android Essentials
- 利用Python進行數據分析(原書第3版)
- Hands-On Automation Testing with Java for Beginners
- Angular開發入門與實戰
- Protocol-Oriented Programming with Swift
- 編程菜鳥學Python數據分析