- Lua Game Development Cookbook
- Mário Ka?uba
- 1060字
- 2021-07-16 13:23:08
Processing input events with LuaSDL
LuaSDL offers a form of platform-independent abstraction layer to these devices with an inner event pool. You only have to query the event pool for unprocessed events and, if there are any, check for the event type.
Getting ready
Before doing any event processing, your application must initialize internal event pools. This can be achieved with the SDL.SDL_Init
function, where the only parameter is a bitmask representing which parts of LuaSDL you want to initialize. You can use the bitlib library for the Lua language. Another option would be to use the bit32 internal library if you are using the newer version of the Lua interpreter. The default value here is SDL.SDL_INIT_EVERYTHING
, which is fine as it starts the event pool automatically. Specifically, you can use the SDL.SDL_INIT_EVENTTHREAD
or SDL.SDL_INIT_VIDEO
values to initialize the event pool.
A code sample can be used to initialize the LuaSDL library. It should be used right at the start of the application:
require 'LuaSDL' require 'bit' -- initialize video device and internal thread for event processing SDL.SDL_Init(bit.bor(SDL.SDL_INIT_VIDEO, SDL.SDL_INIT_EVENTTHREAD))
How to do it…
You can poll for currently pending events with the SDL.SDL_PollEvent
function. This function uses the SDL_Event
object as the only argument and fills this object with event information, if there's any. LuaSDL provides the SDL.SDL_Event_local
function, which creates the local SDL_Event
object. Keep in mind that this object is not kept globally. The SDL_Event
object will be subject to garbage collection after you leave the block where it was defined. The SDL.SDL_PollEvent
function also returns a value 1 if there is an event that is currently pending or 0 if there aren't any. This approach is quite desirable because you call this function only once for each event loop iteration. If there are no events pending, you can just skip further event processing in that iteration.
First of all, you need to create a local event object. This object will contain event information and can be defined at the start of your application and freed upon application exit.
local event = SDL.SDL_Event_local()
The application event loop can be defined as a while
loop:
local running = true while (running) do if (SDL.SDL_PollEvent(event) ~= 0) then process_event(event) end end
Incoming events will be processed in the process_event
function. This function usually handles more than one type of event, which is defined in the event.type
variable. Each event type can be processed separately inside the if-then-else
chain of code blocks or you can rely on the function map stored in a Lua table in the form of an associative array. The Lua language doesn't contain the switch statement known from other programming languages, so you are mostly left with these two options. For other kinds of switch statement alternatives, you can refer to the lua-users wiki page at http://lua-users.org/wiki/SwitchStatement.
As long as the amount of event types is small enough, it doesn't really matter which one you use.
Event handling with the if-then-else chain
An example of the if-else-if
chain is shown in the following code:
local function process_event(event) if event.type == SDL.SDL_KEYDOWN then print("Key pressed:", event.key.keysym.sym) elseif event.type == SDL.SDL_KEYUP then print("Key released:", event.key.keysym.sym) elseif event.type == SDL.SDL_QUIT running = false end end
In the first case with event type SDL.SDL_KEY_DOWN
, the code captures an event of pressing a key on your keyboard. You can get both the key symbol code defined in event.key.keysym.sym
or a scan code from event.key.keysym.scancode
. A key symbol code is keyboard-layout dependent, whereas scancode
is a hardware-dependent value. Usually, you'll want to use a key symbol code if you're developing a game.
The second case with the SDL.SDL_KEYUP
event type captures an event of key releasing and the last one detects a quit event when the user closes the application window.
Event handling with an associative array
The next example shows how to process events with the associative array represented with the Lua table:
local events = { [SDL.SDL_KEYDOWN] = function(raw_event) local event = raw_event.key local key = event.keysym.sym print("Key pressed:", key) end, [SDL.SDL_KEYUP] = function(raw_event) local event = raw_event.key local key = event.keysym.sym print("Key released:", key) end, [SDL.SDL_QUIT] = function(raw_event) running = false end, } local function process_event(event) local event_fn = events[event.type] if type(event_fn)=='function' then event_fn(event) end end
In this case, the process_event
function looks up for a key-value pair in the events
table. A key part of a pair corresponds to the event type identifier. On the other hand, a value part contains a function that will be invoked. A complete list of valid event type identifiers is shown in a table, which we will look at shortly. In every case, an event function will be called with the current event object placed in the first function argument.
Keep in mind that LuaSDL always uses a generic form of event object. Therefore, to get a certain event attribute, you need to follow this structure:
event.[structure_name].[structure_attribute]
For instance, if you wanted to know what key was pressed, you can use the key symbol identifier from the key
structure.
local keySymbol = event.key.keysym.sym
The following table shows what event types LuaSDL can handle:
Each event type has its own attributes. You can use those attributes to obtain information about specific events, for example, the mouse button that was pressed or the key symbol code. The next set of recipes in this chapter will cover the most common use cases of some of the event types.
How it works…
The LuaSDL library is intended to be used with the event polling mechanism, which is used in a loop, as you can see in the following sample code:
-- application can be exited be setting running variable to false local running = true -- prepare local instance of SDL_Event object local local_event = SDL.SDL_Event_local() while (running) do -- check for events in the poll if (SDL.SDL_PollEvent(local_event)~=0) then local event_fn = events[local_event.type] if type(event_fn)=='function' then event_fn(local_event) end else -- ...do game mechanics end end
This application design allows you to react to the input event when needed while idle time can be used to process game mechanics or video rendering. However, special care must be taken to prevent game mechanics from taking too long to finish as this may halt your application or make it less responsive.
See also
- The Using the keyboard input recipe
- The Using the relative mouse position recipe
- The Using the absolute mouse position recipe
- JavaScript前端開發模塊化教程
- The DevOps 2.3 Toolkit
- Manga Studio Ex 5 Cookbook
- Software Testing using Visual Studio 2012
- Visual Basic程序設計教程
- Python高級編程
- aelf區塊鏈應用架構指南
- 動手學數據結構與算法
- 一本書講透Java線程:原理與實踐
- ScratchJr趣味編程動手玩:讓孩子用編程講故事
- Unity&VR游戲美術設計實戰
- C++編程兵書
- Python Projects for Kids
- Java Hibernate Cookbook
- Drupal 8 Development Cookbook(Second Edition)