Charge the hold, and drop the two buttons that have nothing to do
Three things, plus the README moves up to the repo root where a README belongs — it was being served as part of the site. The clock now runs until the finger lifts. The previous commit registered a tap on the lift but backdated the turn to the press, which showed up as the display counting down during a hold and then jumping back. Worse than cosmetic: the hold was refunded, so a thumb resting on your own half bought unlimited thinking time for nothing, and holding past zero couldn't flag you either, because render()'s flag check watches the live display while tap() charged from an earlier instant. One performance.now() at the lift now serves both the outgoing charge and the incoming turnAt, so nothing falls between them and goes to neither player. With the delay at 0 and a turn 1000ms old, an instant lift costs 1001ms and a 600ms hold costs 1602ms — the inverse of what the last commit was verified against. Swipe rejection is untouched; it lives in the pointer handler, not here. Reset and pause step out when they have nothing to do: pause before each game's first tap, reset while the match is still pristine. matchPristine() already meant exactly that, so both toggles sit beside the settings one in render(), where they can't go stale. Reset and settings turn out to be exact opposites. btn--vacant like the gear, so the space is kept — a fresh-match bar differs from the old build only inside those two slots, every other pixel in the frame identical, gear and speaker unmoved. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+15
-10
@@ -761,8 +761,13 @@
|
||||
}
|
||||
|
||||
// here rather than in the mutators, so it can never go stale; the
|
||||
// two-argument toggle leaves the DOM alone when the state already matches
|
||||
btnSettings.classList.toggle("btn--vacant", !matchPristine());
|
||||
// two-argument toggle leaves the DOM alone when the state already matches.
|
||||
// Settings and Reset are exact opposites: before the match you can change
|
||||
// the setup and have nothing to reset, and once it's running, the reverse.
|
||||
var pristine = matchPristine();
|
||||
btnSettings.classList.toggle("btn--vacant", !pristine);
|
||||
btnReset.classList.toggle("btn--vacant", pristine); // nothing played to reset
|
||||
btnPlay.classList.toggle("btn--vacant", st.phase === IDLE); // nothing running to pause
|
||||
}
|
||||
|
||||
function loop(){ render(); requestAnimationFrame(loop); }
|
||||
@@ -778,13 +783,12 @@
|
||||
saveGame();
|
||||
}
|
||||
|
||||
// `at` is when the finger landed. A tap is only confirmed once it lifts, but
|
||||
// the turn has to change at the press or every switch drifts by however long
|
||||
// the finger rested on the panel.
|
||||
function tap(side, at){
|
||||
function tap(side){
|
||||
if(st.phase === FLAG) return;
|
||||
if(st.phase === PAUSE) return;
|
||||
var now = at || performance.now();
|
||||
// the lift, not the press: your clock runs for as long as your finger is
|
||||
// down, so a held thumb costs you exactly the time it was seen counting off
|
||||
var now = performance.now();
|
||||
|
||||
if(st.phase === IDLE){
|
||||
st.active = 1 - side; // you tap your own side to start your opponent
|
||||
@@ -798,7 +802,8 @@
|
||||
}
|
||||
if(side !== st.active) return; // the waiting player can't stop the clock
|
||||
|
||||
// not elapsed(): that measures to *now*, and this has to measure to the press
|
||||
// the same instant charges the outgoing turn and starts the incoming one,
|
||||
// so nothing falls between the two and goes to neither player
|
||||
var e = now - st.turnAt;
|
||||
st.reserve[side] = Math.max(0, st.reserve[side] - Math.max(0, e - cfg.delay));
|
||||
st.moves[side]++;
|
||||
@@ -1177,7 +1182,7 @@
|
||||
p.addEventListener("pointerdown", function(ev){
|
||||
ev.preventDefault();
|
||||
audio(); // unlocking on the press is a valid gesture and earlier is better
|
||||
down = { id: ev.pointerId, x: ev.clientX, y: ev.clientY, t: ev.timeStamp };
|
||||
down = { id: ev.pointerId, x: ev.clientX, y: ev.clientY };
|
||||
// so the lift still lands here if the finger drifts onto the other panel
|
||||
try{ p.setPointerCapture(ev.pointerId); }catch(e){}
|
||||
});
|
||||
@@ -1197,7 +1202,7 @@
|
||||
document.documentElement.requestFullscreen().catch(function(){});
|
||||
}
|
||||
}
|
||||
tap(side, d.t);
|
||||
tap(side);
|
||||
});
|
||||
|
||||
// the branch Android's home gesture takes
|
||||
|
||||
Reference in New Issue
Block a user