import React, { useEffect, useRef, useState } from "react"; import { Box, Typography, useTheme, useMediaQuery } from "@mui/material"; import { motion, useAnimation } from "framer-motion"; import { useSoundSystem } from "../contexts/SoundContext"; // Animation timing configuration const SLOT_ANIMATION_DURATION = 2; // Duration of each slot animation const SLOT_SPEED = 1; // Base speed of the slot animation (higher = faster) const TOTAL_ANIMATION_DURATION = 1; // Total duration for each slot reel in seconds const SLOT_START_DELAY = 0.75; // Delay between each slot start in seconds // Random words for each category const RANDOM_STYLES = [ "Manga", "Comics", "Franco-Belge", "Steampunk", "Cyberpunk", ]; const RANDOM_GENRES = ["Action", "Fantasy", "Sci-Fi", "Mystery", "Horror"]; const RANDOM_EPOCHS = ["Future", "Medieval", "Modern", "Ancient", "Victorian"]; const SlotReel = ({ words, isActive, finalValue, onComplete, delay = 0 }) => { const containerRef = useRef(null); const controls = useAnimation(); const [reelItems, setReelItems] = useState([]); const [isVisible, setIsVisible] = useState(false); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down("sm")); const { playSound } = useSoundSystem(); const lastPositionRef = useRef(0); const itemHeightRef = useRef(0); useEffect(() => { if (isActive) { const repeatedWords = Array(20) .fill([...words]) .flat() .map((word) => ({ word, id: Math.random() })); repeatedWords.push({ word: finalValue, id: "final" }); setReelItems(repeatedWords); const itemHeight = isMobile ? 60 : 80; itemHeightRef.current = itemHeight; const totalHeight = repeatedWords.length * itemHeight; setTimeout(() => { setIsVisible(true); controls .start({ y: [-itemHeight, -totalHeight + itemHeight], transition: { duration: TOTAL_ANIMATION_DURATION / SLOT_SPEED, ease: [0.25, 0.1, 0.25, 1.0], times: [0, 1], onUpdate: (latest) => { // Calculer l'index du mot actuel basé sur la position const currentPosition = Math.abs(latest); const currentIndex = Math.floor(currentPosition / itemHeight); // Si on a changé de mot, jouer le son if ( Math.floor(lastPositionRef.current / itemHeight) !== currentIndex ) { // Vérifier si c'est le dernier mot (final) const isFinalWord = currentIndex === repeatedWords.length - 1; // Jouer le son approprié if (isFinalWord) { playSound("lock"); } else { playSound("tick", "normal"); } } lastPositionRef.current = currentPosition; }, }, }) .then(() => { onComplete?.(); }); }, delay * SLOT_START_DELAY * 1000); } return () => { lastPositionRef.current = 0; }; }, [isActive, finalValue, words, delay, isMobile, playSound]); return ( {reelItems.map(({ word, id }) => ( {word} ))} ); }; const SlotSection = ({ label, value, delay, isActive, onComplete, words }) => { const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down("sm")); return ( {label} ); }; export const UniverseSlotMachine = ({ style, genre, epoch, activeIndex = 0, onComplete, }) => { const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down("sm")); const handleSlotComplete = (index) => { if (index === 2 && activeIndex >= 2) { setTimeout(() => { onComplete?.(); }, SLOT_ANIMATION_DURATION * 1000); } }; return ( Finding a universe = 0} onComplete={() => handleSlotComplete(0)} /> = 1} onComplete={() => handleSlotComplete(1)} /> = 2} onComplete={() => handleSlotComplete(2)} /> ); };