fixed touchscreen controls stuck bug
This commit is contained in:
parent
c80b76e06e
commit
1210201802
|
|
@ -1,6 +1,6 @@
|
|||
import { useEffect, useRef } from "react";
|
||||
import { create } from "nipplejs";
|
||||
import { DEFAULT_JOYSTICK_VALUES, joystickValues } from "../joystickInput";
|
||||
import { joystickValues } from "../joystickInput";
|
||||
|
||||
// const isTouch = navigator.maxTouchPoints > 0;
|
||||
const isTouch = true; // debug
|
||||
|
|
@ -11,7 +11,7 @@ export function JoystickView() {
|
|||
const lookZoneRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
|
||||
if (!isTouch)
|
||||
return;
|
||||
|
||||
|
|
@ -22,67 +22,100 @@ export function JoystickView() {
|
|||
if (!moveZone || !jumpBtn || !lookZone)
|
||||
return;
|
||||
|
||||
const moveJoystick = create({
|
||||
zone: moveZone,
|
||||
mode: 'static',
|
||||
position: { left: '80px', bottom: '80px' },
|
||||
color: 'white',
|
||||
shape: 'square',
|
||||
size: 100,
|
||||
});
|
||||
let moveJoystick: ReturnType<typeof create>;
|
||||
let lookJoystick: ReturnType<typeof create>;
|
||||
|
||||
const lookJoystick = create({
|
||||
zone: lookZone,
|
||||
mode: 'dynamic',
|
||||
dataOnly: true,
|
||||
});
|
||||
const setup = () => {
|
||||
moveJoystick = create({
|
||||
zone: moveZone,
|
||||
mode: 'static',
|
||||
position: { left: '80px', bottom: '80px' },
|
||||
color: 'white',
|
||||
shape: 'circle',
|
||||
size: 100,
|
||||
});
|
||||
|
||||
moveJoystick.on('move', (evt) => {
|
||||
joystickValues.move.x = evt.data.vector.x;
|
||||
joystickValues.move.y = evt.data.vector.y;
|
||||
});
|
||||
moveJoystick.on('end', () => {
|
||||
lookJoystick = create({
|
||||
zone: lookZone,
|
||||
mode: 'dynamic',
|
||||
dataOnly: true,
|
||||
});
|
||||
|
||||
moveJoystick.on('move', (evt) => {
|
||||
joystickValues.move.x = evt.data.vector.x;
|
||||
joystickValues.move.y = evt.data.vector.y;
|
||||
});
|
||||
moveJoystick.on('end', () => {
|
||||
joystickValues.move = { x: 0, y: 0 };
|
||||
});
|
||||
|
||||
lookJoystick.on('move', (evt) => {
|
||||
joystickValues.look = evt.data.vector;
|
||||
});
|
||||
lookJoystick.on('end', () => {
|
||||
joystickValues.look = { x: 0, y: 0 };
|
||||
});
|
||||
};
|
||||
|
||||
const teardown = () => {
|
||||
moveJoystick?.destroy();
|
||||
lookJoystick?.destroy();
|
||||
joystickValues.move = { x: 0, y: 0 };
|
||||
});
|
||||
|
||||
lookJoystick.on('move', (evt) => {
|
||||
joystickValues.look = evt.data.vector;
|
||||
});
|
||||
lookJoystick.on('end', () => {
|
||||
joystickValues.look = { x: 0, y: 0 };
|
||||
});
|
||||
joystickValues.jump = false;
|
||||
};
|
||||
|
||||
setup();
|
||||
|
||||
const onJumpDown = () => { joystickValues.jump = true; };
|
||||
const onJumpUp = () => { joystickValues.jump = false; };
|
||||
|
||||
jumpBtn.addEventListener('pointerdown', onJumpDown);
|
||||
jumpBtn.addEventListener('pointerup', onJumpUp);
|
||||
jumpBtn.addEventListener('pointercancel', onJumpUp);
|
||||
jumpBtn.addEventListener('pointerleave', onJumpUp);
|
||||
|
||||
// When the OS interrupts a touch (app switch, notification, etc.) the browser
|
||||
// fires pointercancel instead of pointerup, leaving nipplejs with a stuck active
|
||||
// identifier. In dynamic mode this silently drops all subsequent touches on the
|
||||
// look zone. Destroying and recreating resets nipplejs's internal touch tracking.
|
||||
const onVisibilityChange = () => {
|
||||
if (document.hidden) {
|
||||
teardown();
|
||||
} else {
|
||||
setup();
|
||||
}
|
||||
};
|
||||
document.addEventListener('visibilitychange', onVisibilityChange);
|
||||
|
||||
return () => {
|
||||
moveJoystick.destroy();
|
||||
lookJoystick.destroy();
|
||||
teardown();
|
||||
jumpBtn.removeEventListener('pointerdown', onJumpDown);
|
||||
jumpBtn.removeEventListener('pointerup', onJumpUp);
|
||||
jumpBtn.removeEventListener('pointercancel', onJumpUp);
|
||||
jumpBtn.removeEventListener('pointerleave', onJumpUp);
|
||||
Object.assign(joystickValues, DEFAULT_JOYSTICK_VALUES);
|
||||
document.removeEventListener('visibilitychange', onVisibilityChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
if (!isTouch) return null;
|
||||
if (!isTouch)
|
||||
return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
ref={moveZoneRef}
|
||||
style={{ position: 'absolute', left: 0, bottom: 0, width: '50%', height: '45%', touchAction: 'none' }}
|
||||
id="move-zone"
|
||||
style={{ position: 'absolute', left: 0, bottom: 0, width: '30vw', height: '30vw', touchAction: 'none', background: 'red' }}
|
||||
/>
|
||||
<div
|
||||
ref={lookZoneRef}
|
||||
style={{ position: 'absolute', right: 0, bottom: 0, width: '50%', height: '45%', touchAction: 'none' }}
|
||||
id="look-zone"
|
||||
style={{ position: 'absolute', right: 0, bottom: 0, width: '100%', height: '100%', touchAction: 'none' }}
|
||||
/>
|
||||
<div
|
||||
ref={jumpBtnRef}
|
||||
id="jump-zone"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
right: 30,
|
||||
|
|
|
|||
Loading…
Reference in New Issue