Specialized components
Input and interaction system
Input receiver
13 min
overview the input receiver component enables game entities to listen for and respond to user inputs it serves as the bridge between the raw input data captured by input sources and the game logic that determines how entities should react to player actions inputcomponent in the ir engine, input receivers are implemented through the inputcomponent when attached to an entity, this component allows it to define semantic actions map physical inputs (like specific keys or buttons) to meaningful actions in the game context specify input sources determine which input devices the entity should listen to query input states check the current state of defined actions to trigger appropriate responses component structure the inputcomponent contains several key properties property description buttonbindings maps semantic action names to physical button inputs inputsources references to entities with inputsourcecomponent that this entity listens to activationdistance how close an input pointer needs to be to interact with this entity autocapture whether the component automatically captures input focus when receiving input example configuration // conceptual structure of an inputcomponent on an interactive entity inputcomponent { // map semantic actions to physical inputs buttonbindings { "interact" \[keyboardbutton keye, mousebutton primaryclick], "alternativeaction" \[keyboardbutton keyq] }, // which input source entities to listen to inputsources \[keyboardentityid, mouseentityid], // additional configuration activationdistance 2, autocapture false } implementation example the following example demonstrates how to implement an interactive door using the inputcomponent 1\ adding the component to an entity // add inputcomponent to a door entity const doorentity = createentity(); setcomponent(doorentity, inputcomponent, { buttonbindings { "interact" \[keyboardbutton keye, mousebutton primaryclick] } // inputsources typically populated by another system // or default to global input sources }); 2\ checking for input in game logic // in a system or script that updates the door const doorinputcomponent = getcomponent(doorentity, inputcomponent); // get the current state of all bound buttons for this entity const buttons = inputcomponent getbuttons(doorentity); if (buttons interact? down) { // check if "interact" was just pressed this frame console log("player pressed interact! opening door "); // code to open the door } querying axis inputs in addition to button states, the inputcomponent can also query continuous axis values // in inputcomponent buttonbindings // "aimhorizontal" \[mouseaxis x] // in game logic const axes = inputcomponent getaxes(someentity); if (buttons aimbutton? pressed) { // if an "aimbutton" is held const lookspeed = 0 1; const horizontalrotation = axes aimhorizontal lookspeed; // apply horizontalrotation to the entity } technical implementation the inputcomponent getbuttons() method is the primary interface for querying input states when called, it performs several operations locate the input entity find the entity that holds the relevant inputcomponent retrieve bindings get the button mappings for the requested semantic actions check input sources iterate through the associated input sources query raw states for each input source, check the state of the mapped buttons combine results aggregate the state information to determine the overall state of each semantic action sequencediagram participant gamelogic as game logic participant helper as inputcomponent getbuttons() participant entityic as inputcomponent (on entity) participant keyboardisc as inputsourcecomponent (keyboard) participant mouseisc as inputsourcecomponent (mouse) gamelogic >>helper get button states for entity helper >>entityic get bindings for "interact" entityic >>helper "interact" maps to \[keye, primaryclick] helper >>entityic get inputsources entityic >>helper \[keyboardentity, mouseentity] helper >>keyboardisc is keye active? keyboardisc >>helper yes, keye down is true note over helper keye is active, so "interact" is active helper >>gamelogic returns proxy; "interact down" is true gamelogic >>gamelogic process "interact" action code implementation // simplified from components/inputcomponent ts export const inputcomponent = definecomponent({ name 'inputcomponent', // schema defines buttonbindings, inputsources, cachedbuttons, etc getbuttons\<bindingstype extends inputbuttonbindings = typeof defaultbuttonbindings>( entitycontext entity, inputbindings bindingstype = defaultbuttonbindings as any, autocapture = true ) { // find the entity with the inputcomponent const inputentity = inputcomponent getinputentity(entitycontext); if (inputentity === undefinedentity) return {} as buttonstatemap\<bindingstype>; const input = getmutablecomponent(inputentity, inputcomponent); // update bindings if new ones are provided if (inputbindings) { for (const binding of object keys(inputbindings)) { if (!input buttonbindings\[binding] value) input buttonbindings\[binding] set(inputbindings\[binding] as any); } } input autocapture set(autocapture); // return a proxy object that dynamically checks input states return input buttons get(no proxy stealth) as buttonstatemap\</ />; }, // additional methods omitted for brevity }); the buttons field in an inputcomponent is implemented as a dynamic proxy when accessing a property like buttons interact , the proxy checks the buttonbindings to find the associated physical buttons iterates through the inputsources to check the state of those buttons considers whether the input has already been consumed by another system returns the aggregated state for the semantic action this proxy mechanism provides a convenient interface while handling complex mapping and state checking behind the scenes benefits of the input receiver approach the inputcomponent provides several advantages abstraction game logic can work with semantic actions rather than specific physical inputs flexibility input bindings can be changed without modifying the core game logic device independence the same interaction can work across different input devices centralization input handling logic is consolidated in a single component next steps with an understanding of how entities can listen for and respond to user inputs, the next chapter explores how the input system coordinates the overall input processing pipeline next input system docid 2yp 6a pmbb9eokw gitv