import React, { useState, useEffect, useRef } from 'react'; import { Clock, AlertTriangle, Zap, GitBranch, GitMerge, Play, Pause, RotateCcw, ChevronRight } from 'lucide-react'; export default function TimelineWeaver() { // Game state const [gameState, setGameState] = useState({ level: 1, playing: false, timelines: [], events: [], paradoxes: [], timeSpeed: 1, tutorial: true, tutorialStep: 0, completed: false, selectedTimeline: null, selectedEvent: null, showParallelUniverses: false, }); const canvasRef = useRef(null); const animationRef = useRef(null); // Initialize game useEffect(() => { initializeLevel(gameState.level); return () => { if (animationRef.current) { cancelAnimationFrame(animationRef.current); } }; }, [gameState.level]); // Initialize a level with timelines, events, and paradoxes const initializeLevel = (level) => { let timelines = []; let events = []; let paradoxes = []; // Level 1: Simple introduction with two timelines if (level === 1) { timelines = [ { id: 1, name: "Alpha", color: "#ffd700", points: generateTimelinePoints(0), active: true }, { id: 2, name: "Beta", color: "#9333ea", points: generateTimelinePoints(1), active: true }, ]; events = [ { id: 1, timelineId: 1, position: 0.2, name: "Invention", resolved: false, connectedTo: null }, { id: 2, timelineId: 2, position: 0.5, name: "Discovery", resolved: false, connectedTo: null }, { id: 3, timelineId: 1, position: 0.7, name: "Paradox Event", resolved: false, connectedTo: null }, ]; paradoxes = [ { id: 1, description: "Invention occurs without prior discovery", eventIds: [1, 2], resolved: false } ]; } else if (level === 2) { // More complex level with three timelines timelines = [ { id: 1, name: "Alpha", color: "#ffd700", points: generateTimelinePoints(0), active: true }, { id: 2, name: "Beta", color: "#9333ea", points: generateTimelinePoints(1), active: true }, { id: 3, name: "Gamma", color: "#0d9488", points: generateTimelinePoints(2), active: true }, ]; events = [ { id: 1, timelineId: 1, position: 0.2, name: "Origin Event", resolved: false, connectedTo: null }, { id: 2, timelineId: 2, position: 0.3, name: "Consequence A", resolved: false, connectedTo: null }, { id: 3, timelineId: 3, position: 0.4, name: "Consequence B", resolved: false, connectedTo: null }, { id: 4, timelineId: 1, position: 0.6, name: "Future Event", resolved: false, connectedTo: null }, { id: 5, timelineId: 2, position: 0.7, name: "Paradox Event", resolved: false, connectedTo: null }, ]; paradoxes = [ { id: 1, description: "Future event occurs before its cause", eventIds: [2, 4], resolved: false }, { id: 2, description: "Consequence B lacks causal origin", eventIds: [1, 3], resolved: false } ]; } setGameState(prev => ({ ...prev, timelines, events, paradoxes, playing: false, completed: false, selectedTimeline: null, selectedEvent: null, })); }; // Generate points for timeline visualization const generateTimelinePoints = (index) => { const baseY = 100 + index * 120; const points = []; for (let i = 0; i <= 100; i++) { const x = i * 10; // Add some gentle waves to make timelines look more interesting const y = baseY + Math.sin(i * 0.05) * 10; points.push({ x, y }); } return points; }; // Handle timeline selection const selectTimeline = (id) => { setGameState(prev => ({ ...prev, selectedTimeline: prev.selectedTimeline === id ? null : id, selectedEvent: null })); }; // Handle event selection const selectEvent = (id) => { setGameState(prev => ({ ...prev, selectedEvent: prev.selectedEvent === id ? null : id })); }; // Connect events to resolve paradoxes const connectEvents = (sourceId, targetId) => { if (sourceId === targetId) return; setGameState(prev => { const updatedEvents = prev.events.map(event => { if (event.id === sourceId) { return { ...event, connectedTo: targetId }; } return event; }); // Check if this connection resolves any paradoxes const updatedParadoxes = prev.paradoxes.map(paradox => { const { eventIds } = paradox; if (eventIds.includes(sourceId) && eventIds.includes(targetId)) { return { ...paradox, resolved: true }; } return paradox; }); // Check if all paradoxes are resolved const allResolved = updatedParadoxes.every(p => p.resolved); return { ...prev, events: updatedEvents, paradoxes: updatedParadoxes, completed: allResolved, selectedEvent: null }; }); }; // Handle connecting selected event to another const handleEventConnection = (targetId) => { if (gameState.selectedEvent) { connectEvents(gameState.selectedEvent, targetId); } }; // Toggle play/pause const togglePlay = () => { setGameState(prev => ({ ...prev, playing: !prev.playing })); }; // Reset level const resetLevel = () => { initializeLevel(gameState.level); }; // Advance to next level const nextLevel = () => { setGameState(prev => ({ ...prev, level: prev.level + 1, tutorial: prev.level === 1, // Show tutorial only for level 1 tutorialStep: 0 })); }; // Toggle parallel universe view const toggleParallelUniverses = () => { setGameState(prev => ({ ...prev, showParallelUniverses: !prev.showParallelUniverses })); }; // Advance tutorial const advanceTutorial = () => { setGameState(prev => ({ ...prev, tutorialStep: prev.tutorialStep + 1, tutorial: prev.tutorialStep < 3 // End tutorial after step 3 })); }; // Tutorial content const getTutorialContent = () => { switch (gameState.tutorialStep) { case 0: return "Welcome to Timeline Weaver! Your goal is to resolve temporal paradoxes by connecting events across timelines."; case 1: return "Click on an event to select it, then click on another event to create a causal connection between them."; case 2: return "Paradoxes are shown in the right panel. Connect the related events to resolve them."; case 3: return "Complete all paradox resolutions to finish the level and advance to the next challenge!"; default: return ""; } }; return (
{getTutorialContent()}