50 lines
1.4 KiB
JavaScript
50 lines
1.4 KiB
JavaScript
(() => {
|
|
function sameTarget(left, right) { return left?.x === right?.x && left?.y === right?.y; }
|
|
|
|
function createTargetActivator({ canFire, select, fire, thresholdMs = 360, now = () => Date.now() }) {
|
|
let lastTap;
|
|
let firing = false;
|
|
|
|
async function fireOnce(target) {
|
|
if (firing || !canFire(target)) return false;
|
|
firing = true;
|
|
lastTap = undefined;
|
|
try {
|
|
await fire(target);
|
|
return true;
|
|
} finally {
|
|
firing = false;
|
|
}
|
|
}
|
|
|
|
function tap(target) {
|
|
if (firing || !canFire(target)) return { action: 'ignored' };
|
|
const timestampMs = now();
|
|
if (lastTap && sameTarget(lastTap.target, target) && timestampMs - lastTap.timestampMs <= thresholdMs) {
|
|
return { action: 'fire', promise: fireOnce(target) };
|
|
}
|
|
select(target);
|
|
lastTap = { target, timestampMs };
|
|
return { action: 'select' };
|
|
}
|
|
|
|
function keyboard(target) {
|
|
if (firing || !canFire(target)) return { action: 'ignored' };
|
|
select(target);
|
|
lastTap = undefined;
|
|
return { action: 'select' };
|
|
}
|
|
|
|
return {
|
|
tap,
|
|
keyboard,
|
|
doubleActivate: (target) => ({ action: 'fire', promise: fireOnce(target) }),
|
|
isFiring: () => firing,
|
|
};
|
|
}
|
|
|
|
const api = { createTargetActivator };
|
|
if (typeof module !== 'undefined' && module.exports) module.exports = api;
|
|
else globalThis.BattleshipTargetInteraction = api;
|
|
})();
|