Il flipper rivisto con la revisione di Codex: punti solo a un urto nuovo, sottopassi contro gli attraversamenti, molla che arriva sempre in campo (senza cancelletto), salvataggio col tempo della simulazione e in vista, corsie che contano attraversando la riga, traguardo acquisito appena raggiunto, annullare non lancia, due dita e tasto destro, pulsanti dei flipper sempre attivi
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GiECd9RWGMKV7n3K1mdy8T
This commit is contained in:
+24
-3
@@ -492,9 +492,12 @@ const debugView = () => debug && debugShown && game && { mouse, points: debugPoi
|
||||
const TOUCH_REACH = 22;
|
||||
const reachOf = e => e.pointerType === 'touch' || e.pointerType === 'pen' ? TOUCH_REACH * WIDTH / canvas.getBoundingClientRect().width : 0;
|
||||
let press = null;
|
||||
// Le dita in più sul flipper (oltre a `press`): ognuna lascia il suo flipper quando si alza. Il tasto destro del
|
||||
// mouse ha lo stesso pointerId del sinistro: per il flipper vale come un dito a parte.
|
||||
const extra = new Set(), pointerKey = e => e.button === 2 ? 'mouse-right' : e.pointerId;
|
||||
canvas.addEventListener('pointerdown', e => {
|
||||
if (debug && e.shiftKey && e.button === 0) { debugPoint(scenePoint(e)); return; }
|
||||
if (!running || e.button > 0) return;
|
||||
if (!running || (e.button > 0 && !(e.button === 2 && game.closeup && story.closeups[game.closeup.id].type === 'flipper'))) return;
|
||||
// Nel primo piano un tocco sfoglia (o salta la battuta): gli oggetti della scena dietro non si toccano.
|
||||
if (game.closeup) {
|
||||
const type = story.closeups[game.closeup.id].type, deck = CARD_AT[type];
|
||||
@@ -520,6 +523,12 @@ canvas.addEventListener('pointerdown', e => {
|
||||
if (gara.press(game.closeup, e.pointerId)) { press = { gara: e.pointerId }; canvas.setPointerCapture(e.pointerId); }
|
||||
return;
|
||||
}
|
||||
// Il flipper: un secondo dito (o il secondo pulsante del mouse) comanda l'altro flipper, per conto suo.
|
||||
if (press?.closeup && type === 'flipper' && !extra.has(pointerKey(e))) {
|
||||
game.closeupAim(scenePoint(e));
|
||||
if (game.closeupPress(pointerKey(e))) { extra.add(pointerKey(e)); canvas.setPointerCapture(e.pointerId); }
|
||||
return;
|
||||
}
|
||||
if (press?.closeup) return;
|
||||
const aimed = game.closeupAim(scenePoint(e));
|
||||
if (['biliardo', 'rinquarto', 'basket', 'micro', 'cerbottana', 'condor'].includes(story.closeups[game.closeup.id].type)) {
|
||||
@@ -537,6 +546,8 @@ canvas.addEventListener('pointerdown', e => {
|
||||
press = { point, reach, long: false, timer: setTimeout(() => { press.long = true; command.clickScene(point, { look: true, reach }); }, LONG_PRESS) };
|
||||
});
|
||||
canvas.addEventListener('pointerup', e => {
|
||||
const key = e.button === 2 ? 'mouse-right' : e.pointerId;
|
||||
if (extra.has(key)) { extra.delete(key); game?.closeupRelease(key); return; }
|
||||
if (!press) return;
|
||||
// Scopa: la carta toccata e lasciata sullo stesso punto. Se sta nella presa già scelta, si prende quella; se no
|
||||
// si sceglie la prima presa che la contiene (un altro tocco conferma). Trascinando via non succede niente.
|
||||
@@ -574,12 +585,13 @@ canvas.addEventListener('pointerup', e => {
|
||||
press = null;
|
||||
});
|
||||
canvas.addEventListener('pointercancel', e => {
|
||||
if (extra.has(e.pointerId)) { extra.delete(e.pointerId); game?.closeupCancel(e.pointerId); return; }
|
||||
if (press?.closeup && e.pointerId !== press.pointerId) return;
|
||||
if (press) clearTimeout(press.timer);
|
||||
if (!press?.closeup || game?.closeup === press.state) game?.closeupCancel(e.pointerId);
|
||||
press = null;
|
||||
});
|
||||
canvas.addEventListener('lostpointercapture', e => { if (press?.closeup && e.pointerId !== press.pointerId) return; if (press?.closeup || press?.gara !== undefined || press?.card !== undefined || press?.table !== undefined) { press = null; game?.closeupCancel(e.pointerId); } });
|
||||
canvas.addEventListener('lostpointercapture', e => { if (extra.has(e.pointerId)) { extra.delete(e.pointerId); game?.closeupCancel(e.pointerId); return; } if (press?.closeup && e.pointerId !== press.pointerId) return; if (press?.closeup || press?.gara !== undefined || press?.card !== undefined || press?.table !== undefined) { press = null; game?.closeupCancel(e.pointerId); } });
|
||||
canvas.addEventListener('contextmenu', e => {
|
||||
e.preventDefault();
|
||||
if (running && !game.closeup) command.clickScene(scenePoint(e), { look: true });
|
||||
@@ -587,6 +599,13 @@ canvas.addEventListener('contextmenu', e => {
|
||||
canvas.addEventListener('pointermove', e => {
|
||||
if (!running) return;
|
||||
mouse = e.pointerType === 'mouse' ? scenePoint(e) : null;
|
||||
// Il tasto destro premuto o lasciato mentre il sinistro è giù arriva come pointermove (pulsanti «in accordo»):
|
||||
// al flipper vale come un secondo dito, per il flipper di destra.
|
||||
if (e.button === 2 && game.closeup && story.closeups[game.closeup.id].type === 'flipper') {
|
||||
if (e.buttons & 2) { if (!extra.has('mouse-right')) { game.closeupAim(scenePoint(e)); if (game.closeupPress('mouse-right')) extra.add('mouse-right'); } }
|
||||
else if (extra.has('mouse-right')) { extra.delete('mouse-right'); game.closeupRelease('mouse-right'); }
|
||||
return;
|
||||
}
|
||||
// Al biliardo e alle bocce la mira segue il mouse finché un clic (o una regolazione fine) non la fissa: dopo,
|
||||
// attraversare il campo per raggiungere la forza, «Tira» o «Lancia» non cambia il colpo. Al tiro dopo torna libera.
|
||||
// (Bocce: scoperto girando il video «Come si gioca», la mira finiva a due passi andando verso il cursore.)
|
||||
@@ -620,7 +639,7 @@ const MINI = {
|
||||
condor: { ...condor, back: 'Torna al campone', label: 'La Condor: muovi il mouse o tocca il campo per mirare, tieni premuto per trattenere il fiato e lascia per sparare; oppure premi Spara. Frecce per spostare il mirino.' },
|
||||
campana: { ...campana, back: 'Torna al campone', label: 'La campana: muovi il mouse o tocca la campana per mirare, tieni premuto per la forza e lascia per tirare il sassolino; oppure regola la forza e premi Tira (frecce su e giù per mirare, destra e sinistra per la forza). Ai salti premi, o Spazio, quando la lancetta è nel verde.' },
|
||||
bruciate: { ...bruciate, back: 'Torna alla festa', label: 'Le bruciate: tieni premuto e fai dei giri, col mouse o col dito, per girare la manovella; oppure Spazio o le frecce, una spinta a ogni colpo. Né troppo piano né troppo forte; quando son cotte, Rovescia nel sacco (o Invio).' },
|
||||
flipper: { ...flipper, toggle: true, back: 'Torna in strada', label: 'Il flipper del River: tieni premuto per caricare la molla e lascia per lanciare (o regola la forza e premi Lancia, o Spazio). In gioco, tieni premuto sulla metà sinistra o destra della scena per alzare il flipper di quel lato, oppure i pulsanti Flipper o le frecce sinistra e destra.' },
|
||||
flipper: { ...flipper, toggle: true, back: 'Torna in strada', label: 'Il flipper del River: tieni premuto per caricare la molla e lascia per lanciare (o regola la forza e premi Lancia, o Spazio). In gioco, tieni premuto sulla metà sinistra o destra della scena per alzare il flipper di quel lato, anche con due dita o col tasto destro del mouse; oppure i pulsanti Flipper o le frecce sinistra e destra.' },
|
||||
micro: { ...micro, back: 'Torna dal Chiaru', label: 'La pista col gesso: muovi il mouse o tocca il parcheggio per mirare, tieni premuto per caricare la spinta e lascia; oppure regola la forza e premi Spingi. Frecce o pulsanti Mira per girare.' },
|
||||
basket: { ...basket, back: 'Torna in strada', label: 'Fai due tiri: muovi il mouse o tocca per mirare, tieni premuto per caricare la forza, lascia per tirare.' },
|
||||
// La gara: niente mira né forza, il pulsante alterna gas e freno (chi non può tenere premuto).
|
||||
@@ -1057,6 +1076,8 @@ function updateUi() {
|
||||
setValue($('bocce-power'), Math.round(c.power * 100));
|
||||
setValue($('bocce-power-value'), `${Math.round(c.power * 100)}%`);
|
||||
for (const id of ['bocce-power', 'bocce-left', 'bocce-right']) setProp($(id), 'disabled', !(mg.canAdjust?.(c) ?? mg.canThrow(c)) || (c.holding && !mg.toggle) || !!game.speech);
|
||||
// Al flipper i due pulsanti valgono per tutta la partita, il cursore della molla solo prima del lancio.
|
||||
if (mg.canFlip) for (const id of ['bocce-left', 'bocce-right']) setProp($(id), 'disabled', !mg.canFlip(c) || !!game.speech);
|
||||
setProp($('bocce-throw'), 'disabled', !(mg.canPress?.(c) ?? mg.canThrow(c)) || (c.holding && !mg.toggle) || !!game.speech);
|
||||
// Il GP di Fortezza: niente forza, e i due pulsanti di mira diventano lo sterzo (si tengono premuti).
|
||||
// Nel GP di Fortezza il cursore della forza diventa la sensibilità dello sterzo col dito (ricordata).
|
||||
|
||||
Reference in New Issue
Block a user