@benev/tact 0.1.0-1 → 0.1.0-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/README.md +176 -115
  2. package/package.json +3 -2
  3. package/s/{station → core/bindings}/types.ts +4 -20
  4. package/s/core/controllers/controller.ts +7 -0
  5. package/s/core/controllers/infra/group.ts +17 -0
  6. package/s/{station/devices → core/controllers}/infra/sampler.ts +3 -3
  7. package/s/{station/devices → core/controllers/standard}/gamepad.ts +6 -6
  8. package/s/core/controllers/standard/index.ts +7 -0
  9. package/s/{station/devices → core/controllers/standard}/keyboard.ts +3 -3
  10. package/s/{station/devices → core/controllers/standard}/pointer.ts +34 -34
  11. package/s/{nubs/stick/device.ts → core/controllers/standard/stick.ts} +3 -3
  12. package/s/{nubs/virtual-gamepad/device.ts → core/controllers/standard/virtual-gamepad.ts} +5 -5
  13. package/s/core/controllers/types.ts +4 -0
  14. package/s/core/core.test.ts +90 -0
  15. package/s/core/hub/auto-gamepads.ts +8 -0
  16. package/s/{station/parts/switchboard-bindings.ts → core/hub/bindings.ts} +4 -4
  17. package/s/core/hub/hub.ts +102 -0
  18. package/s/core/index.ts +19 -0
  19. package/s/{station/parts → core/port}/action.ts +3 -9
  20. package/s/core/port/port.ts +34 -0
  21. package/s/core/port/resolution/defaults.ts +30 -0
  22. package/s/{station/parts/routines/lensing_algorithm.ts → core/port/resolution/lens-algo.ts} +13 -11
  23. package/s/core/port/resolution/resolver.ts +77 -0
  24. package/s/core/port/resolution/types.ts +9 -0
  25. package/s/core/port/types.ts +10 -0
  26. package/s/core/port/utils/aggregate_samples_into_map.ts +20 -0
  27. package/s/core/port/utils/wipe_samples_map.ts +8 -0
  28. package/s/core/testing/testing.ts +50 -0
  29. package/s/demo/main.bundle.ts +2 -2
  30. package/s/index.ts +1 -11
  31. package/s/nubs/stick/view.ts +2 -2
  32. package/s/nubs/virtual-gamepad/view.ts +6 -6
  33. package/s/tests.test.ts +2 -4
  34. package/s/{station/utils/tmin.ts → utils/quick-math.ts} +6 -0
  35. package/x/{station → core/bindings}/types.d.ts +4 -16
  36. package/x/core/bindings/types.js +5 -0
  37. package/x/core/bindings/types.js.map +1 -0
  38. package/x/core/controllers/controller.d.ts +4 -0
  39. package/x/core/controllers/controller.js +3 -0
  40. package/x/core/controllers/controller.js.map +1 -0
  41. package/x/core/controllers/infra/group.d.ts +7 -0
  42. package/x/core/controllers/infra/group.js +13 -0
  43. package/x/core/controllers/infra/group.js.map +1 -0
  44. package/x/core/controllers/infra/sampler.d.ts +8 -0
  45. package/x/{station/devices → core/controllers}/infra/sampler.js +2 -2
  46. package/x/core/controllers/infra/sampler.js.map +1 -0
  47. package/x/core/controllers/standard/gamepad.d.ts +10 -0
  48. package/x/{station/devices → core/controllers/standard}/gamepad.js +5 -5
  49. package/x/core/controllers/standard/gamepad.js.map +1 -0
  50. package/x/core/controllers/standard/index.d.ts +5 -0
  51. package/x/core/controllers/standard/index.js +6 -0
  52. package/x/core/controllers/standard/index.js.map +1 -0
  53. package/x/{station/devices → core/controllers/standard}/keyboard.d.ts +3 -3
  54. package/x/{station/devices → core/controllers/standard}/keyboard.js +3 -3
  55. package/x/core/controllers/standard/keyboard.js.map +1 -0
  56. package/x/{station/devices → core/controllers/standard}/pointer.d.ts +3 -3
  57. package/x/{station/devices → core/controllers/standard}/pointer.js +29 -29
  58. package/x/core/controllers/standard/pointer.js.map +1 -0
  59. package/x/{nubs/stick/device.d.ts → core/controllers/standard/stick.d.ts} +2 -2
  60. package/x/{nubs/stick/device.js → core/controllers/standard/stick.js} +4 -4
  61. package/x/core/controllers/standard/stick.js.map +1 -0
  62. package/x/core/controllers/standard/virtual-gamepad.d.ts +7 -0
  63. package/x/{nubs/virtual-gamepad/device.js → core/controllers/standard/virtual-gamepad.js} +6 -6
  64. package/x/core/controllers/standard/virtual-gamepad.js.map +1 -0
  65. package/x/core/controllers/types.d.ts +2 -0
  66. package/x/core/controllers/types.js +2 -0
  67. package/x/core/controllers/types.js.map +1 -0
  68. package/x/core/controllers/utils/modprefix.js.map +1 -0
  69. package/x/core/core.test.d.ts +11 -0
  70. package/x/core/core.test.js +84 -0
  71. package/x/core/core.test.js.map +1 -0
  72. package/x/core/hub/auto-gamepads.d.ts +2 -0
  73. package/x/core/hub/auto-gamepads.js +6 -0
  74. package/x/core/hub/auto-gamepads.js.map +1 -0
  75. package/x/core/hub/bindings.d.ts +2 -0
  76. package/x/{station/parts/switchboard-bindings.js → core/hub/bindings.js} +4 -4
  77. package/x/core/hub/bindings.js.map +1 -0
  78. package/x/core/hub/hub.d.ts +29 -0
  79. package/x/core/hub/hub.js +91 -0
  80. package/x/core/hub/hub.js.map +1 -0
  81. package/x/core/index.d.ts +14 -0
  82. package/x/core/index.js +15 -0
  83. package/x/core/index.js.map +1 -0
  84. package/x/{station/parts → core/port}/action.d.ts +1 -3
  85. package/x/{station/parts → core/port}/action.js +3 -10
  86. package/x/core/port/action.js.map +1 -0
  87. package/x/core/port/port.d.ts +12 -0
  88. package/x/core/port/port.js +25 -0
  89. package/x/core/port/port.js.map +1 -0
  90. package/x/core/port/resolution/defaults.d.ts +4 -0
  91. package/x/{station/parts → core/port/resolution}/defaults.js +4 -3
  92. package/x/core/port/resolution/defaults.js.map +1 -0
  93. package/x/core/port/resolution/lens-algo.d.ts +2 -0
  94. package/x/{station/parts/routines/lensing_algorithm.js → core/port/resolution/lens-algo.js} +9 -8
  95. package/x/core/port/resolution/lens-algo.js.map +1 -0
  96. package/x/core/port/resolution/resolver.d.ts +9 -0
  97. package/x/core/port/resolution/resolver.js +64 -0
  98. package/x/core/port/resolution/resolver.js.map +1 -0
  99. package/x/core/port/resolution/types.d.ts +6 -0
  100. package/x/core/port/resolution/types.js +2 -0
  101. package/x/core/port/resolution/types.js.map +1 -0
  102. package/x/core/port/types.d.ts +7 -0
  103. package/x/core/port/types.js +2 -0
  104. package/x/core/port/types.js.map +1 -0
  105. package/x/core/port/utils/aggregate_samples_into_map.d.ts +3 -0
  106. package/x/core/port/utils/aggregate_samples_into_map.js +11 -0
  107. package/x/core/port/utils/aggregate_samples_into_map.js.map +1 -0
  108. package/x/core/port/utils/is-pressed.js.map +1 -0
  109. package/x/core/port/utils/wipe_samples_map.d.ts +2 -0
  110. package/x/core/port/utils/wipe_samples_map.js +5 -0
  111. package/x/core/port/utils/wipe_samples_map.js.map +1 -0
  112. package/x/{station → core}/testing/testing.d.ts +8 -8
  113. package/x/core/testing/testing.js +42 -0
  114. package/x/core/testing/testing.js.map +1 -0
  115. package/x/demo/main.bundle.js +2 -2
  116. package/x/demo/main.bundle.js.map +1 -1
  117. package/x/demo/main.bundle.min.js +1 -1
  118. package/x/demo/main.bundle.min.js.map +4 -4
  119. package/x/index.d.ts +1 -11
  120. package/x/index.html +3 -3
  121. package/x/index.js +1 -11
  122. package/x/index.js.map +1 -1
  123. package/x/nubs/stick/view.d.ts +2 -2
  124. package/x/nubs/stick/view.js.map +1 -1
  125. package/x/nubs/virtual-gamepad/view.d.ts +2 -2
  126. package/x/nubs/virtual-gamepad/view.js +5 -5
  127. package/x/nubs/virtual-gamepad/view.js.map +1 -1
  128. package/x/tests.test.js +2 -4
  129. package/x/tests.test.js.map +1 -1
  130. package/x/{station/utils/tmax.d.ts → utils/quick-math.d.ts} +1 -0
  131. package/x/utils/quick-math.js +11 -0
  132. package/x/utils/quick-math.js.map +1 -0
  133. package/s/station/devices/infra/device.ts +0 -7
  134. package/s/station/devices/infra/group.ts +0 -17
  135. package/s/station/parts/defaults.ts +0 -28
  136. package/s/station/parts/resolver.ts +0 -73
  137. package/s/station/parts/routines/aggregate_samples_into_map.ts +0 -20
  138. package/s/station/parts/routines/build_updatable_actions_structure.ts +0 -29
  139. package/s/station/station.test.ts +0 -86
  140. package/s/station/station.ts +0 -47
  141. package/s/station/switchboard.ts +0 -107
  142. package/s/station/testing/testing.ts +0 -47
  143. package/s/station/utils/tmax.ts +0 -7
  144. package/x/nubs/stick/device.js.map +0 -1
  145. package/x/nubs/virtual-gamepad/device.d.ts +0 -7
  146. package/x/nubs/virtual-gamepad/device.js.map +0 -1
  147. package/x/station/devices/gamepad.d.ts +0 -10
  148. package/x/station/devices/gamepad.js.map +0 -1
  149. package/x/station/devices/infra/device.d.ts +0 -4
  150. package/x/station/devices/infra/device.js +0 -3
  151. package/x/station/devices/infra/device.js.map +0 -1
  152. package/x/station/devices/infra/group.d.ts +0 -7
  153. package/x/station/devices/infra/group.js +0 -13
  154. package/x/station/devices/infra/group.js.map +0 -1
  155. package/x/station/devices/infra/sampler.d.ts +0 -8
  156. package/x/station/devices/infra/sampler.js.map +0 -1
  157. package/x/station/devices/keyboard.js.map +0 -1
  158. package/x/station/devices/pointer.js.map +0 -1
  159. package/x/station/parts/action.js.map +0 -1
  160. package/x/station/parts/defaults.d.ts +0 -5
  161. package/x/station/parts/defaults.js.map +0 -1
  162. package/x/station/parts/resolver.d.ts +0 -10
  163. package/x/station/parts/resolver.js +0 -63
  164. package/x/station/parts/resolver.js.map +0 -1
  165. package/x/station/parts/routines/aggregate_samples_into_map.d.ts +0 -3
  166. package/x/station/parts/routines/aggregate_samples_into_map.js +0 -11
  167. package/x/station/parts/routines/aggregate_samples_into_map.js.map +0 -1
  168. package/x/station/parts/routines/build_updatable_actions_structure.d.ts +0 -5
  169. package/x/station/parts/routines/build_updatable_actions_structure.js +0 -18
  170. package/x/station/parts/routines/build_updatable_actions_structure.js.map +0 -1
  171. package/x/station/parts/routines/lensing_algorithm.d.ts +0 -2
  172. package/x/station/parts/routines/lensing_algorithm.js.map +0 -1
  173. package/x/station/parts/switchboard-bindings.d.ts +0 -2
  174. package/x/station/parts/switchboard-bindings.js.map +0 -1
  175. package/x/station/station.d.ts +0 -15
  176. package/x/station/station.js +0 -35
  177. package/x/station/station.js.map +0 -1
  178. package/x/station/station.test.d.ts +0 -11
  179. package/x/station/station.test.js +0 -80
  180. package/x/station/station.test.js.map +0 -1
  181. package/x/station/switchboard.d.ts +0 -30
  182. package/x/station/switchboard.js +0 -90
  183. package/x/station/switchboard.js.map +0 -1
  184. package/x/station/testing/testing.js +0 -39
  185. package/x/station/testing/testing.js.map +0 -1
  186. package/x/station/types.js +0 -5
  187. package/x/station/types.js.map +0 -1
  188. package/x/station/utils/is-pressed.js.map +0 -1
  189. package/x/station/utils/modprefix.js.map +0 -1
  190. package/x/station/utils/tmax.js +0 -6
  191. package/x/station/utils/tmax.js.map +0 -1
  192. package/x/station/utils/tmin.d.ts +0 -1
  193. package/x/station/utils/tmin.js +0 -6
  194. package/x/station/utils/tmin.js.map +0 -1
  195. /package/s/{station → core/controllers}/utils/modprefix.ts +0 -0
  196. /package/s/{station → core/port}/utils/is-pressed.ts +0 -0
  197. /package/x/{station → core/controllers}/utils/modprefix.d.ts +0 -0
  198. /package/x/{station → core/controllers}/utils/modprefix.js +0 -0
  199. /package/x/{station → core/port}/utils/is-pressed.d.ts +0 -0
  200. /package/x/{station → core/port}/utils/is-pressed.js +0 -0
