brilliantsole 0.0.27 → 0.0.28

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 (167) hide show
  1. package/assets/3d/anchor.glb +0 -0
  2. package/assets/3d/coin.glb +0 -0
  3. package/assets/3d/glasses.glb +0 -0
  4. package/assets/audio/bounceMedium.wav +0 -0
  5. package/assets/audio/bounceStrong.wav +0 -0
  6. package/assets/audio/bounceWeak.wav +0 -0
  7. package/assets/audio/coin.wav +0 -0
  8. package/assets/audio/getUp.wav +0 -0
  9. package/assets/audio/grab.wav +0 -0
  10. package/assets/audio/kick.wav +0 -0
  11. package/assets/audio/platterFadeIn old.wav +0 -0
  12. package/assets/audio/platterFadeIn.wav +0 -0
  13. package/assets/audio/platterFadeOut.wav +0 -0
  14. package/assets/audio/punch.wav +0 -0
  15. package/assets/audio/punchSqueak.wav +0 -0
  16. package/assets/audio/purr.wav +0 -0
  17. package/assets/audio/purrFadeOut.wav +0 -0
  18. package/assets/audio/release.wav +0 -0
  19. package/assets/audio/splat.wav +0 -0
  20. package/assets/audio/stomp.wav +0 -0
  21. package/build/brilliantsole.cjs +2627 -775
  22. package/build/brilliantsole.cjs.map +1 -1
  23. package/build/brilliantsole.js +2273 -721
  24. package/build/brilliantsole.js.map +1 -1
  25. package/build/brilliantsole.ls.js +2096 -535
  26. package/build/brilliantsole.ls.js.map +1 -1
  27. package/build/brilliantsole.min.js +1 -1
  28. package/build/brilliantsole.min.js.map +1 -1
  29. package/build/brilliantsole.module.d.ts +235 -65
  30. package/build/brilliantsole.module.js +2266 -722
  31. package/build/brilliantsole.module.js.map +1 -1
  32. package/build/brilliantsole.module.min.d.ts +235 -65
  33. package/build/brilliantsole.module.min.js +1 -1
  34. package/build/brilliantsole.module.min.js.map +1 -1
  35. package/build/brilliantsole.node.module.d.ts +229 -62
  36. package/build/brilliantsole.node.module.js +2619 -776
  37. package/build/brilliantsole.node.module.js.map +1 -1
  38. package/build/dts/BS-output.d.ts +10 -0
  39. package/build/dts/BS.d.ts +20 -8
  40. package/build/dts/CameraManager.d.ts +72 -0
  41. package/build/dts/Device.d.ts +46 -13
  42. package/build/dts/DeviceInformationManager.d.ts +4 -4
  43. package/build/dts/DeviceManager.d.ts +2 -0
  44. package/build/dts/FileTransferManager.d.ts +18 -8
  45. package/build/dts/InformationManager.d.ts +2 -0
  46. package/build/dts/TfliteManager.d.ts +22 -2
  47. package/build/dts/WifiManager.d.ts +61 -0
  48. package/build/dts/connection/BaseConnectionManager.d.ts +35 -3
  49. package/build/dts/connection/ClientConnectionManager.d.ts +7 -2
  50. package/build/dts/connection/bluetooth/NobleConnectionManager.d.ts +2 -1
  51. package/build/dts/connection/bluetooth/WebBluetoothConnectionManager.d.ts +1 -0
  52. package/build/dts/connection/bluetooth/bluetoothUUIDs.d.ts +2 -2
  53. package/build/dts/connection/udp/UDPConnectionManager.d.ts +28 -0
  54. package/build/dts/connection/webSocket/WebSocketConnectionManager.d.ts +25 -0
  55. package/build/dts/devicePair/DevicePair.d.ts +5 -5
  56. package/build/dts/scanner/BaseScanner.d.ts +4 -1
  57. package/build/dts/scanner/NobleScanner.d.ts +2 -1
  58. package/build/dts/sensor/MotionSensorDataManager.d.ts +5 -2
  59. package/build/dts/sensor/SensorDataManager.d.ts +5 -4
  60. package/build/dts/server/BaseClient.d.ts +5 -3
  61. package/build/dts/server/ServerUtils.d.ts +1 -1
  62. package/build/dts/server/websocket/WebSocketUtils.d.ts +1 -1
  63. package/build/dts/utils/Console.d.ts +2 -0
  64. package/build/dts/utils/ThrottleUtils.d.ts +2 -0
  65. package/build/dts/vibration/VibrationManager.d.ts +19 -2
  66. package/build/index.d.ts +232 -62
  67. package/build/index.node.d.ts +226 -59
  68. package/examples/3d/scene.html +19 -5
  69. package/examples/3d-generic/index.html +144 -0
  70. package/examples/3d-generic/script.js +266 -0
  71. package/examples/basic/index.html +211 -16
  72. package/examples/basic/script.js +731 -105
  73. package/examples/edge-impulse/script.js +135 -44
  74. package/examples/edge-impulse-test/README.md +11 -0
  75. package/examples/edge-impulse-test/edge-impulse-standalone.js +7228 -0
  76. package/examples/edge-impulse-test/edge-impulse-standalone.wasm +0 -0
  77. package/examples/edge-impulse-test/index.html +75 -0
  78. package/examples/edge-impulse-test/run-impulse.js +135 -0
  79. package/examples/edge-impulse-test/script.js +200 -0
  80. package/examples/gloves/edge-impulse-standalone.js +7228 -0
  81. package/examples/gloves/edge-impulse-standalone.wasm +0 -0
  82. package/examples/gloves/index.html +4 -1
  83. package/examples/gloves/run-impulse.js +135 -0
  84. package/examples/gloves/script.js +367 -51
  85. package/examples/graph/script.js +94 -37
  86. package/examples/punch/index.html +135 -0
  87. package/examples/punch/punch.tflite +0 -0
  88. package/examples/punch/script.js +169 -0
  89. package/examples/server/index.html +98 -22
  90. package/examples/server/script.js +317 -109
  91. package/examples/ukaton-firmware-update/merged-firmware.bin +0 -0
  92. package/examples/utils/aframe/aframe-master.min.js +2 -0
  93. package/examples/utils/aframe/bs-vibration.js +150 -0
  94. package/examples/utils/aframe/force-pushable.js +80 -0
  95. package/examples/utils/aframe/grabbable-anchor.js +46 -0
  96. package/examples/utils/aframe/grabbable-listener.js +31 -0
  97. package/examples/utils/aframe/grabbable-physics-body.js +190 -0
  98. package/examples/utils/aframe/grow-shrink.js +25 -0
  99. package/examples/utils/aframe/hand-punch.js +119 -0
  100. package/examples/utils/aframe/my-obb-collider.js +293 -0
  101. package/examples/utils/aframe/occlude-hand-tracking-controls.js +47 -0
  102. package/examples/utils/aframe/occlude-mesh.js +42 -0
  103. package/examples/utils/aframe/palm-up-detector.js +47 -0
  104. package/examples/utils/aframe/shadow-material.js +20 -0
  105. package/examples/utils/aframe/soft-shadow-light.js +9 -0
  106. package/examples/webxr-2/assets/3d/soccerBall.glb +0 -0
  107. package/examples/webxr-2/assets/audio/shellBounce.wav +0 -0
  108. package/examples/webxr-2/assets/audio/shellHit.wav +0 -0
  109. package/examples/webxr-2/assets/audio/shellKick.wav +0 -0
  110. package/examples/webxr-2/assets/audio/soccerBounce.wav +0 -0
  111. package/examples/webxr-2/assets/audio/soccerKick.mp3 +0 -0
  112. package/examples/webxr-2/assets/images/shellTexture.png +0 -0
  113. package/examples/webxr-2/components/bs-ankle.js +337 -0
  114. package/examples/webxr-2/components/coin.js +84 -0
  115. package/examples/webxr-2/components/custom-wrap.js +17 -0
  116. package/examples/webxr-2/components/goomba.js +3250 -0
  117. package/examples/webxr-2/components/init-shell-material.js +215 -0
  118. package/examples/webxr-2/components/platter.js +172 -0
  119. package/examples/webxr-2/components/shell.js +374 -0
  120. package/examples/webxr-2/components/soccer-ball.js +250 -0
  121. package/examples/webxr-2/components/squashed-goomba.js +249 -0
  122. package/examples/webxr-2/edge-impulse-standalone.js +7228 -0
  123. package/examples/webxr-2/edge-impulse-standalone.wasm +0 -0
  124. package/examples/webxr-2/index.html +996 -0
  125. package/examples/webxr-2/kick.tflite +0 -0
  126. package/examples/webxr-2/kick2.tflite +0 -0
  127. package/examples/webxr-2/run-impulse.js +135 -0
  128. package/examples/webxr-2/script.js +384 -0
  129. package/package.json +2 -1
  130. package/src/.prettierrc +4 -0
  131. package/src/BS.ts +70 -8
  132. package/src/CameraManager.ts +499 -0
  133. package/src/Device.ts +581 -86
  134. package/src/DeviceInformationManager.ts +19 -10
  135. package/src/DeviceManager.ts +85 -25
  136. package/src/FileTransferManager.ts +145 -20
  137. package/src/InformationManager.ts +40 -15
  138. package/src/TfliteManager.ts +171 -25
  139. package/src/WifiManager.ts +323 -0
  140. package/src/connection/BaseConnectionManager.ts +128 -30
  141. package/src/connection/ClientConnectionManager.ts +34 -10
  142. package/src/connection/bluetooth/BluetoothConnectionManager.ts +8 -2
  143. package/src/connection/bluetooth/NobleConnectionManager.ts +147 -41
  144. package/src/connection/bluetooth/WebBluetoothConnectionManager.ts +99 -34
  145. package/src/connection/bluetooth/bluetoothUUIDs.ts +40 -13
  146. package/src/connection/udp/UDPConnectionManager.ts +356 -0
  147. package/src/connection/websocket/WebSocketConnectionManager.ts +282 -0
  148. package/src/devicePair/DevicePair.ts +95 -25
  149. package/src/devicePair/DevicePairPressureSensorDataManager.ts +27 -7
  150. package/src/scanner/BaseScanner.ts +49 -11
  151. package/src/scanner/NobleScanner.ts +76 -14
  152. package/src/sensor/MotionSensorDataManager.ts +21 -6
  153. package/src/sensor/PressureSensorDataManager.ts +37 -8
  154. package/src/sensor/SensorConfigurationManager.ts +73 -22
  155. package/src/sensor/SensorDataManager.ts +104 -23
  156. package/src/server/BaseClient.ts +150 -36
  157. package/src/server/BaseServer.ts +50 -2
  158. package/src/server/ServerUtils.ts +39 -9
  159. package/src/server/udp/UDPServer.ts +73 -22
  160. package/src/server/udp/UDPUtils.ts +9 -2
  161. package/src/server/websocket/WebSocketClient.ts +27 -7
  162. package/src/server/websocket/WebSocketUtils.ts +4 -2
  163. package/src/utils/Console.ts +62 -9
  164. package/src/utils/ParseUtils.ts +24 -5
  165. package/src/utils/ThrottleUtils.ts +62 -0
  166. package/src/utils/Timer.ts +1 -1
  167. package/src/vibration/VibrationManager.ts +166 -40
