This commit is contained in:
2026-07-02 13:30:15 +02:00
parent e0f9dd8da3
commit c7911f670a

124
app.js
View File

@@ -92,23 +92,33 @@
? confetti.create($("#confetti"), { resize: true, useWorker: true }) ? confetti.create($("#confetti"), { resize: true, useWorker: true })
: () => {}; : () => {};
const CONFETTI_COLORS = ["#ffd23f", "#ff9e00", "#ff2e88", "#00e5ff", "#29e08a", "#ffffff"];
function bigBurst() {
// esplosione centrale abbondante
myConfetti({ particleCount: 220, spread: 110, startVelocity: 48, origin: { y: 0.55 }, colors: CONFETTI_COLORS });
myConfetti({ particleCount: 140, spread: 130, startVelocity: 40, decay: 0.92, scalar: 1.1, origin: { y: 0.6 }, colors: CONFETTI_COLORS });
// due cannoni laterali
myConfetti({ particleCount: 80, angle: 60, spread: 75, origin: { x: 0, y: 0.7 }, colors: CONFETTI_COLORS });
myConfetti({ particleCount: 80, angle: 120, spread: 75, origin: { x: 1, y: 0.7 }, colors: CONFETTI_COLORS });
}
function celebrate(kind) { function celebrate(kind) {
bigBurst();
if (kind === "jackpot") { if (kind === "jackpot") {
const end = Date.now() + 1400; // pioggia prolungata extra per il jackpot
const colors = ["#ffd23f", "#ff9e00", "#ff2e88", "#00e5ff", "#ffffff"]; const end = Date.now() + 2600;
(function frame() { (function frame() {
myConfetti({ particleCount: 6, angle: 60, spread: 70, origin: { x: 0 }, colors }); myConfetti({ particleCount: 12, angle: 60, spread: 80, origin: { x: 0 }, colors: CONFETTI_COLORS });
myConfetti({ particleCount: 6, angle: 120, spread: 70, origin: { x: 1 }, colors }); myConfetti({ particleCount: 12, angle: 120, spread: 80, origin: { x: 1 }, colors: CONFETTI_COLORS });
myConfetti({ particleCount: 4, spread: 120, startVelocity: 55, origin: { y: 0.3 }, colors }); myConfetti({ particleCount: 10, spread: 140, startVelocity: 60, origin: { y: 0.25 }, colors: CONFETTI_COLORS });
if (Date.now() < end) requestAnimationFrame(frame); if (Date.now() < end) requestAnimationFrame(frame);
})(); })();
} else { } else {
myConfetti({ // anche un reveal normale ha una seconda ondata
particleCount: 90, setTimeout(() => {
spread: 80, myConfetti({ particleCount: 120, spread: 100, startVelocity: 40, origin: { y: 0.5 }, colors: CONFETTI_COLORS });
origin: { y: 0.55 }, }, 220);
colors: ["#ffd23f", "#00e5ff", "#ff2e88", "#ffffff"],
});
} }
} }
@@ -305,6 +315,7 @@
let cursor = 0; let cursor = 0;
let auto = false; let auto = false;
let busy = false; let busy = false;
let leverArmed = false;
// scommettitori (TU + banco simulato) // scommettitori (TU + banco simulato)
let players = []; let players = [];
@@ -343,9 +354,11 @@
setProgress(); setProgress();
$("#player-name").textContent = "—"; $("#player-name").textContent = "—";
$("#odds").innerHTML = ""; $("#odds").innerHTML = "";
mc("Si parte! Premi START 🎰"); mc("Tira giù la leva per far salire il primo! ⬇️");
$("#btn-primary").textContent = "START 🎰"; // il bottone principale serve solo per RIGIOCA a fine partita
$("#btn-primary").disabled = false; $("#btn-primary").style.display = "none";
$("#btn-primary").onclick = onPrimary;
armLever(true);
} }
/* ---------- Rendering ---------- */ /* ---------- Rendering ---------- */
@@ -488,6 +501,7 @@
return; return;
} }
busy = true; busy = true;
armLever(false);
Audio.init(); Audio.init();
Audio.resume(); Audio.resume();
@@ -505,12 +519,11 @@
botsPlace(odds); botsPlace(odds);
mc(`Tocca a ${person}! Dove finirà? 🎲`); mc(`Tocca a ${person}! Dove finirà? 🎲`);
// leva + spin // animazione leva + boost monete
$("#lever").classList.add("pull"); $("#lever").classList.add("pull");
setTimeout(() => $("#lever").classList.remove("pull"), 300); setTimeout(() => $("#lever").classList.remove("pull"), 320);
if (window.__coinBoost) window.__coinBoost(); if (window.__coinBoost) window.__coinBoost();
$("#btn-primary").disabled = true;
await spinReel(roomId); await spinReel(roomId);
// atterraggio // atterraggio
@@ -544,13 +557,17 @@
busy = false; busy = false;
if (cursor >= revealQueue.length) { if (cursor >= revealQueue.length) {
$("#btn-primary").textContent = "FINE 🏁"; setTimeout(endGame, 1100);
$("#btn-primary").disabled = false; } else if (auto) {
setTimeout(endGame, 900); setTimeout(nextTurn, 1400);
} else { } else {
$("#btn-primary").textContent = "SPINNA! 🎰"; // riarma la leva per il prossimo giro
$("#btn-primary").disabled = false; setTimeout(() => {
if (auto) setTimeout(nextTurn, 1400); if (!busy && cursor < revealQueue.length && !auto) {
armLever(true);
mc("Tira di nuovo la leva! ⬇️");
}
}, 1300);
} }
} }
@@ -563,16 +580,18 @@
} }
function endGame() { function endGame() {
armLever(false);
const winner = players.slice().sort((a, b) => b.chips - a.chips)[0]; const winner = players.slice().sort((a, b) => b.chips - a.chips)[0];
const you = players.find((p) => p.you); const you = players.find((p) => p.you);
mc(`🏁 Tutti sistemati! Vincitore scommesse: ${winner.name} (${winner.chips} gettoni).`); mc(`🏁 Tutti sistemati! Vincitore scommesse: ${winner.name} (${winner.chips} gettoni).`);
log(`Fine. I tuoi gettoni: ${you.chips}. Miglior scommettitore: ${winner.name}.`, "win"); log(`Fine. I tuoi gettoni: ${you.chips}. Miglior scommettitore: ${winner.name}.`, "win");
Audio.fanfare();
celebrate("jackpot"); celebrate("jackpot");
$("#btn-primary").style.display = "";
$("#btn-primary").textContent = "RIGIOCA 🔁"; $("#btn-primary").textContent = "RIGIOCA 🔁";
$("#btn-primary").disabled = false; $("#btn-primary").disabled = false;
$("#btn-primary").onclick = () => { $("#btn-primary").onclick = () => {
newGame(false); newGame(false);
$("#btn-primary").onclick = onPrimary;
}; };
} }
@@ -584,6 +603,52 @@
.join(""); .join("");
} }
/* ---------- Leva (trigger dei giri) ---------- */
function armLever(on) {
leverArmed = on;
const lever = $("#lever");
lever.classList.toggle("armed", on);
}
function pullAndSpin() {
if (!leverArmed || busy) return;
armLever(false);
nextTurn();
}
function bindLever() {
const lever = $("#lever");
let dragging = false;
let startY = 0;
lever.addEventListener("pointerdown", (e) => {
if (!leverArmed || busy) return;
dragging = true;
startY = e.clientY;
try {
lever.setPointerCapture(e.pointerId);
} catch (err) {}
e.preventDefault();
});
lever.addEventListener("pointermove", (e) => {
if (!dragging) return;
const dy = Math.max(0, Math.min(70, e.clientY - startY));
lever.style.transform = `rotate(${(dy / 70) * 28}deg)`;
});
const release = (e) => {
if (!dragging) return;
dragging = false;
const dy = Math.max(0, e.clientY - startY);
lever.style.transform = "";
// tap secco (dy piccolo) oppure tirata piena => parte; tirata a metà => annulla
if (dy < 8 || dy >= 26) pullAndSpin();
};
lever.addEventListener("pointerup", release);
lever.addEventListener("pointercancel", () => {
dragging = false;
$("#lever").style.transform = "";
});
}
/* ---------- Controlli ---------- */ /* ---------- Controlli ---------- */
function onPrimary() { function onPrimary() {
if (busy) return; if (busy) return;
@@ -595,18 +660,25 @@
} }
function bindControls() { function bindControls() {
bindLever();
$("#btn-primary").onclick = onPrimary; $("#btn-primary").onclick = onPrimary;
$("#btn-auto").onclick = (e) => { $("#btn-auto").onclick = (e) => {
auto = !auto; auto = !auto;
e.currentTarget.classList.toggle("active", auto); e.currentTarget.classList.toggle("active", auto);
if (auto && !busy && cursor < revealQueue.length) nextTurn(); if (auto) {
armLever(false);
if (!busy && cursor < revealQueue.length) nextTurn();
} else if (!busy && cursor < revealQueue.length) {
armLever(true);
mc("Tira la leva! ⬇️");
}
}; };
$("#btn-reroll").onclick = () => { $("#btn-reroll").onclick = () => {
if (busy) return; if (busy) return;
Audio.init(); Audio.init();
Audio.resume(); Audio.resume();
newGame(true); newGame(true);
mc("Nuovo sorteggio pronto! 🎲 Premi START."); mc("Nuovo sorteggio pronto! 🎲 Tira la leva ⬇️");
}; };
$("#btn-sound").onclick = (e) => { $("#btn-sound").onclick = (e) => {
Audio.on = !Audio.on; Audio.on = !Audio.on;