package/README.md CHANGED
@@ -1,50 +1,128 @@
1
1
 
2
2
  # @benev/tact
3
- > user input keybindings and gamepad support for web games
3
+ > web game input library, from keypress to couch co-op
4
4
 
5
5
  ```ts
6
6
  npm install @benev/tact
7
7
  ```
8
8
 
9
- - 🛰️ **devices** are for sampling user inputs
10
- - 🔗 **bindings** describe how samples influence actions
11
- - 📡 **station** runs device samples through bindings, updating actions
12
- - 🔌 **switchboard** assigns devices to stations (multi-gamepad couch co-op!)
13
- - 🔘 **nubs** is mobile ui virtual gamepad stuff
9
+ - 🛹 **deck** user input coordinator with bindings persistence
10
+ - 🎮 **controllers** produce user input samples
11
+ - 🧩 **bindings** describe how actions interpret samples
12
+ - 🔌 **port** updates actions by interpreting samples
13
+ - 🛞 **hub** plugs controllers into ports (multi-gamepad couch co-op!)
14
+ - 📱 **nubs** is mobile ui virtual gamepad stuff
15
+
16
+
14
17
 
15
18
  <br/><br/>
16
19
 
17
- ## 🍋 tact devices
18
- > produces user input "samples"
20
+ ## 🍋 tact deck
21
+ > *user input coordinator with bindings persistence*
22
+
23
+ the deck is the heart of tact.. it ties all the important parts together..
24
+
25
+ ### 🛹 deck setup
26
+ - **import stuff from tact**
27
+ ```ts
28
+ import * as tact from "@benev/tact"
29
+ ```
30
+ - **setup your deck**
31
+ ```ts
32
+ const deck = new tact.Deck({
33
+ ports: 4,
34
+ kv: tact.Deck.localStorageKv(),
35
+ defaultBindings: tact.Hub.bindings({
36
+ walking: {
37
+ forward: [
38
+ {lenses: [{code: "KeyW"}]},
39
+ {lenses: [{code: "gamepad.stick.left.up"}]},
40
+ ],
41
+ jump: [
42
+ {lenses: [{code: "Space"}]},
43
+ {lenses: [{code: "gamepad.a"}]},
44
+ ],
45
+ },
46
+ gunning: {
47
+ shoot: [
48
+ {lenses: [{code: "pointer.button.left"}]},
49
+ {lenses: [{code: "gamepad.trigger.right"}]},
50
+ ],
51
+ },
52
+ }),
53
+ })
54
+ ```
55
+
56
+ ### 🛹 plug controllers into the hub
57
+ - **plug a keyboard/mouse player into the hub**
58
+ ```ts
59
+ deck.hub.plug(
60
+ new tact.GroupController(
61
+ new tact.KeyboardController(),
62
+ new tact.PointerController(),
63
+ new tact.VirtualGamepadController(),
64
+ )
65
+ )
66
+ ```
67
+ - **auto connect/disconnect gamepads as they come and go**
68
+ ```ts
69
+ tact.autoGamepads(deck.hub.plug)
70
+ ```
71
+
72
+ ### 🛹 do your gameplay
73
+ - **start with what modes you want enabled in your game**
74
+ ```ts
75
+ for (const port of deck.ports)
76
+ port.modes.adds("walking", "gunning")
77
+ ```
78
+ - **poll the deck, interrogate actions for your gameplay**
79
+ ```ts
80
+ onEachTickInYourGame(() => {
81
+
82
+ // do your polling
83
+ const [p1, p2, p3, p4] = deck.hub.poll()
84
+
85
+ // check if the first player is pressing "forward" action
86
+ p1.actions.walking.forward.pressed // true
87
+
88
+ // check how hard the second player is pulling that trigger
89
+ p2.actions.gunning.shoot.value // 0.123
90
+ })
91
+ ```
92
+
93
+
94
+
95
+ <br/><br/>
19
96
 
