Inputs
If you have questions, please ask them in our Discord server and we'll answer them promptly! 😊
Dreamlab offers a flexible system for responding to player input, providing a simple way to listen to incoming input events and automatically adds your game’s inputs to our input binding UI.
Registering Inputs
Inputs can be referenced either by Input Code, which corresponds to keyboard or mouse inputs, or by registering a named input with the input system. The advantage of named inputs is that they are automatically picked up by Dreamlab’s UI and allows players to set custom key binds.
View a full list of available input codes here.
Registering an input should be done as early as possible, usually this is done inside of an entities init()
function.
Since the input system is only available on the client, you need to check that it is available first.
Registering an input requires a unique identifier, a human readable label, and a default keybind. The human readable name will be used for the automatic rebinding UI.
As with Spawnable Entities, we recommend namespacing input identifiers using a similar @entity/input
format, but again this is just a convention.
We recommend using a string enum to define input identifiers in a type-safe way.
import type { SpawnableContext } from '@dreamlab.gg/core'
import { SpawnableEntity } from '@dreamlab.gg/core'
import { inputs } from '@dreamlab.gg/core/labs'
// Define inputs with a string enum
enum ExampleInput {
MyInput = '@example/my-input',
MyOtherInput = '@example/my-other-input',
}
type Args = typeof ArgsSchema
const ArgsSchema = z.object({})
export class ExampleInputs extends SpawnableEntity<Args> {
public constructor(ctx: SpawnableContext<Args>) {
super(ctx)
// Use a "magic" function to get a reference to the input manager
const $inputs = inputs()
if ($inputs) {
// ensure you only do input related code on the client
$inputs.registerInput(ExampleInput.MyInput, 'My Input', 'KeyG')
$inputs.registerInput(ExampleInput.MyOtherInput, 'Other Input', 'KeyH')
// ... register more inputs
}
}
}
Responding to Inputs
You can either poll the state of an input directly, or attatch an event listener to the input system to run code when an input state changes. Usually you should use event listeners, unless you want to run code that deals with physics bodies.
Event Based
Input events are fired when the input pressed
state changes, and this state is passed in to event handlers as a boolean argument.
Make sure you only respond to the event for one state or your code will execute twice, once when the input is pressed and once when gets released.
// ... clipped
export class ExampleInputs extends SpawnableEntity<Args> {
public constructor(ctx: SpawnableContext<Args>) {
const $inputs = inputs()
if ($inputs) {
$inputs.registerInput(ExampleInput.MyInput, 'My Input', 'KeyG')
// Listen to keys directly
$inputs.addListener('Space', (pressed: boolean) => {
// Only run when the input has been pressed
if (!pressed) return
// ...
})
// Listen to named inputs
// Inputs must be registered first
$inputs.addListener(ExampleInput.MyInput, (pressed: boolean) => {
// ...
})
}
return { game }
}
// ... clipped
}
Tick Based
// ... clipped
export class ExampleInputs extends SpawnableEntity<Args> {
// ... clipped
public override onPhysicsStep({ time, delta }, { game }) {
const inputs = game.client?.inputs
if (inputs) {
// Get the state of a raw input
const keyPressed = inputs.getKey('Space')
// Get the state of a named input
const inputPressed = inputs.getInput(ExampleInput.MyInput)
// ...
}
}
// ... clipped
}