Affiche la deuxième pièce à venir dans La Corne d'Abondance
Build and deploy / deploy (push) Successful in 36s
Build and deploy / deploy (push) Successful in 36s
Petit badge "Puis" à côté du score, taille d'affichage fixe (juste informatif, pas de position à viser) — la file glisse d'un cran à chaque lâcher : ce qui était annoncé en second devient la pièce à viser. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -50,6 +50,9 @@ export function MelonGame({ citizens, onFinish }: { citizens: MemberRow[]; onFin
|
||||
const [score, setScore] = useState(0);
|
||||
const [pieces, setPieces] = useState<Piece[]>([]);
|
||||
const [nextTier, setNextTier] = useState(() => randomTier(DROP_MIN_TIER, dropMaxTier));
|
||||
// Palier annoncé après nextTier — juste informatif (pas de position à
|
||||
// viser), pour voir venir deux coups à l'avance au lieu d'un seul.
|
||||
const [secondTier, setSecondTier] = useState(() => randomTier(DROP_MIN_TIER, dropMaxTier));
|
||||
|
||||
const onFinishRef = useRef(onFinish);
|
||||
useEffect(() => {
|
||||
@@ -59,6 +62,7 @@ export function MelonGame({ citizens, onFinish }: { citizens: MemberRow[]; onFin
|
||||
const statusRef = useRef<Status>("playing");
|
||||
const scoreRef = useRef(0);
|
||||
const nextTierRef = useRef(nextTier);
|
||||
const secondTierRef = useRef(secondTier);
|
||||
const dropXRef = useRef(CONTAINER_WIDTH / 2);
|
||||
const engineRef = useRef<Matter.Engine | null>(null);
|
||||
const bodiesRef = useRef(new Map<number, Matter.Body>());
|
||||
@@ -121,8 +125,11 @@ export function MelonGame({ citizens, onFinish }: { citizens: MemberRow[]; onFin
|
||||
scoreRef.current = 0;
|
||||
statusRef.current = "playing";
|
||||
const firstNextTier = randomTier(DROP_MIN_TIER, dropMaxTier);
|
||||
const firstSecondTier = randomTier(DROP_MIN_TIER, dropMaxTier);
|
||||
nextTierRef.current = firstNextTier;
|
||||
secondTierRef.current = firstSecondTier;
|
||||
setNextTier(firstNextTier);
|
||||
setSecondTier(firstSecondTier);
|
||||
setPieces([]);
|
||||
setScore(0);
|
||||
setStatus("playing");
|
||||
@@ -146,9 +153,14 @@ export function MelonGame({ citizens, onFinish }: { citizens: MemberRow[]; onFin
|
||||
const dropped = spawnPiece(tier, x, radius + 6);
|
||||
setPieces((current) => [...current, dropped]);
|
||||
|
||||
const upcoming = randomTier(DROP_MIN_TIER, dropMaxTier);
|
||||
// La file glisse d'un cran : ce qui était annoncé en second devient la
|
||||
// pièce à viser, et un nouveau palier est tiré pour la deuxième place.
|
||||
const upcoming = secondTierRef.current;
|
||||
const newSecond = randomTier(DROP_MIN_TIER, dropMaxTier);
|
||||
nextTierRef.current = upcoming;
|
||||
secondTierRef.current = newSecond;
|
||||
setNextTier(upcoming);
|
||||
setSecondTier(newSecond);
|
||||
setDropX(dropXRef.current);
|
||||
}, [spawnPiece, setDropX, tierRadii, dropMaxTier]);
|
||||
|
||||
@@ -343,7 +355,21 @@ export function MelonGame({ citizens, onFinish }: { citizens: MemberRow[]; onFin
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center gap-3">
|
||||
<p className="font-heading text-2xl text-gold-bright">{score}</p>
|
||||
<div className="flex items-center justify-between" style={{ width: CONTAINER_WIDTH }}>
|
||||
<p className="font-heading text-2xl text-gold-bright">{score}</p>
|
||||
|
||||
{/* Deuxième pièce annoncée (après celle à viser) : juste
|
||||
informatif, taille d'affichage fixe quel que soit le vrai
|
||||
rayon du palier — pas de position à viser pour celle-ci. */}
|
||||
<div className="flex items-center gap-1.5 opacity-70">
|
||||
<span className="font-heading text-[0.6rem] tracking-wide text-marble/50 uppercase">Puis</span>
|
||||
<Avatar
|
||||
pseudo={citizens[secondTier]?.pseudo ?? "?"}
|
||||
avatarUrl={citizens[secondTier]?.avatar_url ?? null}
|
||||
size={32}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
ref={containerRef}
|
||||
|
||||
Reference in New Issue
Block a user