20
- ### 🥝 polling is good, actually
97
+ ## 🍋 tact controllers
98
+ > *produces user input "samples"*
99
+
100
+ ### 🎮 polling is good, actually
21
101
  - tact operates on the basis of *polling*
22
102
  - *"but polling is bad"* says you — but no — you're wrong — polling is unironically *based,* and you *should* do it
23
103
  - in a game, we want to be processing our inputs *every frame*
24
104
  - the gift of polling is total control over *when* inputs are processed
25
105
  - i will elaborate no further 🗿
26
106
 
27
- ### 🥝 basically how a device works
28
- - make a keyboard device
107
+ ### 🎮 basically how a controller works
108
+ - make a controller
29
109
  ```ts
30
- import {KeyboardDevice} from "@benev/tact"
31
-
32
- const device = new KeyboardDevice(window)
110
+ const keyboard = new tact.KeyboardController()
33
111
  ```
34
112
  - take samples each frame
35
113
  ```ts
36
- const samples = device.takeSamples()
114
+ const samples = keyboard.takeSamples()
37
115
  // [
38
116
  // ["KeyA", 1],
39
117
  // ["Space", 0]
40
118
  // ]
41
119
  ```
42
- - dispose the device when you're done with it
120
+ - dispose when you're done with it
43
121
  ```ts
44
- device.dispose()
122
+ keyboard.dispose()
45
123
  ```
