import React, { useState, useEffect, useRef, useCallback } from 'react'; import { Play, Pause, RotateCcw, Trophy, Flag, Zap, Fuel } from 'lucide-react'; const HillClimbRacing = () => { const [isPlaying, setIsPlaying] = useState(false); const [gameOver, setGameOver] = useState(false); const [winner, setWinner] = useState(false); const [playerPosition, setPlayerPosition] = useState(0); const [opponentPosition, setOpponentPosition] = useState(0); const [fuel, setFuel] = useState(100); const [boost, setBoost] = useState(0); const [terrain, setTerrain] = useState([]); const [gameSpeed, setGameSpeed] = useState(1); const gameLoopRef = useRef(null); const keysPressed = useRef(new Set()); // Generate realistic terrain with hills and obstacles useEffect(() => { const generateTerrain = () => { const newTerrain = []; let currentHeight = 200; for (let i = 0; i < 300; i++) { // Create natural-looking hills with varying steepness const hillFactor = Math.sin(i * 0.08) * 40 + Math.cos(i * 0.03) * 30; const noise = (Math.random() - 0.5) * 10; currentHeight = Math.max(100, Math.min(300, 200 + hillFactor + noise)); // Determine terrain type based on slope let type = 'normal'; if (i > 0) { const slope = currentHeight - newTerrain[i - 1].height; if (Math.abs(slope) > 15) { type = 'steep'; } else if (i % 25 === 0 && i > 50) { type = 'boost'; } else if (i % 40 === 0 && i > 30) { type = 'rough'; } } newTerrain.push({ height: currentHeight, type }); } setTerrain(newTerrain); }; generateTerrain(); }, []); // Handle keyboard input const handleKeyDown = useCallback((e) => { keysPressed.current.add(e.code); if (e.code === 'Space') { e.preventDefault(); if (boost > 0 && isPlaying) { setBoost(prev => Math.max(prev - 15, 0)); setGameSpeed(2); } } }, [boost, isPlaying]); const handleKeyUp = useCallback((e) => { keysPressed.current.delete(e.code); if (e.code === 'Space') { setGameSpeed(1); } }, []); useEffect(() => { window.addEventListener('keydown', handleKeyDown); window.addEventListener('keyup', handleKeyUp); return () => { window.removeEventListener('keydown', handleKeyDown); window.removeEventListener('keyup', handleKeyUp); }; }, [handleKeyDown, handleKeyUp]); // Game loop useEffect(() => { if (!isPlaying || gameOver) return; const updateGame = () => { // Update player position if (fuel > 0) { const baseSpeed = 1.2; const terrainEffect = terrain[Math.floor(playerPosition)]?.type === 'rough' ? 0.7 : 1; const steepEffect = terrain[Math.floor(playerPosition)]?.type === 'steep' ? 0.8 : 1; const boostEffect = gameSpeed; const speed = baseSpeed * terrainEffect * steepEffect * boostEffect; const newPosition = Math.min(playerPosition + speed, 299); setPlayerPosition(newPosition); // Consume fuel based on speed and terrain const fuelConsumption = 0.3 * (speed / baseSpeed); setFuel(prev => Math.max(prev - fuelConsumption, 0)); // Collect boost items if (terrain[Math.floor(playerPosition)]?.type === 'boost') { setBoost(prev => Math.min(prev + 25, 100)); } } // Update opponent AI const opponentBaseSpeed = 1.0; const opponentTerrainEffect = terrain[Math.floor(opponentPosition)]?.type === 'rough' ? 0.8 : 1; const opponentSteepEffect = terrain[Math.floor(opponentPosition)]?.type === 'steep' ? 0.9 : 1; const opponentSpeed = opponentBaseSpeed * opponentTerrainEffect * opponentSteepEffect + (Math.random() * 0.3); const newOpponentPosition = Math.min(opponentPosition + opponentSpeed, 299); setOpponentPosition(newOpponentPosition); // Check win/lose conditions if (playerPosition >= 299 && opponentPosition < 299) { setWinner(true); setGameOver(true); setIsPlaying(false); } else if (opponentPosition >= 299 && playerPosition < 299) { setWinner(false); setGameOver(true); setIsPlaying(false); } else if (fuel <= 0 && playerPosition < 299) { setWinner(false); setGameOver(true); setIsPlaying(false); } }; gameLoopRef.current = setInterval(updateGame, 50); return () => clearInterval(gameLoopRef.current); }, [isPlaying, gameOver, playerPosition, opponentPosition, fuel, boost, gameSpeed, terrain]); const startGame = () => { setIsPlaying(true); setGameOver(false); setWinner(false); setPlayerPosition(0); setOpponentPosition(0); setFuel(100); setBoost(30); setGameSpeed(1); }; const resetGame = () => { setIsPlaying(false); setGameOver(false); setWinner(false); setPlayerPosition(0); setOpponentPosition(0); setFuel(100); setBoost(30); setGameSpeed(1); }; // Calculate positions for rendering const trackLength = 1200; // Total track length in pixels const playerCarX = (playerPosition / 299) * trackLength; const opponentCarX = (opponentPosition / 299) * trackLength; // Calculate car rotation based on terrain slope const getPlayerCarRotation = () => { const currentIndex = Math.floor(playerPosition); if (currentIndex >= terrain.length - 1) return 0; const currentHeight = terrain[currentIndex].height; const nextHeight = terrain[currentIndex + 1].height; const slope = nextHeight - currentHeight; return Math.atan(slope / 4) * (180 / Math.PI); }; const getOpponentCarRotation = () => { const currentIndex = Math.floor(opponentPosition); if (currentIndex >= terrain.length - 1) return 0; const currentHeight = terrain[currentIndex].height; const nextHeight = terrain[currentIndex + 1].height; const slope = nextHeight - currentHeight; return Math.atan(slope / 4) * (180 / Math.PI); }; const playerRotation = getPlayerCarRotation(); const opponentRotation = getOpponentCarRotation(); return (
{/* Header */}

HILL CLIMB RACING

Race to the summit before your opponent!

{/* Game Stats */}
Fuel: {Math.round(fuel)}%
Boost: {Math.round(boost)}%
Distance: {Math.round(playerPosition)}m
{!gameOver ? ( <> ) : ( )}
{/* Game Area */}
{/* Sky with clouds */}
{/* Sun */}
{/* Clouds */}
{/* Mountains in background */}
{/* Finish flag */}
FINISH
{/* Terrain Track */} {/* Ground */} `L ${i * 4} ${320 - point.height}`).join(' ')} L ${trackLength} 320 Z`} fill="url(#groundGradient)" /> {/* Boost zones */} {terrain.map((point, i) => point.type === 'boost' && ( ) )} {/* Rough terrain */} {terrain.map((point, i) => point.type === 'rough' && ( ) )} {/* Steep slopes indicator */} {terrain.map((point, i) => point.type === 'steep' && i % 3 === 0 && ( ) )} {/* Cars */}
{/* Player Car - Detailed design */}
{/* Windshield */}
{/* Headlights */}
{/* Wheels */}
{/* Exhaust */}
PLAYER
{/* Opponent Car */}
{/* Windshield */}
{/* Headlights */}
{/* Wheels */}
OPPONENT
{/* Controls hint */} {!isPlaying && !gameOver && (

Press SPACE to BOOST!

Use boost strategically to climb steep hills faster

)}
{/* Game Over Modal */} {gameOver && (
{winner ? (

VICTORY!

Champion of the Hills!

) : (
X

DEFEAT!

Better luck next time!

)}

Your Distance: {Math.round(playerPosition)}m

Opponent Distance: {Math.round(opponentPosition)}m

)} {/* Instructions */}

Game Instructions

1

Press PLAY to start the race against AI opponent

2

Hold SPACEBAR to activate BOOST (consumes boost meter)

3

Collect YELLOW BOOST ZONES to refill boost

4

Avoid ROUGH TERRAIN and manage fuel carefully!

); }; export default HillClimbRacing;
Заголовок формы
Расскажите клиенту, что вам нужны его данные для связи с вами
Нажимая на кнопку, вы соглашаетесь с условиями о персональных данных
Made on
Tilda