ugly-game 0.5.2 → 0.5.3
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.
|
@@ -27,6 +27,10 @@ export declare class BrowserRawBackend {
|
|
|
27
27
|
private paused;
|
|
28
28
|
constructor(opts: BrowserBackendOpts);
|
|
29
29
|
setPaused(p: boolean): void;
|
|
30
|
+
/** Drop every held key / mouse button / touch. Called when the window can no longer observe releases (blur,
|
|
31
|
+
* tab hidden, pointer-lock lost) so a key held across the disruption can't stick "on" and drive the avatar
|
|
32
|
+
* forever. Public so a host can force it (e.g. right before opening a modal that steals focus). */
|
|
33
|
+
releaseHeld(): void;
|
|
30
34
|
private on;
|
|
31
35
|
private cursor;
|
|
32
36
|
private gesture;
|
|
@@ -36,6 +36,10 @@ export class BrowserRawBackend {
|
|
|
36
36
|
paused = false; // while a menu is open: suspend gameplay input + don't grab pointer lock
|
|
37
37
|
constructor(opts) { this.target = opts.target; this.pointerLock = opts.pointerLock ?? false; this.attach(); }
|
|
38
38
|
setPaused(p) { this.paused = p; }
|
|
39
|
+
/** Drop every held key / mouse button / touch. Called when the window can no longer observe releases (blur,
|
|
40
|
+
* tab hidden, pointer-lock lost) so a key held across the disruption can't stick "on" and drive the avatar
|
|
41
|
+
* forever. Public so a host can force it (e.g. right before opening a modal that steals focus). */
|
|
42
|
+
releaseHeld() { this.keysDown.clear(); this.touches.clear(); this.pointerButtons.clear(); }
|
|
39
43
|
on(el, type, fn, o) {
|
|
40
44
|
const handler = fn;
|
|
41
45
|
el.addEventListener(type, handler, o);
|
|
@@ -54,7 +58,21 @@ export class BrowserRawBackend {
|
|
|
54
58
|
this.on(window, 'keydown', (e) => { if (!this.keysDown.has(e.code))
|
|
55
59
|
this.edges.add('key:' + e.code); this.keysDown.add(e.code); });
|
|
56
60
|
this.on(window, 'keyup', (e) => { this.keysDown.delete(e.code); });
|
|
57
|
-
|
|
61
|
+
// RELEASE ALL held input whenever the window can no longer see the keys being let go. `blur` alone is not
|
|
62
|
+
// enough: on macOS an app-switch (Cmd+Tab) delivers the keyup to the background, and the reliable page-side
|
|
63
|
+
// signal is `visibilitychange`→hidden (blur can be missed). Losing pointer lock (Esc / menu) is the same
|
|
64
|
+
// hazard. Without this a movement key held at switch-time stays in keysDown and the avatar walks that way
|
|
65
|
+
// forever ("stuck always going backward"). We clear ONLY on the disruptive edge — never when the tab becomes
|
|
66
|
+
// visible again or when lock is ACQUIRED, which would wrongly drop a key the player is legitimately holding.
|
|
67
|
+
this.on(window, 'blur', () => { this.releaseHeld(); });
|
|
68
|
+
const onHidden = () => { if (document.hidden)
|
|
69
|
+
this.releaseHeld(); };
|
|
70
|
+
const onUnlock = () => { if (document.pointerLockElement !== this.target)
|
|
71
|
+
this.releaseHeld(); };
|
|
72
|
+
document.addEventListener('visibilitychange', onHidden);
|
|
73
|
+
document.addEventListener('pointerlockchange', onUnlock);
|
|
74
|
+
this.disposers.push(() => { document.removeEventListener('visibilitychange', onHidden); });
|
|
75
|
+
this.disposers.push(() => { document.removeEventListener('pointerlockchange', onUnlock); });
|
|
58
76
|
this.on(this.target, 'wheel', (e) => { this.pwheel += e.deltaY; e.preventDefault(); }, { passive: false });
|
|
59
77
|
this.on(this.target, 'contextmenu', (e) => { e.preventDefault(); });
|
|
60
78
|
this.on(this.target, 'pointerdown', (e) => {
|