46
124
 
47
- ### 🥝 samples explained
125
+ ### 🎮 samples explained
48
126
  - a sample is a raw input of type `[code: string, value: number]`
49
127
  - a sample has a `code` string
50
128
  - it's either a [standard keycode](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values), like `KeyA`
@@ -57,7 +135,7 @@ npm install @benev/tact
57
135
  - sometimes we use numbers greater then `1`, like for dots of pointer movement like in `pointer.move.up`
58
136
  - don't worry about sensitivity, deadzones, values like `0.00001` — actions will account for all that using bindings later on
59
137
 
60
- ### 🥝 sample code modprefixes
138
+ ### 🎮 sample code modprefixes
61
139
  - here at tact, we have this nifty `modprefix` convention
62
140
  - consider a keycode like `KeyA`
63
141
  - `ctrl-KeyA` means the "ctrl" modifier was held
@@ -68,8 +146,8 @@ npm install @benev/tact
68
146
  - `x-KeyA` means *no* modifier was held (exclusive)
69
147
  - `KeyA` doesn't care if any modifiers were held or not
70
148
 
71
- ### 🥝 sample code reference
72
- - **KeyboardDevice**
149
+ ### 🎮 sample code reference
150
+ - **KeyboardController**
73
151
  - any [standard keycode](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values)
