Toggling Input Focus Across Objects

One of my biggest challenges in coding a game’s architecture is handling player input properly. The ability to control several different types of objects, such as the player, a menu, a vehicle, or the GUI, and switching back and forth between them can result in a cluster of if statements across a dozen objects.

Here’s my standard method of dealing with Input Focus

First, I add a couple variables to my Game object’s create event.

Game object – Create event

inputFocus = noone; //current input focus
inputFocusPrev = inputFocus; //previous input focus

The inputFocus variable will hold the object ID of whichever object we’re wanting the player to control.

Next, we create 3 main GML scripts that will handle most of the legwork for us when switching objects.

  • input_is_focused(id) – Checks if the current object ID is equal to the current inputFocus ID.
  • input_focus(id) – Changes the inputFocus ID to the entered ID.
  • input_focus_previous() – Toggles the inputFocus back to the previous inputFocus ID.

input_is_focused(id)

///input_is_focused(id)
///@description Checks if input is focused on object
///@param id

var oid = argument0;

//if the inputFocus ID matches the entered ID, return true. Otherwise, return false.
return Game.inputFocus == oid;

The reason we break this out into a script is for readability and to make global changes easier.

Because this script is specifically referencing an Object’s variable, if that Object’s name needs to be changed or you decide to create a different object to hold the configuration, you only have to change it in one file, rather than across dozens or possibly hundreds of objects.

input_focus(id)

///input_focus(id)
///@description Changes focus of input to object
///@param id

var oid = argument0;
Game.inputFocusPrev = Game.inputFocus;
Game.inputFocus = oid;

We store the inputFocus ID in the inputFocusPrev for use later, and then set the inputFocus to the entered Object ID.

input_focus_previous()

///input_focus_previous()
///@description Changes focus of input to the last object

var tmpFocus = Game.inputFocus; //store current focus
Game.inputFocus = Game.inputFocusPrev; //change current focus to previous object
Game.inputFocusPrev = tmpFocus; //set previous to current focus

This is useful for quick toggling back and forth. For example, opening and closing the Player’s inventory.

Once you have these scripts and the Game object variables, you can set up your input per object as follows:

Player object – Step event

if(input_is_focused(id)){
	if(keyboard_check_pressed(vk_escape)){
		with(instance_create_depth(0, 0, 0, Inventory)){
			parent = other.id;	
		}
	}
}

This code creates the Inventory object when the Escape key is pressed. Wrapping the keyboard check inside of the input_is_focused if statement keeps the input from happening unless the game is specifically focused on the Player object.

Next, in the Inventory object Create Event, we change the input_focus to the Inventory object.

Inventory object – Create event

/// @description Init Inventory

parent = noone;
input_focus(id);

Now input is happening on the Inventory and not on the Player:

Inventory object – Step event

/// @description Handle Inventory Input

if(input_is_focused(id)){
    if(keyboard_check_pressed(vk_escape)){
        instance_destroy(id);
        input_focus_previous();
    }
}

We use input_focus_previous() when the Inventory is closed, which switches inputFocus back to the last object that had focus. Having the ability to toggle back to the previous ID is useful because the player may not have opened the menu while controlling the Player object.

Now you can handle each object’s input within the object itself, and switch focus between them fairly easily.

 

Leave a Reply

Your email address will not be published. Required fields are marked *