simvx.core.input.actions¶
How device inputs compose into an action, and what type that action has.
A game declares what an action is rather than assembling it at every call site::
input_context = {
"jump": [Key.SPACE, Controller.A], # bool
"throttle": [Axis1D(low=Key.LEFT_CONTROL, high=Key.SPACE),
Controller.RIGHT_TRIGGER], # float
"move": [Axis2D.WASD, Controller.LEFT_STICK], # Vec2
}
The type follows from the bindings: buttons alone give bool, an
- class:
Axis1Dor a single axis givesfloat, an :class:Axis2Dor a stick givesVec2.Input.value(action)returns that type andInput.pressed(action)still answers on all three, meaning “past the deadzone” for a continuous one.
Each entry in the list is one source, and a source produces a whole value of the action’s type on its own. That is what makes “largest magnitude wins” well defined: the keys give one vector, the stick gives another, and the action takes whichever is further from rest rather than summing them.
A full axis is its two halves, and a stick is its two axes, so there is one
composite for a scalar and one for a vector rather than a type per spelling:
a bare axis such as Controller.LEFT_X or a tablet’s ring normalises to an
- class:
Axis1Dover its negative and positive halves, and a stick such asController.LEFT_STICKto an :class:Axis2Dover the halves of its two axes.
A string is another entry’s name. Actions and device aliases are entries of
one map, so "pause": ["start", Key.ESCAPE] takes whatever "start"
resolves to, and Axis2D(up="forward", ...) takes the one control
"forward" names. The input map expands the names once whenever it changes.
Module Contents¶
Classes¶
What type an action’s value has, decided by the bindings it was given. |
|
Two opposed inputs composed into one signed value, -1.0 to 1.0. |
|
Four inputs composed into a direction, with a magnitude of at most 1.0. |
|
One entry of the input map: what it is called, what type it has, what drives it. |
Functions¶
Data¶
API¶
- simvx.core.input.actions.__all__¶
[‘ActionKind’, ‘Axis1D’, ‘Axis2D’, ‘BindingSpec’, ‘SourceSpec’]
- class simvx.core.input.actions.ActionKind[source]¶
Bases:
enum.StrEnumWhat type an action’s value has, decided by the bindings it was given.
Initialization
Initialize self. See help(type(self)) for accurate signature.
- BUTTON¶
‘button’
- AXIS_1D¶
‘axis_1d’
- AXIS_2D¶
‘axis_2d’
- __new__(*values)¶
- __add__()¶
- __contains__()¶
- __delattr__()¶
- __dir__()¶
- __eq__()¶
- __format__()¶
- __ge__()¶
- __getattribute__()¶
- __getitem__()¶
- __getnewargs__()¶
- __getstate__()¶
- __gt__()¶
- __hash__()¶
- __iter__()¶
- __le__()¶
- __len__()¶
- __lt__()¶
- __mod__()¶
- __mul__()¶
- __ne__()¶
- __reduce__()¶
- __reduce_ex__()¶
- __repr__()¶
- __rmod__()¶
- __rmul__()¶
- __setattr__()¶
- __sizeof__()¶
- __str__()¶
- __subclasshook__()¶
- capitalize()¶
- casefold()¶
- center()¶
- count()¶
- encode()¶
- endswith()¶
- expandtabs()¶
- find()¶
- format()¶
- format_map()¶
- index()¶
- isalnum()¶
- isalpha()¶
- isascii()¶
- isdecimal()¶
- isdigit()¶
- isidentifier()¶
- islower()¶
- isnumeric()¶
- isprintable()¶
- isspace()¶
- istitle()¶
- isupper()¶
- join()¶
- ljust()¶
- lower()¶
- lstrip()¶
- partition()¶
- removeprefix()¶
- removesuffix()¶
- replace()¶
- rfind()¶
- rindex()¶
- rjust()¶
- rpartition()¶
- rsplit()¶
- rstrip()¶
- split()¶
- splitlines()¶
- startswith()¶
- strip()¶
- swapcase()¶
- title()¶
- translate()¶
- upper()¶
- zfill()¶
- __deepcopy__(memo)¶
- __copy__()¶
- name()¶
- value()¶
- class simvx.core.input.actions.Axis1D[source]¶
Two opposed inputs composed into one signed value, -1.0 to 1.0.
Axis1D(low=Key.LEFT_CONTROL, high=Key.SPACE)reads -1.0 while Control is held, 1.0 while Space is, and 0.0 with neither or both. Either side may be an axis half, which is how a trigger or a stick direction joins the same action: a bare axis in an action’s binding list becomes this over its two halves.Attributes: low: What drives the value negative. high: What drives it positive. deadzone: How far from rest the composed value must be to count. A component that is an axis half applies it; a button never sits inside it.
- low: simvx.core.input.actions.BindingSpec¶
None
- high: simvx.core.input.actions.BindingSpec¶
None
- deadzone: float¶
0.2
- property parts: tuple[simvx.core.input.actions.Part, simvx.core.input.actions.Part][source]¶
This source’s components as declared,
(low, high): bindings, or entries’ names.
- property bindings: tuple[simvx.core.input.events.InputBinding, simvx.core.input.events.InputBinding][source]¶
This source’s components,
(low, high), once the map has resolved every name in it.
- __mul__(factor: float) simvx.core.input.actions.Axis1D[source]¶
Both halves multiplied into the action’s unit:
Axis1D(low=Key.Q, high=Key.E) * 2.
- __rmul__¶
None
- per_second(rate: float) simvx.core.input.actions.Axis1D[source]¶
Both halves as motion: the held value times rate each second.
- classmethod for_device_axis(axis: simvx.core.input.controls.DeviceAxis, *, deadzone: float = 0.0) simvx.core.input.actions.Axis1D[source]¶
One whole axis, a tablet’s ring or strip, as a signed value: its two halves.
No deadzone by default: a dial reads exactly where it was turned, and a delta of a fraction of a turn is a real motion.
- class simvx.core.input.actions.Axis2D[source]¶
Four inputs composed into a direction, with a magnitude of at most 1.0.
Axis2D(up=Key.W, down=Key.S, left=Key.A, right=Key.D)is the keyboard half of a movement action, ready-made as :attr:WASDand :attr:ARROWS;Controller.LEFT_STICKin the same list is the stick half, and the action takes whichever is further from rest.+yis down the screen, as everywhere else in 2D. Keyword-only, because an order is a convention nothing checks and a wrong one inverts movement silently.The deadzone is radial rather than per axis, so a stick pushed diagonally is not clipped into a square: the whole vector is discarded when it is shorter than deadzone and passed through when it is not. A diagonal held on the keyboard is normalised to length 1.0, so walking diagonally is not faster.
Attributes: up, down, left, right: What drives each direction. deadzone: How far from centre the composed vector must reach to count.
- up: simvx.core.input.actions.BindingSpec¶
None
- down: simvx.core.input.actions.BindingSpec¶
None
- left: simvx.core.input.actions.BindingSpec¶
None
- right: simvx.core.input.actions.BindingSpec¶
None
- deadzone: float¶
0.2
- WASD: ClassVar[simvx.core.input.actions.Axis2D]¶
None
- ARROWS: ClassVar[simvx.core.input.actions.Axis2D]¶
None
- property parts: tuple[simvx.core.input.actions.Part, simvx.core.input.actions.Part, simvx.core.input.actions.Part, simvx.core.input.actions.Part][source]¶
This source’s components as declared,
(up, down, left, right): bindings, or names.
- property bindings: tuple[simvx.core.input.events.InputBinding, simvx.core.input.events.InputBinding, simvx.core.input.events.InputBinding, simvx.core.input.events.InputBinding][source]¶
This source’s components,
(up, down, left, right), once the map has resolved every name.
- __mul__(factor: float) simvx.core.input.actions.Axis2D[source]¶
Every direction multiplied into the action’s unit:
Touch.PAN * 0.01reads the screen’s width as 1.
- __rmul__¶
None
- per_second(rate: float) simvx.core.input.actions.Axis2D[source]¶
Every direction as motion: the held value times rate each second.
- classmethod for_stick(stick: simvx.core.input.controls.DeviceStick, *, deadzone: float = 0.2) simvx.core.input.actions.Axis2D[source]¶
One whole stick as a vector: the halves of its two axes, on the stick’s unit.
- simvx.core.input.actions.to_source(spec: simvx.core.input.actions.SourceSpec) simvx.core.input.actions.Source[source]¶
Normalise one entry of an action’s binding list into a source.
A bare axis becomes the :class:
Axis1Dover its two halves and a bare stick the :class:Axis2Dover its two axes, so everything below this point deals in three source types rather than in every spelling of them.
- simvx.core.input.actions.kind_for(name: str, sources: list[simvx.core.input.actions.Source]) simvx.core.input.actions.ActionKind[source]¶
The type an action has, given its sources, refusing a list that has none.
The widest source decides, and a narrower one has to have an unambiguous reading inside it: a button in a float action pushes it positive, while a button or a scalar in a 2D action names no direction at all and is refused here rather than resolving to something the game did not mean.
- class simvx.core.input.actions.Action[source]¶
One entry of the input map: what it is called, what type it has, what drives it.
An action and a device alias are both entries.
sourceseach produce a whole value on their own and may name other entries; once the map has expanded them,bindingsis the same thing flattened to device bindings, which is what a prompt and the event resolver read. An entry keyed by a control rather than a name is a game’s redefinition of an engine entry,Controller.A, and has exactly one source.- name: str | simvx.core.input.controls.DeviceControl¶
None
- kind: simvx.core.input.actions.ActionKind¶
None
- sources: list[simvx.core.input.actions.Source]¶
‘field(…)’
- bindings: list[simvx.core.input.events.InputBinding]¶
‘field(…)’