@@ -0,0 +1,374 @@
1
+ AFRAME.registerComponent("shell", {
2
+ schema: {
3
+ template: { default: "#shellTemplate", type: "selector" },
4
+ kickSoundSelector: { default: "#shellKickAudio" },
5
+ bounceSoundSelector: { default: "#shellBounceAudio" },
6
+ },
7
+
8
+ collisionFilterGroup: 1 << 2,
9
+ collisionFilterMask: (1 << 0) | (1 << 2),
10
+
11
+ shapeMain: `shape: cylinder;
12
+ radiusTop: 0.12;
13
+ radiusBottom: 0.12;
14
+ height: 0.12;
15
+ offset: 0 0.01 0;
16
+ `,
17
+
18
+ init: function () {
19
+ this.yaw = 0;
20
+ window.shells = window.shells || [];
21
+ window.shells.push(this);
22
+
23
+ this.el.classList.add("lookAt");
24
+
25
+ this.camera = document.querySelector("a-camera");
26
+
27
+ this.el.shapeMain = this.shapeMain;
28
+
29
+ this.kickVelocity = new THREE.Vector3();
30
+ this.kickEuler = new THREE.Euler();
31
+
32
+ this.collisionNormal = new THREE.Vector3();
33
+ this.velocityVector = new THREE.Vector3();
34
+
35
+ this.velocity2D = new THREE.Vector3();
36
+
37
+ this.quaternion = new THREE.Quaternion();
38
+ this.euler = new THREE.Euler();
39
+ this.releaseEuler = new THREE.Euler();
40
+ this.releaseQuaternion = new THREE.Quaternion();
41
+
42
+ this.spinQuaternion = new THREE.Quaternion();
43
+ this.spinEuler = new THREE.Euler();
44
+
45
+ this.targetEuler = new THREE.Quaternion();
46
+ this.targetQuaternion = new THREE.Quaternion();
47
+
48
+ this.el.addEventListener("kick", this.onKick.bind(this));
49
+ this.el.addEventListener("stomp", this.onStomp.bind(this));
50
+
51
+ this.setGrabEnabled = AFRAME.utils.throttleLeadingAndTrailing(
52
+ this.setGrabEnabled.bind(this),
53
+ 70
54
+ );
55
+
56
+ this.checkVelocity = AFRAME.utils.throttle(
57
+ this.checkVelocity.bind(this),
58
+ 100
59
+ );
60
+
61
+ this.el.addEventListener("grabstarted", () => this.setGrabEnabled(true));
62
+ this.el.addEventListener("grabended", () => this.setGrabEnabled(false));
63
+
64
+ this.el.addEventListener("collide", this.onCollide.bind(this));
65
+ this.el.addEventListener(
66
+ "obbcollisionstarted",
67
+ this.onObbCollisionStarted.bind(this)
68
+ );
69
+
70
+ this.el.addEventListener("toss", this.onToss.bind(this));
71
+
72
+ this.el.addEventListener("body-loaded", this.onBodyLoaded.bind(this));
73
+ this.el.addEventListener("loaded", () => {
74
+ const template = this.data.template.content
75
+ .querySelector("a-entity")
76
+ .cloneNode(true);
77
+ this.el.setAttribute("scale", template.getAttribute("scale"));
78
+
79
+ template.classList.forEach((_class) => {
80
+ //console.log(`adding class ${_class}`);
81
+ this.el.classList.add(_class);
82
+ });
83
+ Array.from(template.children).forEach((entity) => {
84
+ this.el.appendChild(entity);
85
+ });
86
+ setTimeout(() => {
87
+ this.bodyEl = this.el.querySelector(".body");
88
+ this.bodyEl.addEventListener(
89
+ "animationcomplete",
90
+ this.onAnimationComplete.bind(this)
91
+ );
92
+ this.el.setAttribute("grabbable", "");
93
+ this.el.setAttribute(
94
+ "grabbable-physics-body",
95
+ `type: dynamic; enable-angular-velocity: false;`
96
+ );
97
+ }, 1);
98
+ });
99
+
100
+ this.kickSound = document.createElement("a-entity");
101
+ this.kickSound.setAttribute("sound", `src: ${this.data.kickSoundSelector}`);
102
+ this.el.sceneEl.appendChild(this.kickSound);
103
+
104
+ this.bounceSound = document.createElement("a-entity");
105
+ this.bounceSound.setAttribute(
106
+ "sound",
107
+ `src: ${this.data.bounceSoundSelector}`
108
+ );
109
+ this.el.sceneEl.appendChild(this.bounceSound);
110
+
111
+ this.playBounceSound = AFRAME.utils.throttle(
112
+ this.playBounceSound.bind(this),
113
+ 50
114
+ );
115
+ },
116
+
117
+ onAnimationComplete: function (event) {},
118
+
119
+ onToss: function (event) {
120
+ // console.log("toss", event);
121
+ const { velocity, angularVelocity } = event.detail;
122
+ },
123
+
124
+ setGrabEnabled: function (enabled) {
125
+ if (enabled) {
126
+ this.onGrabStarted();
127
+ } else {
128
+ this.onGrabEnded();
129
+ }
130
+ },
131
+ onGrabStarted: function () {
132
+ // console.log("onGrabStarted");
133
+ this.isGrabbed = true;
134
+ },
135
+ onGrabEnded: function () {
136
+ // console.log("onGrabEnded");
137
+ this.isGrabbed = false;
138
+ },
139
+
140
+ worldBasis: {
141
+ forward: new THREE.Vector3(0, 0, 1),
142
+ up: new THREE.Vector3(0, 1, 0),
143
+ right: new THREE.Vector3(1, 0, 0),
144
+ },
145
+
146
+ collisionAngleThreshold: THREE.MathUtils.degToRad(20),
147
+ collisionVelocityThreshold: 0.1,
148
+ onCollide: async function (event) {
149
+ const { contact } = event.detail;
150
+ const collidedEntity = event.detail.body.el;
151
+ //console.log("collided with", collidedEntity);
152
+ const worldMesh = collidedEntity.dataset.worldMesh;
153
+ if (worldMesh) {
154
+ let playBounce = false;
155
+ if (worldMesh == "wall") {
156
+ playBounce = true;
157
+ } else {
158
+ this.collisionNormal.copy(contact.ni);
159
+ if (contact.bi != this.body) {
160
+ this.collisionNormal.multiplyScalar(-1);
161
+ }
162
+ this.velocityVector.copy(this.body.velocity);
163
+ const angle = this.collisionNormal.angleTo(this.velocityVector);
164
+ const velocityLength = this.velocityVector.length();
165
+ playBounce =
166
+ angle < this.collisionAngleThreshold &&
167
+ velocityLength > this.collisionVelocityThreshold;
168
+ if (!playBounce) {
169
+ // console.log({ angle, velocityLength, playBounce });
170
+ }
171
+ }
172
+
173
+ if (playBounce) {
174
+ this.playBounceSound();
175
+ }
176
+ }
177
+ },
178
+
179
+ playBounceSound: function () {
180
+ this.bounceSound.object3D.position.copy(this.el.object3D.position);
181
+ this.bounceSound.components.sound.playSound();
182
+ },
183
+ playKickSound: function () {
184
+ this.kickSound.object3D.position.copy(this.el.object3D.position);
185
+ this.kickSound.components.sound.playSound();
186
+ },
187
+
188
+ onKick: function (event) {
189
+ if (this.isGrabbed || !this.body) {
190
+ return;
191
+ }
192
+ const { velocity, yaw } = event.detail;
193
+ // console.log("onKick", yaw);
194
+ this.playKickSound();
195
+ this.kickVelocity.set(0, 1, -3.5);
196
+ this.kickEuler.set(0, yaw, 0);
197
+ this.kickVelocity.applyEuler(this.kickEuler);
198
+ this.body.velocity.copy(this.kickVelocity);
199
+ },
200
+ onStomp: function (event) {
201
+ if (this.isGrabbed || !this.body) {
202
+ return;
203
+ }
204
+
205
+ const { distance, yaw, kill } = event.detail;
206
+ // console.log("onStomp", { distance, yaw, kill });
207
+
208
+ this.playKickSound();
209
+
210
+ this.kickVelocity.set(0, 3, 0);
211
+ this.kickEuler.set(0, -yaw, 0);
212
+ this.kickVelocity.applyEuler(this.kickEuler);
213
+ this.body.velocity.copy(this.kickVelocity);
214
+ //this.body.velocity.set(0, 2, 0);
215
+
216
+ this.isStomped = true;
217
+ this.stompStartTime = this.latestTick;
218
+ this.stompFinishTime = this.stompStartTime + this.stompDuration;
219
+ },
220
+
221
+ onObbCollisionStarted: async function (event) {
222
+ if (!this.body) {
223
+ return;
224
+ }
225
+ if (this.isGrabbed) {
226
+ return;
227
+ }
228
+ const velocity = this.body.velocity.clone();
229
+ // TODO: - should it kill a goomba if not moving?
230
+ const collidedEntity = event.detail.withEl;
231
+ const goomba = collidedEntity.components["goomba"];
232
+ if (goomba) {
233
+ goomba.el.emit("shell", {
234
+ velocity,
235
+ position: this.el.object3D.position,
236
+ });
237
+ }
238
+ },
239
+
240
+ onBodyLoaded: function (event) {
241
+ const { body } = event.detail;
242
+ body.collisionFilterGroup = this.collisionFilterGroup;
243
+ body.collisionFilterMask = this.collisionFilterMask;
244
+ // console.log("body", body);
245
+ this.body = body;
246
+ if (this.manualRotate) {
247
+ body.fixedRotation = true;
248
+ body.updateMassProperties();
249
+ }
250
+ body.linearDamping = 0;
251
+ body.angularDamping = 0;
252
+ body.material =
253
+ this.el.sceneEl.systems["physics"].driver.getMaterial("shell");
254
+ if (!this.manualRotate) {
255
+ body.angularVelocity.set(0, 10, 0);
256
+ }
257
+
258
+ this.releaseQuaternion.copy(this.el.object3D.quaternion);
259
+ this.releaseEuler.copy(this.el.object3D.rotation);
260
+ this.releaseTime = this.latestTick;
261
+ this.restoredRotationTime = this.releaseTime + this.restoreRotationDuration;
262
+ this.didRestoreRotation = false;
263
+ },
264
+
265
+ spinScalar: 0.01,
266
+ manualRotate: true,
267
+ restoreRotationDuration: 200,
268
+
269
+ speedMax: 5,
270
+
271
+ checkVelocity: function () {
272
+ if (this.body.velocity.length() > this.speedMax) {
273
+ console.log("speed too fast");
274
+ this.velocityVector.copy(this.body.velocity);
275
+ this.velocityVector.setLength(this.speedMax - 1);
276
+ this.body.velocity.copy(this.velocityVector);
277
+ }
278
+ },
279
+
280
+ stompScalars: { pitch: 0.4, roll: 0.4 },
281
+ stompDelay: { pitch: 0, roll: 0 },
282
+ stompInterpolationOffsets: { pitch: 0, roll: 0.25 },
283
+ stompInterpolationScalars: { pitch: 1.75, roll: 1.75 },
284
+ stompDuration: 700,
285
+
286
+ tick: function (time, timeDelta) {
287
+ this.latestTick = time;
288
+
289
+ if (!this.isGrabbed && this.body) {
290
+ this.checkVelocity();
291
+ }
292
+
293
+ if (!this.isGrabbed && this.body && this.manualRotate) {
294
+ this.velocity2D.copy(this.body.velocity);
295
+ this.velocity2D.y = 0;
296
+ const spinSpeed = this.velocity2D.length() * this.spinScalar;
297
+ this.yaw += timeDelta * spinSpeed;
298
+ this.yaw %= 2 * Math.PI;
299
+ this.spinEuler.set(0, this.yaw, 0);
300
+ //this.spinQuaternion.setFromEuler(this.spinEuler);
301
+
302
+ if (!this.didRestoreRotation) {
303
+ let interpolation = THREE.MathUtils.inverseLerp(
304
+ this.releaseTime,
305
+ this.restoredRotationTime,
306
+ this.latestTick
307
+ );
308
+ interpolation = THREE.MathUtils.clamp(interpolation, 0, 1);
309
+ this.quaternion.slerpQuaternions(
310
+ this.releaseQuaternion,
311
+ this.targetQuaternion,
312
+ interpolation
313
+ );
314
+ if (interpolation >= 1) {
315
+ this.didRestoreRotation = true;
316
+ }
317
+ }
318
+
319
+ if (this.manualRotate && !this.isStomped) {
320
+ this.bodyEl.object3D.rotation.copy(this.spinEuler);
321
+ //this.quaternion.multiply(this.spinQuaternion);
322
+ this.body.quaternion.copy(this.quaternion);
323
+ }
324
+
325
+ if (this.isStomped) {
326
+ let interpolation = THREE.MathUtils.inverseLerp(
327
+ this.stompStartTime,
328
+ this.stompFinishTime,
329
+ this.latestTick
330
+ );
331
+ interpolation = THREE.MathUtils.clamp(interpolation, 0, 1);
332
+
333
+ let pitchInterpolation =
334
+ this.stompInterpolationScalars.pitch * interpolation +
335
+ this.stompInterpolationOffsets.pitch;
336
+ pitchInterpolation = THREE.MathUtils.clamp(pitchInterpolation, 0, 1);
337
+
338
+ let rollInterpolation =
339
+ this.stompInterpolationScalars.roll * interpolation +
340
+ this.stompInterpolationOffsets.roll;
341
+ rollInterpolation = THREE.MathUtils.clamp(rollInterpolation, 0, 1);
342
+
343
+ const pitch =
344
+ Math.sin(pitchInterpolation * 2 * Math.PI) *
345
+ this.stompScalars.pitch *
346
+ (1 - interpolation);
347
+ const roll =
348
+ Math.sin(rollInterpolation * 2 * Math.PI) *
349
+ this.stompScalars.roll *
350
+ (1 - interpolation);
351
+
352
+ console.log({ pitch, roll });
353
+
354
+ this.spinEuler.set(pitch, this.yaw, roll);
355
+ this.bodyEl.object3D.rotation.copy(this.spinEuler);
356
+
357
+ if (interpolation >= 1) {
358
+ console.log("finished stomp animation");
359
+ this.isStomped = false;
360
+ }
361
+ }
362
+
363
+ if (this.el.object3D.position.y < -10) {
364
+ console.log("fell through floor");
365
+ this.body.velocity.set(0, 0, 0);
366
+ this.body.position.copy(this.camera.object3D.position);
367
+ }
368
+ }
369
+ },
370
+
371
+ remove: function () {
372
+ this.removeSelf();
373
+ },
374
+ });
@@ -0,0 +1,250 @@
1
+ AFRAME.registerComponent("soccer-ball", {
2
+ schema: {
3
+ template: { default: "#soccerTemplate", type: "selector" },
4
+ kickSoundSelector: { default: "#soccerKickAudio" },
5
+ bounceSoundSelector: { default: "#soccerBounceAudio" },
6
+ },
7
+
8
+ collisionFilterGroup: 1 << 2,
9
+ collisionFilterMask: (1 << 0) | (1 << 2),
10
+
11
+ shapeMain: `shape: sphere; radius: 0.112;`,
12
+
13
+ init: function () {
14
+ window.soccerBalls = window.soccerBalls || [];
15
+ window.soccerBalls.push(this);
16
+
17
+ this.el.shapeMain = this.shapeMain;
18
+
19
+ this.el.classList.add("lookAt");
20
+
21
+ this.camera = document.querySelector("a-camera");
22
+
23
+ this.kickVelocity = new THREE.Vector3();
24
+ this.kickEuler = new THREE.Euler();
25
+
26
+ this.collisionNormal = new THREE.Vector3();
27
+ this.velocityVector = new THREE.Vector3();
28
+
29
+ this.el.addEventListener("kick", this.onKick.bind(this));
30
+ this.el.addEventListener("stomp", this.onStomp.bind(this));
31
+
32
+ this.setGrabEnabled = AFRAME.utils.throttleLeadingAndTrailing(
33
+ this.setGrabEnabled.bind(this),
34
+ 70
35
+ );
36
+
37
+ this.el.addEventListener("grabstarted", () => this.setGrabEnabled(true));
38
+ this.el.addEventListener("grabended", () => this.setGrabEnabled(false));
39
+
40
+ this.el.addEventListener("collide", this.onCollide.bind(this));
41
+ this.el.addEventListener(
42
+ "obbcollisionstarted",
43
+ this.onObbCollisionStarted.bind(this)
44
+ );
45
+
46
+ this.el.addEventListener("toss", this.onToss.bind(this));
47
+
48
+ this.el.addEventListener("body-loaded", this.onBodyLoaded.bind(this));
49
+ this.el.addEventListener("loaded", () => {
50
+ const template = this.data.template.content
51
+ .querySelector("a-entity")
52
+ .cloneNode(true);
53
+ this.el.setAttribute("scale", template.getAttribute("scale"));
54
+
55
+ template.classList.forEach((_class) => {
56
+ //console.log(`adding class ${_class}`);
57
+ this.el.classList.add(_class);
58
+ });
59
+ Array.from(template.children).forEach((entity) => {
60
+ this.el.appendChild(entity);
61
+ });
62
+ setTimeout(() => {
63
+ this.bodyEl = this.el.querySelector(".body");
64
+ this.el.setAttribute("grabbable", "");
65
+ this.el.setAttribute("grabbable-physics-body", `type: dynamic; `);
66
+ }, 1);
67
+ });
68
+
69
+ this.kickSound = document.createElement("a-entity");
70
+ this.kickSound.setAttribute("sound", `src: ${this.data.kickSoundSelector}`);
71
+ this.el.sceneEl.appendChild(this.kickSound);
72
+
73
+ this.bounceSound = document.createElement("a-entity");
74
+ this.bounceSound.setAttribute(
75
+ "sound",
76
+ `src: ${this.data.bounceSoundSelector}`
77
+ );
78
+ this.el.sceneEl.appendChild(this.bounceSound);
79
+
80
+ this.playBounceSound = AFRAME.utils.throttle(
81
+ this.playBounceSound.bind(this),
82
+ 200
83
+ );
84
+ },
85
+
86
+ onAnimationComplete: function (event) {},
87
+
88
+ onToss: function (event) {
89
+ // console.log("toss", event);
90
+ const { velocity, angularVelocity } = event.detail;
91
+ },
92
+
93
+ setGrabEnabled: function (enabled) {
94
+ if (enabled) {
95
+ this.onGrabStarted();
96
+ } else {
97
+ this.onGrabEnded();
98
+ }
99
+ },
100
+ onGrabStarted: function () {
101
+ // console.log("onGrabStarted");
102
+ this.isGrabbed = true;
103
+ },
104
+ onGrabEnded: function () {
105
+ // console.log("onGrabEnded");
106
+ this.isGrabbed = false;
107
+ },
108
+
109
+ worldBasis: {
110
+ forward: new THREE.Vector3(0, 0, 1),
111
+ up: new THREE.Vector3(0, 1, 0),
112
+ right: new THREE.Vector3(1, 0, 0),
113
+ },
114
+
115
+ collisionAngleThreshold: THREE.MathUtils.degToRad(20),
116
+ collisionVelocityThreshold: 0.4,
117
+ collisionVelocityVolumeScalar: 1,
118
+ onCollide: async function (event) {
119
+ const { contact } = event.detail;
120
+ const collidedEntity = event.detail.body.el;
121
+ //console.log("collided with", collidedEntity);
122
+ const worldMesh = collidedEntity.dataset.worldMesh;
123
+ let volume = 1;
124
+ if (worldMesh || collidedEntity.components.shell) {
125
+ let playBounce = false;
126
+ if (worldMesh == "wall") {
127
+ playBounce = true;
128
+ } else {
129
+ this.collisionNormal.copy(contact.ni);
130
+ if (contact.bi != this.body) {
131
+ this.collisionNormal.multiplyScalar(-1);
132
+ }
133
+ this.velocityVector.copy(this.body.velocity);
134
+ const angle = this.collisionNormal.angleTo(this.velocityVector);
135
+ const velocityLength = this.velocityVector.length();
136
+ playBounce =
137
+ angle < this.collisionAngleThreshold &&
138
+ velocityLength > this.collisionVelocityThreshold;
139
+ if (playBounce) {
140
+ volume = velocityLength * this.collisionVelocityVolumeScalar;
141
+ }
142
+ }
143
+
144
+ if (playBounce) {
145
+ this.playBounceSound(volume);
146
+ }
147
+ }
148
+ },
149
+
150
+ playBounceSound: function (volume = 1) {
151
+ this.bounceSound.components.sound.stopSound();
152
+ this.bounceSound.components.sound.pool.children[0].setVolume(volume);
153
+ this.bounceSound.object3D.position.copy(this.el.object3D.position);
154
+ this.bounceSound.components.sound.playSound();
155
+ },
156
+ playKickSound: function () {
157
+ this.kickSound.components.sound.stopSound();
158
+ this.kickSound.components.sound.pool.children[0].setVolume(4);
159
+ this.kickSound.object3D.position.copy(this.el.object3D.position);
160
+ this.kickSound.components.sound.playSound();
161
+ },
162
+
163
+ kickHeightRange: { min: 1, max: 4 },
164
+ onKick: function (event) {
165
+ if (this.isGrabbed || !this.body) {
166
+ return;
167
+ }
168
+ const { velocity, yaw } = event.detail;
169
+ // console.log("onKick", yaw);
170
+ this.playKickSound();
171
+ const kickHeight = THREE.MathUtils.lerp(
172
+ this.kickHeightRange.min,
173
+ this.kickHeightRange.max,
174
+ Math.random()
175
+ );
176
+ this.kickVelocity.set(0, kickHeight, -5);
177
+ this.kickEuler.set(0, yaw, 0);
178
+ this.kickVelocity.applyEuler(this.kickEuler);
179
+ this.body.velocity.copy(this.kickVelocity);
180
+ },
181
+ onStomp: function (event) {
182
+ if (this.isGrabbed || !this.body) {
183
+ return;
184
+ }
185
+
186
+ const { distance, yaw, kill } = event.detail;
187
+ // console.log("onStomp", { distance, yaw, kill });
188
+
189
+ console.log({ yaw });
190
+
191
+ this.kickVelocity.set(0, 4, 0);
192
+ this.kickEuler.set(0, yaw, 0);
193
+ this.kickVelocity.applyEuler(this.kickEuler);
194
+ this.body.velocity.copy(this.kickVelocity);
195
+
196
+ const strength = this.kickVelocity.length();
197
+ const angularVelocity = new THREE.Vector3(strength * 0.8, 0, 0);
198
+ angularVelocity.applyEuler(this.kickEuler);
199
+ // console.log("angularVelocity", angularVelocity);
200
+ this.body.angularVelocity.set(...angularVelocity.toArray());
201
+ },
202
+
203
+ onObbCollisionStarted: async function (event) {
204
+ if (!this.body) {
205
+ return;
206
+ }
207
+ if (this.isGrabbed) {
208
+ return;
209
+ }
210
+ const velocity = this.body.velocity.clone();
211
+ // TODO: - should it kill a goomba if not moving?
212
+ const collidedEntity = event.detail.withEl;
213
+ const goomba = collidedEntity.components["goomba"];
214
+ if (goomba) {
215
+ goomba.el.emit("shell", {
216
+ velocity,
217
+ position: this.el.object3D.position,
218
+ });
219
+ }
220
+ },
221
+
222
+ onBodyLoaded: function (event) {
223
+ const { body } = event.detail;
224
+ // body.mass = 1;
225
+ body.collisionFilterGroup = this.collisionFilterGroup;
226
+ body.collisionFilterMask = this.collisionFilterMask;
227
+ // console.log("body", body);
228
+ this.body = body;
229
+ body.linearDamping = 0.15;
230
+ body.angularDamping = 0.4;
231
+ body.material =
232
+ this.el.sceneEl.systems["physics"].driver.getMaterial("soccerBall");
233
+ },
234
+
235
+ tick: function (time, timeDelta) {
236
+ this.latestTick = time;
237
+
238
+ if (!this.isGrabbed && this.body) {
239
+ if (this.el.object3D.position.y < -10) {
240
+ console.log("fell through floor");
241
+ this.body.velocity.set(0, 0, 0);
242
+ this.body.position.copy(this.camera.object3D.position);
243
+ }
244
+ }
245
+ },
246
+
247
+ remove: function () {
248
+ this.removeSelf();
249
+ },
250
+ });