Skip to content

Commit 803b16e

Browse files
committed
fix(anim): fixes #38 - animations et gameplay
1 parent eccc216 commit 803b16e

2 files changed

Lines changed: 282 additions & 74 deletions

File tree

lucky7-app/frontend/src/app/components/GameScreen.tsx

Lines changed: 90 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,16 @@ function SlotMachineDisplay({
172172
);
173173
}
174174

175-
const CONFETTI_COLORS = ['#f59e0b', '#ef4444', '#3b82f6', '#10b981', '#8b5cf6', '#f97316', '#ec4899', '#14b8a6'];
175+
const CONFETTI_COLORS = [
176+
'#f59e0b',
177+
'#ef4444',
178+
'#3b82f6',
179+
'#10b981',
180+
'#8b5cf6',
181+
'#f97316',
182+
'#ec4899',
183+
'#14b8a6',
184+
];
176185

177186
function TrophyConfetti() {
178187
return (
@@ -182,7 +191,13 @@ function TrophyConfetti() {
182191
<span
183192
key={i}
184193
className="anim-confetti-particle"
185-
style={{ backgroundColor: color, '--a': `${i * 45}deg`, animationDelay: `${(i * 0.14) % 1.1}s` } as React.CSSProperties}
194+
style={
195+
{
196+
backgroundColor: color,
197+
'--a': `${i * 45}deg`,
198+
animationDelay: `${(i * 0.14) % 1.1}s`,
199+
} as React.CSSProperties
200+
}
186201
/>
187202
))}
188203
</span>
@@ -215,7 +230,10 @@ const jackpotCoord = (() => {
215230
},
216231
unregister(cb: (d: number) => void) {
217232
slots = slots.filter(s => s !== cb);
218-
if (slots.length === 0) { assignments = jShuffle(JACKPOT_TIERS); done = 0; }
233+
if (slots.length === 0) {
234+
assignments = jShuffle(JACKPOT_TIERS);
235+
done = 0;
236+
}
219237
},
220238
reportDone() {
221239
done++;
@@ -233,13 +251,20 @@ const jackpotCoord = (() => {
233251
function JackpotBadge() {
234252
const [reels, setReels] = useState([7, 7, 7]);
235253
const [locked, setLocked] = useState([false, false, false]);
236-
const r = useRef<{ timers: ReturnType<typeof setTimeout>[]; duration: number; spin: () => void }>({
237-
timers: [], duration: 2000, spin: () => {},
238-
});
254+
const r = useRef<{ timers: ReturnType<typeof setTimeout>[]; duration: number; spin: () => void }>(
255+
{
256+
timers: [],
257+
duration: 2000,
258+
spin: () => {},
259+
}
260+
);
239261

240262
useEffect(() => {
241263
function clearAll() {
242-
r.current.timers.forEach(t => { clearTimeout(t); clearInterval(t as unknown as ReturnType<typeof setInterval>); });
264+
r.current.timers.forEach(t => {
265+
clearTimeout(t);
266+
clearInterval(t as unknown as ReturnType<typeof setInterval>);
267+
});
243268
r.current.timers = [];
244269
}
245270

@@ -251,50 +276,82 @@ function JackpotBadge() {
251276
const ivals: ReturnType<typeof setInterval>[] = [];
252277

253278
[0, 1, 2].forEach(i => {
254-
const id = setInterval(() => {
255-
setReels(prev => { const n = [...prev]; n[i] = Math.floor(Math.random() * 9) + 1; return n; });
256-
}, 80 + i * 15);
279+
const id = setInterval(
280+
() => {
281+
setReels(prev => {
282+
const n = [...prev];
283+
n[i] = Math.floor(Math.random() * 9) + 1;
284+
return n;
285+
});
286+
},
287+
80 + i * 15
288+
);
257289
r.current.timers.push(id as unknown as ReturnType<typeof setTimeout>);
258290
ivals.push(id);
259291
});
260292

261293
[base, base + 400, base + 800].forEach((delay, i) => {
262294
const t = setTimeout(() => {
263295
clearInterval(ivals[i]);
264-
setReels(prev => { const n = [...prev]; n[i] = 7; return n; });
265-
setLocked(prev => { const n = [...prev]; n[i] = true; return n; });
296+
setReels(prev => {
297+
const n = [...prev];
298+
n[i] = 7;
299+
return n;
300+
});
301+
setLocked(prev => {
302+
const n = [...prev];
303+
n[i] = true;
304+
return n;
305+
});
266306
// Last reel done — signal coordinator; wait for all badges before restart
267307
if (i === 2) jackpotCoord.reportDone();
268308
}, delay);
269309
r.current.timers.push(t);
270310
});
271311
};
272312

273-
const cb = (d: number) => { r.current.duration = d; r.current.spin(); };
313+
const cb = (d: number) => {
314+
r.current.duration = d;
315+
r.current.spin();
316+
};
274317
r.current.duration = jackpotCoord.register(cb);
275318
r.current.spin();
276319

277-
return () => { jackpotCoord.unregister(cb); clearAll(); };
320+
return () => {
321+
jackpotCoord.unregister(cb);
322+
clearAll();
323+
};
278324
}, []);
279325

280326
const allLocked = locked.every(Boolean);
281327
const [rainKey, setRainKey] = useState(0);
282328
const wasLocked = useRef(false);
283-
if (allLocked && !wasLocked.current) { wasLocked.current = true; setRainKey(k => k + 1); }
329+
if (allLocked && !wasLocked.current) {
330+
wasLocked.current = true;
331+
setRainKey(k => k + 1);
332+
}
284333
if (!allLocked) wasLocked.current = false;
285334

286335
return (
287336
<span className="relative inline-flex items-center gap-px bg-green-500/15 border border-green-500/40 rounded px-1 py-px font-black tabular-nums leading-none text-[11px]">
288337
{reels.map((n, i) => (
289-
<span key={i} className={`w-[9px] text-center transition-colors duration-150 ${locked[i] ? 'text-yellow-400' : 'text-green-400'}`}>{n}</span>
290-
))}
291-
{allLocked && [0, 1, 2].map(i => (
292338
<span
293-
key={`${rainKey}-${i}`}
294-
className="anim-coin-rain"
295-
style={{ right: `${i * 10}px`, animationDelay: `${i * 0.12}s`, zIndex: 50 }}
296-
>🪙</span>
339+
key={i}
340+
className={`w-[9px] text-center transition-colors duration-150 ${locked[i] ? 'text-yellow-400' : 'text-green-400'}`}
341+
>
342+
{n}
343+
</span>
297344
))}
345+
{allLocked &&
346+
[0, 1, 2].map(i => (
347+
<span
348+
key={`${rainKey}-${i}`}
349+
className="anim-coin-rain"
350+
style={{ right: `${i * 10}px`, animationDelay: `${i * 0.12}s`, zIndex: 50 }}
351+
>
352+
🪙
353+
</span>
354+
))}
298355
</span>
299356
);
300357
}
@@ -316,7 +373,9 @@ function DoubleBadge({ value }: { value: number }) {
316373

317374
return (
318375
<span className="inline-flex items-center bg-blue-500/15 border border-blue-500/40 rounded px-1 py-px font-black tabular-nums leading-none text-[11px] text-blue-400">
319-
<span key={display} className="anim-badge-slam">x{display}</span>
376+
<span key={display} className="anim-badge-slam">
377+
x{display}
378+
</span>
320379
</span>
321380
);
322381
}
@@ -1280,8 +1339,7 @@ export default function GameScreen({ players: initialPlayers, rules, onEnd }: Ga
12801339
rolledDice.filter(r => r.score === 7).length === 3;
12811340
const demonVisible =
12821341
allRolled && rules.demon && rolledDice.filter(r => r.score === 6).length === 3;
1283-
const legendeVisible =
1284-
rules.legende && rolledDice.some(r => r.score === 11);
1342+
const legendeVisible = rules.legende && rolledDice.some(r => r.score === 11);
12851343

12861344
return players.map((player, index) => {
12871345
const roll = rolledDice.find(r => r.playerId === player.id);
@@ -1305,7 +1363,11 @@ export default function GameScreen({ players: initialPlayers, rules, onEnd }: Ga
13051363
legendeVisible &&
13061364
(roll.dice1 >= 5 || roll.dice2 >= 5);
13071365
const isLegendeTrigger =
1308-
revealed && !isJackpotPlayer && !isDemonPlayer && legendeVisible && roll.score === 11;
1366+
revealed &&
1367+
!isJackpotPlayer &&
1368+
!isDemonPlayer &&
1369+
legendeVisible &&
1370+
roll.score === 11;
13091371
const isJeton =
13101372
revealed &&
13111373
!isJackpotPlayer &&
@@ -1358,7 +1420,7 @@ export default function GameScreen({ players: initialPlayers, rules, onEnd }: Ga
13581420
🔥
13591421
</span>
13601422
)}
1361-
1423+
13621424
{isDouble && (
13631425
<span className="absolute right-1 top-0 text-5xl font-black opacity-[0.18] select-none pointer-events-none leading-tight text-blue-300">
13641426
{roll.dice1}
@@ -1915,7 +1977,7 @@ export default function GameScreen({ players: initialPlayers, rules, onEnd }: Ga
19151977
🔥
19161978
</span>
19171979
)}
1918-
1980+
19191981
{isDouble && (
19201982
<span className="absolute right-1 top-0 text-5xl font-black opacity-[0.18] select-none pointer-events-none leading-tight text-blue-300">
19211983
{s.dice1}

0 commit comments

Comments
 (0)