74
152
  - `KeyA`
75
153
  - `Space`
@@ -80,7 +158,7 @@ npm install @benev/tact
80
158
  - `alt-shift-Space`
81
159
  - `x-Digit2`
82
160
  - etc
83
- - **PointerDevice**
161
+ - **PointerController**
84
162
  - mouse buttons (plus modprefixes)
85
163
  - `pointer.button.left`
86
164
  - `pointer.button.right`
@@ -97,7 +175,7 @@ npm install @benev/tact
97
175
  - `pointer.move.down`
98
176
  - `pointer.move.left`
99
177
  - `pointer.move.right`
100
- - **GamepadDevice**
178
+ - **GamepadController**
101
179
  - gamepad buttons
102
180
  - `gamepad.a`
103
181
  - `gamepad.b`
@@ -126,17 +204,17 @@ npm install @benev/tact
126
204
  - `gamepad.stick.right.left`
127
205
  - `gamepad.stick.right.right`
128
206
 
207
+
208
+
129
209
  <br/><br/>
130
210
 
131
211
  ## 🍋 tact bindings
132
- > keybindings! they describe how actions interpret samples
212
+ > *keybindings! they describe how actions interpret samples*
133
213
 
134
- ### 🥝 bindings example
214
+ ### 🧩 bindings example
135
215
  - let's start with a small example:
136
216
  ```ts
137
- import {Bindings} from "@benev/tact"
138
-
139
- const bindings = asBindings({
217
+ const bindings = tact.asBindings({
140
218
  walking: {
141
219
  forward: [{lenses: [{code: "KeyW"}]}],
142
220
  jump: [{lenses: [{code: "Space"}]}],
@@ -152,32 +230,46 @@ npm install @benev/tact
152
230
  - 🚨 TODO okay these rules are complex and i'm gonna rework them soon
153
231
  - whole modes can be enabled or disabled
154
232
 
233
+
234
+
155
235
  <br/><br/>
156
236
 
157
- ## 🍋 tact station
158
- > polling gives you actions
237
+ ## 🍋 tact port
238
+ > *polling gives you "actions"*
159
239
 
160
- ### 🥝 creating a station
161
- - create a station
240
+ ### 🔌 port basics
241
+ - **make a port**
162
242
  ```ts
