Add Hugo website and rewrite docs to match current engine
New Hugo site in website/ with prosperon.dev theme (blue/gold/castle aesthetic), docs sidebar navigation, and content pages. Rewrote all doc files to align with the actual codebase: compositor+film2d rendering, use() modules (no global prosperon object), Pit language, script+JSON entity model. Added entities.md, front matter to all 70+ API docs, and updated API index for current module architecture. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
180
docs/input.md
180
docs/input.md
@@ -1,54 +1,148 @@
|
||||
# Program events and an example input system
|
||||
---
|
||||
title: "Input"
|
||||
type: docs
|
||||
---
|
||||
|
||||
Prosperon provides a handy `input` module. Input is done in a highly generic and customizable manner. *players* can take control of any object (actor or otherwise) in Prosperon, after which it is referred to as a *pawn* of a player. If the object has a defined *input* object, it is a valid pawn. One player can have many pawns, but each pawn may have only one player.
|
||||
# Input
|
||||
|
||||
Pawns are added as a stack, with the newest ones getting priority, and handled first. It is possible for pawns to block input to lower pawns on the stack.
|
||||
Prosperon's input system normalizes keyboard, mouse, gamepad, and touch into **named actions**. You define what actions your game uses, bind them to physical inputs, and the engine routes events to the right place.
|
||||
|
||||
```
|
||||
*newest*
|
||||
car <== When a key is pressed, this is the first pawn to handle input
|
||||
player
|
||||
ui <== /block/ is set to true here, so editor recieves no input!
|
||||
editor
|
||||
*oldest*
|
||||
```
|
||||
## Actions
|
||||
|
||||
The default player can be obtained with `Player.players[0]`. Players are all local, and the highest number is determined by platform.
|
||||
An action is a named game event like `"jump"`, `"attack"`, or `"ui_up"`. Multiple physical inputs can trigger the same action:
|
||||
|
||||
The **input** object defines a number of keys or actions, with their values being functions.
|
||||
|
||||
## Editor input
|
||||
The editor input style defines keystrokes. It is good for custom editors, or any sort of game that requires many hotkeys. Keystrokes are case sensitive and can be augmented with auxiliary keys.
|
||||
|
||||
| symbol | key |
|
||||
|--------|-------|
|
||||
| C | ctrl |
|
||||
| M | alt |
|
||||
| S | super |
|
||||
|
||||
```
|
||||
```javascript
|
||||
var input = use('input')
|
||||
var orc = this.spawn('orc');
|
||||
orc.inputs = {};
|
||||
orc.inputs.a = function() { ... };
|
||||
orc.inputs.A = function() { ... }; /* This is only called with a capital A! */
|
||||
orc.inputs['C-a'] = function() { ... }; /* Control-a */
|
||||
input.players[0].control(orc); /* player 0 is now in control of the orc */
|
||||
|
||||
input.configure({
|
||||
action_map: {
|
||||
jump: ['space', 'gamepad_a'],
|
||||
attack: ['mouse_button_left', 'gamepad_x'],
|
||||
move_left: ['a', 'left', 'gamepad_dpleft'],
|
||||
move_right: ['d', 'right', 'gamepad_dpright']
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The input object can be modified to customize how it handles input.
|
||||
Default actions are provided for common UI navigation (`ui_up`, `ui_down`, `ui_left`, `ui_right`, `confirm`, `cancel`, `menu`).
|
||||
|
||||
| property | type | effect |
|
||||
|----------------|----------|--------------------------------------|
|
||||
| post | function | called after any input is processed |
|
||||
| =release_post= | function | called after any input is released |
|
||||
| fallthru | bool | false if input should stop with this |
|
||||
| block | bool | true if input should stop with this |
|
||||
## Players and Users
|
||||
|
||||
The input can be modified by setting properties on the associated function.
|
||||
The input system supports multiple players. Each **user** has:
|
||||
|
||||
| property | type | effect |
|
||||
|----------|----------|--------------------------------------------------------|
|
||||
| released | function | Called when the input is released |
|
||||
| rep | bool | true if holding the input should repeatedly trigger it |
|
||||
| down | function | called while the input is down |
|
||||
- Paired devices (keyboard, specific gamepad, etc.)
|
||||
- An action map (bindings can differ per player)
|
||||
- A **control stack** of possessed entities
|
||||
|
||||
```javascript
|
||||
var p1 = input.player1()
|
||||
```
|
||||
|
||||
### Device Pairing
|
||||
|
||||
By default, pairing is `'last_used'` — all input goes to player 1, and the active device switches when a button is pressed. For local multiplayer, use `'explicit'` pairing where each player is assigned specific devices.
|
||||
|
||||
```javascript
|
||||
input.configure({
|
||||
max_users: 2,
|
||||
pairing: 'explicit'
|
||||
})
|
||||
```
|
||||
|
||||
## Control Stack (Possession)
|
||||
|
||||
Players **possess** entities to route input to them. The control stack is ordered — the topmost entity gets input first.
|
||||
|
||||
```javascript
|
||||
var p1 = input.player1()
|
||||
|
||||
// Take control of the player character
|
||||
p1.possess(player_entity)
|
||||
|
||||
// Push a menu on top — it gets input priority
|
||||
p1.push(pause_menu)
|
||||
|
||||
// Pop the menu — player character gets input again
|
||||
p1.pop()
|
||||
```
|
||||
|
||||
The possessed entity must have an `on_input` method:
|
||||
|
||||
```javascript
|
||||
var player = {
|
||||
on_input: function(action, data) {
|
||||
if (action == 'jump' && data.pressed) {
|
||||
// jump logic
|
||||
}
|
||||
if (action == 'move_right') {
|
||||
// data.pressed, data.released, data.time
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Device Detection
|
||||
|
||||
The input system tracks what kind of device is active, so you can show appropriate button prompts:
|
||||
|
||||
```javascript
|
||||
var p1 = input.player1()
|
||||
var kind = p1.device_kind() // 'keyboard', 'mouse', 'gamepad'
|
||||
var type = p1.gamepad_type() // 'xbox', 'playstation', etc.
|
||||
```
|
||||
|
||||
Get the display name or icon for an action based on the current device:
|
||||
|
||||
```javascript
|
||||
var icon = p1.get_icon_for_action('jump')
|
||||
var binding = p1.get_primary_binding('jump')
|
||||
```
|
||||
|
||||
## Emacs-Style Keybindings
|
||||
|
||||
For editors or complex hotkey systems, Prosperon supports modifier notation:
|
||||
|
||||
| Prefix | Key |
|
||||
|--------|-----|
|
||||
| `C-` | Ctrl |
|
||||
| `M-` | Alt |
|
||||
| `S-` | Super |
|
||||
|
||||
So `C-a` means Ctrl+A, `C-M-s` means Ctrl+Alt+S. Case is preserved — `a` and `A` are different bindings.
|
||||
|
||||
The emacs module is enabled by default but can be disabled:
|
||||
|
||||
```javascript
|
||||
input.configure({ emacs: false })
|
||||
```
|
||||
|
||||
## Gestures
|
||||
|
||||
Touch gesture recognition is built in:
|
||||
|
||||
- Swipe detection (with configurable distance and time thresholds)
|
||||
- Pinch detection
|
||||
|
||||
```javascript
|
||||
input.configure({
|
||||
gestures: true,
|
||||
swipe_min_dist: 50,
|
||||
swipe_max_time: 0.5
|
||||
})
|
||||
```
|
||||
|
||||
## Saved Bindings
|
||||
|
||||
Player bindings are automatically saved and loaded, so remapped controls persist across sessions.
|
||||
|
||||
## Raw Events
|
||||
|
||||
For debugging or special cases, the raw SDL event can be accessed via the config callback:
|
||||
|
||||
```javascript
|
||||
core.start({
|
||||
input: function(raw_event) {
|
||||
// raw SDL event object
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user