import React, { useState, useEffect, useRef, useCallback } from 'react'; import { ArrowLeft, Trophy, Sparkles, Moon, Sun } from 'lucide-react'; // --- ZAAWANSOWANY MODEL KOTA (DetailedKitty) --- interface DetailedKittyProps { isJumping: boolean; isNight: boolean; isGameOver: boolean; } const DetailedKitty: React.FC = ({ isJumping, isNight, isGameOver }) => { const mainColor = isGameOver ? (isNight ? '#475569' : '#cbd5e1') : (isNight ? '#f8fafc' : '#f472b6'); const stripeColor = isNight ? '#cbd5e1' : '#ec4899'; const earColor = isNight ? '#334155' : '#fbcfe8'; return (
{/* OGON */}
{/* TUŁÓW */}
{/* Paski dekoracyjne */}
{/* GŁOWA */}
{/* Uszy */}
{/* Oczy */}
{isGameOver ? 'x' :
}
{isGameOver ? 'x' :
}
{/* Wąsy */}
{/* ŁAPKI (Animowane) */}
); }; // --- GŁÓWNY KOMPONENT GRY --- export const KittyGame: React.FC<{ onBack: () => void }> = ({ onBack }) => { const [isPlaying, setIsPlaying] = useState(false); const [gameOver, setGameOver] = useState(false); const [score, setScore] = useState(0); const [highScore, setHighScore] = useState(() => { const saved = localStorage.getItem('kittyHighScore'); return saved ? parseInt(saved, 10) : 0; }); const [displayKittyY, setDisplayKittyY] = useState(0); const [displayObstacleX, setDisplayObstacleX] = useState(600); const isNight = Math.floor(score / 10) % 2 === 1; const kittyYRef = useRef(0); const obstacleXRef = useRef(600); const velocityRef = useRef(0); const scoreRef = useRef(0); const requestRef = useRef(0); const GRAVITY = 0.6; const JUMP_STRENGTH = -11; const GROUND_Y = 0; const endGame = useCallback(() => { setGameOver(true); setIsPlaying(false); const currentHighScore = parseInt(localStorage.getItem('kittyHighScore') || '0', 10); if (scoreRef.current > currentHighScore) { setHighScore(scoreRef.current); localStorage.setItem('kittyHighScore', scoreRef.current.toString()); } }, []); const startGame = useCallback(() => { setIsPlaying(true); setGameOver(false); setScore(0); scoreRef.current = 0; kittyYRef.current = 0; obstacleXRef.current = 600; velocityRef.current = 0; setDisplayKittyY(0); setDisplayObstacleX(600); }, []); const jump = useCallback(() => { if (kittyYRef.current <= GROUND_Y && !gameOver && isPlaying) { velocityRef.current = JUMP_STRENGTH; } }, [gameOver, isPlaying]); useEffect(() => { const update = () => { if (gameOver || !isPlaying) return; velocityRef.current += GRAVITY; kittyYRef.current -= velocityRef.current; if (kittyYRef.current <= GROUND_Y) { kittyYRef.current = GROUND_Y; velocityRef.current = 0; } obstacleXRef.current -= 5 + (scoreRef.current * 0.2); if (obstacleXRef.current < -50) { obstacleXRef.current = 650; scoreRef.current += 1; setScore(scoreRef.current); } // DOSTOSOWANA KOLIZJA: Uwzględnia większy model kota if (obstacleXRef.current < 110 && obstacleXRef.current > 30 && kittyYRef.current < 45) { endGame(); return; } setDisplayKittyY(kittyYRef.current); setDisplayObstacleX(obstacleXRef.current); requestRef.current = requestAnimationFrame(update); }; if (isPlaying && !gameOver) { requestRef.current = requestAnimationFrame(update); } return () => cancelAnimationFrame(requestRef.current); }, [isPlaying, gameOver, endGame]); useEffect(() => { const handleKey = (e: KeyboardEvent) => { if (e.code === 'Space') { e.preventDefault(); if (!isPlaying || gameOver) startGame(); else jump(); } }; window.addEventListener('keydown', handleKey); return () => window.removeEventListener('keydown', handleKey); }, [isPlaying, gameOver, startGame, jump]); return (
{ if (!isPlaying || gameOver) startGame(); else jump(); }} > {/* Niebo */}
{/* Wyniki */}
Score: {score}
High: {highScore}
{/* KOTEK */}
2} isNight={isNight} isGameOver={gameOver} />
{/* PRZESZKODA (Kłębek wełny) */}
{/* Ziemia */}
{[...Array(9)].map((_, i) => 🐾)}
{/* Ekrany informacyjne */} {!isPlaying && !gameOver && (
)} {gameOver && (

Meow! 😿

Score: {score}

)}
); };