163
- import {Station} from "@benev/tact"
164
-
165
- const station = new Station(bindings)
166
- .addModes("walking")
167
- .addDevices(
168
- new KeyboardDevice(window),
169
- new PointerDevice(window),
170
- )
243
+ const port = new tact.Port(bindings)
244
+ ```
245
+ - **attach some controllers to the port**
246
+ ```ts
247
+ port.controllers
248
+ .add(new tact.KeyboardController())
249
+ .add(new tact.PointerController())
250
+ .add(new tact.VirtualGamepadController())
251
+ ```
252
+ - you can add/delete controllers from the set any time
253
+ - **don't forget to enable modes!**
254
+ ```ts
255
+ port.modes.add("walking")
256
+ ```
257
+ - if you don't enable any modes, no actions will happen
258
+ - actions only happen for enabled modes
259
+ - you can toggle modes on and off by adding/deleting them from the modes set
260
+ - **you can update the bindings any time**
261
+ ```ts
262
+ port.bindings = freshBindings
171
263
  ```
172
264
 
173
- ### 🥝 how to use actions
174
- - poll the station every frame
265
+ ### 🔌 interrogating actions
266
+ - **poll the port every frame**
175
267
  ```ts
176
- station.poll(Date.now())
268
+ const actions = port.poll()
177
269
  ```
178
- - now you use the `actions`
270
+ - **now you can inspect the `actions`**
179
271
  ```ts
180
- station.actions.walking.forward.value // 1
272
+ actions.walking.forward.value // 1
181
273
  ```
182
274
  - `walking` is a `mode`
183
275
  - `forward` is an `action`
@@ -187,113 +279,82 @@ npm install @benev/tact
187
279
  - `action.pressed` — true if the value > 0
188
280
  - `action.down` — true for one frame when the key goes from up to down
189
281
  - `action.up` — true for one frame when the key goes from down to up
190
- - `action.on(action => {})` — react to changes ([`@e280/stz`](https://github.com/e280/stz) sub fn)
191
- - `action.onDown(action => {})` — react only on down ([`@e280/stz`](https://github.com/e280/stz) sub fn)
192
282
 
193
- ### 🥝 more about station
194
- - you can enable/disable modes like this (it's a set)
195
- ```ts
196
- station.modes.add("gunning")
197
- // now the "gunning" actions can fire
198
283
 
199
- station.modes.delete("walking")
200
- // now the "walking" actions *cannot* fire
201
- ```
202
- - you can add/remove devices from the set any time
203
- ```ts
204
- station.devices.add(new GamepadDevice(pad))
205
- ```
206
- - you can update the bindings at runtime
207
- ```ts
208
- station.bindings = bindings2
209
- ```
210
284
 
211
285
  <br/><br/>
212
286
 
213
- ## 🍋 tact switchboard
214
- > multiple gamepads! couch co-op is so back
287
+ ## 🍋 tact hub
288
+ > *multiple gamepads! couch co-op is so back*
215
289
 
216
- ### 🥝 feel the vibes
217
- - you know the way old timey game consoles had controller ports? and then players could plug their controller into whatever port they wanted? and then you could unplug and replug your controller into a different port? yeah — that's what switchboard does.
218
- - with the switchboard, think of the "stations" as controller ports, and the "devices" as player controllers.
219
- - import stuff:
220
- ```ts
221
- import {
222
- Switchboard, Station,
223
- GroupDevice, GamepadDevice, KeyboardDevice, PointerDevice,
224
- } from "@benev/tact"
225
- ```
290
+ you know the way old-timey game consoles had four controller ports on the front?
226
291
 
227
- ### 🥝 create a switchboard with stations
228
- - **adopt standard switchboard bindings**
292
+ the hub embraces that analogy, helping you coordinate the plugging and unplugging of virtual controllers into its virtual ports.
293
+
294
+ ### 🛞 create a hub with ports
295
+ - **adopt standard hub bindings**
229
296
  ```ts
230
- // transform your game's bindings into switchboard-friendly bindings
231
- const sBindings = Switchboard.bindings(bindings)
297
+ // transform your game's bindings into hub-friendly bindings
298
+ const hubBindings = tact.Hub.bindings(bindings)
232
299
  ```
233
- - this allows players to shimmy what station their controller controls
234
- - gamepad: hold middle button and press bumpers
300
+ - this augments your bindings with standard hub-specific bindings
301
+ - this lets players to shimmy what port their controller is plugged into
302
+ - gamepad: hold gamma (middle button) and press bumpers
235
303
  - keyboard: left bracket or right bracket
236
- - **make switchboard with stations at the ready**
304
+ - **make hub with multiple ports at the ready**
237
305
  ```ts
