From c7911f670ac40701bfa11af0ce766422a7c4a5c5 Mon Sep 17 00:00:00 2001 From: Alberto Moretti Date: Thu, 2 Jul 2026 13:30:15 +0200 Subject: [PATCH] confetti --- app.js | 124 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 98 insertions(+), 26 deletions(-) diff --git a/app.js b/app.js index b9dc8f1..a5721c0 100644 --- a/app.js +++ b/app.js @@ -92,23 +92,33 @@ ? 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) { + bigBurst(); if (kind === "jackpot") { - const end = Date.now() + 1400; - const colors = ["#ffd23f", "#ff9e00", "#ff2e88", "#00e5ff", "#ffffff"]; + // pioggia prolungata extra per il jackpot + const end = Date.now() + 2600; (function frame() { - myConfetti({ particleCount: 6, angle: 60, spread: 70, origin: { x: 0 }, colors }); - myConfetti({ particleCount: 6, angle: 120, spread: 70, origin: { x: 1 }, colors }); - myConfetti({ particleCount: 4, spread: 120, startVelocity: 55, origin: { y: 0.3 }, colors }); + myConfetti({ particleCount: 12, angle: 60, spread: 80, origin: { x: 0 }, colors: CONFETTI_COLORS }); + myConfetti({ particleCount: 12, angle: 120, spread: 80, origin: { x: 1 }, colors: CONFETTI_COLORS }); + myConfetti({ particleCount: 10, spread: 140, startVelocity: 60, origin: { y: 0.25 }, colors: CONFETTI_COLORS }); if (Date.now() < end) requestAnimationFrame(frame); })(); } else { - myConfetti({ - particleCount: 90, - spread: 80, - origin: { y: 0.55 }, - colors: ["#ffd23f", "#00e5ff", "#ff2e88", "#ffffff"], - }); + // anche un reveal normale ha una seconda ondata + setTimeout(() => { + myConfetti({ particleCount: 120, spread: 100, startVelocity: 40, origin: { y: 0.5 }, colors: CONFETTI_COLORS }); + }, 220); } } @@ -305,6 +315,7 @@ let cursor = 0; let auto = false; let busy = false; + let leverArmed = false; // scommettitori (TU + banco simulato) let players = []; @@ -343,9 +354,11 @@ setProgress(); $("#player-name").textContent = "—"; $("#odds").innerHTML = ""; - mc("Si parte! Premi START 🎰"); - $("#btn-primary").textContent = "START 🎰"; - $("#btn-primary").disabled = false; + mc("Tira giù la leva per far salire il primo! ⬇️"); + // il bottone principale serve solo per RIGIOCA a fine partita + $("#btn-primary").style.display = "none"; + $("#btn-primary").onclick = onPrimary; + armLever(true); } /* ---------- Rendering ---------- */ @@ -488,6 +501,7 @@ return; } busy = true; + armLever(false); Audio.init(); Audio.resume(); @@ -505,12 +519,11 @@ botsPlace(odds); mc(`Tocca a ${person}! Dove finirà? 🎲`); - // leva + spin + // animazione leva + boost monete $("#lever").classList.add("pull"); - setTimeout(() => $("#lever").classList.remove("pull"), 300); + setTimeout(() => $("#lever").classList.remove("pull"), 320); if (window.__coinBoost) window.__coinBoost(); - $("#btn-primary").disabled = true; await spinReel(roomId); // atterraggio @@ -544,13 +557,17 @@ busy = false; if (cursor >= revealQueue.length) { - $("#btn-primary").textContent = "FINE 🏁"; - $("#btn-primary").disabled = false; - setTimeout(endGame, 900); + setTimeout(endGame, 1100); + } else if (auto) { + setTimeout(nextTurn, 1400); } else { - $("#btn-primary").textContent = "SPINNA! 🎰"; - $("#btn-primary").disabled = false; - if (auto) setTimeout(nextTurn, 1400); + // riarma la leva per il prossimo giro + setTimeout(() => { + if (!busy && cursor < revealQueue.length && !auto) { + armLever(true); + mc("Tira di nuovo la leva! ⬇️"); + } + }, 1300); } } @@ -563,16 +580,18 @@ } function endGame() { + armLever(false); const winner = players.slice().sort((a, b) => b.chips - a.chips)[0]; const you = players.find((p) => p.you); mc(`🏁 Tutti sistemati! Vincitore scommesse: ${winner.name} (${winner.chips} gettoni).`); log(`Fine. I tuoi gettoni: ${you.chips}. Miglior scommettitore: ${winner.name}.`, "win"); + Audio.fanfare(); celebrate("jackpot"); + $("#btn-primary").style.display = ""; $("#btn-primary").textContent = "RIGIOCA 🔁"; $("#btn-primary").disabled = false; $("#btn-primary").onclick = () => { newGame(false); - $("#btn-primary").onclick = onPrimary; }; } @@ -584,6 +603,52 @@ .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 ---------- */ function onPrimary() { if (busy) return; @@ -595,18 +660,25 @@ } function bindControls() { + bindLever(); $("#btn-primary").onclick = onPrimary; $("#btn-auto").onclick = (e) => { auto = !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 = () => { if (busy) return; Audio.init(); Audio.resume(); newGame(true); - mc("Nuovo sorteggio pronto! 🎲 Premi START."); + mc("Nuovo sorteggio pronto! 🎲 Tira la leva ⬇️"); }; $("#btn-sound").onclick = (e) => { Audio.on = !Audio.on;