238
- const switchboard = new Switchboard([
239
- new Station(sBindings),
240
- new Station(sBindings),
241
- new Station(sBindings),
242
- new Station(sBindings),
306
+ const hub = new tact.Hub([
307
+ new tact.Port(hubBindings),
308
+ new tact.Port(hubBindings),
309
+ new tact.Port(hubBindings),
310
+ new tact.Port(hubBindings),
243
311
  ])
244
312
  ```
245
- - yes that's right — each player can have their own bindings 🤯
313
+ - yes that's right — each player port gets its own bindings 🤯
246
314
 
247
- ### 🥝 connect player's devices to the switchboard
248
- - **let's connect the keyboard/mouse player**
315
+ ### 🛞 plug in some controllers
316
+ - **let's plug in the keyboard/mouse player**
249
317
  ```ts
250
- switchboard.connect(
251
- new GroupDevice(
252
- new KeyboardDevice(window),
253
- new PointerDevice(window),
318
+ hub.plug(
319
+ new tact.GroupController(
320
+ new tact.KeyboardController(),
321
+ new tact.PointerController(),
322
+ new tact.VirtualGamepadController(),
254
323
  )
255
324
  )
256
325
  ```
257
- - the switchboard assumes a single device represents a single player, thus we can use a `GroupDevice` to combine multple devices into one
326
+ - the hub requires a single controller to represent a player, thus we can use a `GroupController` to combine multple controllers into one
258
327
  - **wire up gamepad auto connect/disconnect**
259
328
  ```ts
260
- GamepadDevice.on(device => switchboard.connect(device))
329
+ tact.autoGamepads(hub.plug)
261
330
  ```
262
331
 
263
- ### 🥝 you're ready!
332
+ ### 🛞 it's gaming time
264
333
  - **do your polling, interrogate those actions**
265
334
  ```ts
266
- const [p1, p2, p3, p4] = switchboard.stations
267
-
268
- // poll them all
269
- switchboard.poll(Date.now())
335
+ const [p1, p2, p3, p4] = hub.poll()
270
336
 
271
- p1.actions.walking.jump.value // 1
272
- p2.actions.walking.jump.value // 0
337
+ p1.walking.jump.value // 1
338
+ p2.walking.jump.value // 0
273
339
  ```
274
340
 
275
- ### 🥝 the more you know, about the switchboard
276
- - `switchboard.stations` — direct access to the array of stations
277
- - `switchboard.isActive(p1)` — check if there's a switchboard-connected-device assigned to this station
278
- - `switchboard.shimmy(device, 1)` — shimmy a device forward one station
279
- - `switchboard.shimmy(device, -1)` — shimmy a device backward one station
280
- - `switchboard.connect(device, p4)` — connect-or-reassign a device to a specific station
281
- - `switchboard.connect(device)` — connect a device to the next unassigned station (or the last station)
282
- - `switchboard.disconnect(device)` — unassign a device and forget about it
341
+
283
342
 
284
343
  <br/><br/>
285
344
 
286
345
  ## 🍋 tact nubs
287
- > mobile ui like virtual thumbsticks and buttons
346
+ > *mobile ui like virtual thumbsticks and buttons*
288
347
 
289
- ### 🥝 nub stick
348
+ ### 📱 nub stick
290
349
  > TODO lol need to write docs
291
350
 
292
- ### 🥝 nub virtual gamepad
351
+ ### 📱 nub virtual gamepad
293
352
  > TODO lol need to write docs
294
353
 
354
+
355
+
295
356
  <br/><br/>
296
357
 
297
358
  ## 🍋 tact is by https://benevolent.games/
298
- > building the future of web games
359
+ > *building the future of web games*
299
360
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@benev/tact",
3
- "version": "0.1.0-1",
3
+ "version": "0.1.0-2",
4
4
  "description": "keybindings and gamepad support for web games",
5
5
  "license": "MIT",
6
6
  "author": "Chase Moskal <chasemoskal@gmail.com>",
@@ -8,7 +8,8 @@
8
8
  "main": "./x/index.js",
9
9
  "sideEffects": false,
10
10
  "exports": {
11
- ".": "./x/index.js"
11
+ ".": "./x/index.js",
12
+ "./core": "./x/core/index.js"
12
13
  },
13
14
  "files": [
14
15
  "x",
@@ -1,15 +1,4 @@
1
1
 
2
- import {Action} from "./parts/action.js"
3
-
4
- export type Actions<B extends Bindings> = {
5
- [Mode in keyof B]: {
6
- [K in keyof B[Mode]]: Action
7
- }
8
- }
9
-
10
- export type Sample = [code: string, value: number]
11
- export type SampleMap = Map<string, number>
12
-
13
2
  export type Timing = (
14
3
  | DirectTiming
15
4
  | TapTiming
@@ -32,11 +21,6 @@ export type Lens = {
32
21
  settings?: Partial<LensSettings>
33
22
  }
34
23
 
35
- export type LensState = {
36
- lastValue: number
37
- holdStart: number
38
- }
39
-
40
24
  export type Spoon = {
41
25
  lenses: Lens[]
42
26
  required?: Lens[]
@@ -59,14 +43,14 @@ export function asBindings<B extends Bindings>(bindings: B) {
59
43
  return bindings
60
44
  }
61
45
 
62
- export const switchboardMode = "switchboard" as const
46
+ export const hubMode = "hub" as const
63
47
 
64
- export type AsSwitchboardBindings<B extends Bindings> = {
65
- [switchboardMode]: {
48
+ export type AsHubBindings<B extends Bindings> = {
49
+ [hubMode]: {
66
50
  shimmyNext: Spoon[],
67
51
  shimmyPrevious: Spoon[],
68
52
  }
69
53
  } & B
70
54
 
71
- export type SwitchboardBindings = AsSwitchboardBindings<Bindings>
55
+ export type HubBindings = AsHubBindings<Bindings>
72
56
 
@@ -0,0 +1,7 @@
1
+
2
+ import {Sample} from "./types.js"
3
+
4
+ export abstract class Controller {
5
+ abstract takeSamples(): Sample[]
6
+ }
7
+
@@ -0,0 +1,17 @@
1
+
2
+ import {SetG} from "@e280/stz"
3
+ import {Controller} from "../controller.js"
4
+
5
+ export class GroupController extends Controller {
6
+ controllers = new SetG<Controller>()
7
+
8
+ constructor(...controllers: Controller[]) {
9
+ super()
10
+ this.controllers.adds(...controllers)
11
+ }
12
+
13
+ takeSamples() {
14
+ return [...this.controllers].flatMap(controller => controller.takeSamples())
15
+ }
16
+ }
17
+
@@ -1,9 +1,9 @@
1
1
 
2
2
  import {sub} from "@e280/stz"
3
- import {Device} from "./device.js"
4
- import {Sample, SampleMap} from "../../types.js"
3
+ import {Controller} from "../controller.js"
4
+ import {Sample, SampleMap} from "../types.js"
5
5
 
6
- export class SamplerDevice extends Device {
6
+ export class SamplerController extends Controller {
7
7
  on = sub<Sample>()
8
8
  #map: SampleMap = new Map()
9
9
 
@@ -1,8 +1,8 @@
1
1
 
2
- import {tmax} from "../utils/tmax.js"
3
- import {SamplerDevice} from "./infra/sampler.js"
4
- import {splitAxis} from "../../utils/split-axis.js"
5
- import {gamepads, Pad} from "../../utils/gamepads.js"
2
+ import {tmax} from "../../../utils/quick-math.js"
3
+ import {splitAxis} from "../../../utils/split-axis.js"
4
+ import {SamplerController} from "../infra/sampler.js"
5
+ import {gamepads, Pad} from "../../../utils/gamepads.js"
6
6
 
7
7
  const gamepadButtonCodes = [
8
8
  "gamepad.a",
@@ -24,8 +24,8 @@ const gamepadButtonCodes = [
24
24
  "gamepad.gamma",
25
25
  ]
26
26
 
27
- export class GamepadDevice extends SamplerDevice {
28
- static on(fn: (device: GamepadDevice) => () => void) {
27
+ export class GamepadController extends SamplerController {
28
+ static on(fn: (controller: GamepadController) => () => void) {
29
29
  return gamepads(pad => fn(new this(pad)))
30
30
  }
31
31
 
@@ -0,0 +1,7 @@
1
+
2
+ export * from "./gamepad.js"
3
+ export * from "./keyboard.js"
4
+ export * from "./pointer.js"
5
+ export * from "./stick.js"
6
+ export * from "./virtual-gamepad.js"
7
+
@@ -1,15 +1,15 @@
1
1
 
2
2
  import {coalesce, ev, sub} from "@e280/stz"
3
3
  import {Sample} from "../types.js"
4
- import {Device} from "./infra/device.js"
4
+ import {Controller} from "../controller.js"
5
5
  import {modprefix} from "../utils/modprefix.js"
6
6
 
7
- export class KeyboardDevice extends Device {
7
+ export class KeyboardController extends Controller {
8
8
  on = sub<Sample>()
9
9
  dispose: () => void
10
10
  #held = new Set<string>()
11
11
 
12
- constructor(target: EventTarget) {
12
+ constructor(target: EventTarget = window) {
13
13
  super()
14
14
 
15
15
  const down = (code: string) => {