import React, { useState, useEffect, useRef } from 'react'; import { ChevronUp, ChevronDown, ChevronLeft, ChevronRight, Map, Settings, Info } from 'lucide-react'; export default function VolvoSimulator() { // Game state const [speed, setSpeed] = useState(0); const [rpm, setRpm] = useState(0); const [gear, setGear] = useState(1); const [position, setPosition] = useState({ x: 50, y: 50 }); const [direction, setDirection] = useState(0); // 0-359 degrees const [engineStarted, setEngineStarted] = useState(false); const [showMap, setShowMap] = useState(false); const [showSettings, setShowSettings] = useState(false); const [showInfo, setShowInfo] = useState(true); const [fuel, setFuel] = useState(100); const [distance, setDistance] = useState(0); const [currentLocation, setCurrentLocation] = useState("Praha"); // Game world data const locations = [ { name: "Praha", x: 50, y: 50, description: "Hlavní město České republiky" }, { name: "Brno", x: 70, y: 70, description: "Druhé největší město v ČR" }, { name: "Ostrava", x: 85, y: 40, description: "Průmyslové město na severovýchodě" }, { name: "Plzeň", x: 30, y: 55, description: "Domov slavného piva" }, { name: "Olomouc", x: 75, y: 55, description: "Historické město s univerzitou" }, { name: "České Budějovice", x: 45, y: 80, description: "Město na jihu Čech" }, { name: "Karlovy Vary", x: 20, y: 30, description: "Lázeňské město" }, { name: "Liberec", x: 40, y: 20, description: "Město pod Ještědem" }, ]; // Car specifications const carSpecs = { model: "Volvo S60 5D", year: 2004, engine: "2.4L 5-válec", power: "170 koní", transmission: "5-stupňová manuální", topSpeed: 220, acceleration: "8.5s (0-100 km/h)", weight: "1550 kg", }; // Key state tracking const [keysPressed, setKeysPressed] = useState({ up: false, down: false, left: false, right: false, }); const gameLoopRef = useRef(null); const canvasRef = useRef(null); // Handle key presses useEffect(() => { const handleKeyDown = (e) => { if (e.key === 'ArrowUp' || e.key === 'w') { setKeysPressed(prev => ({ ...prev, up: true })); } else if (e.key === 'ArrowDown' || e.key === 's') { setKeysPressed(prev => ({ ...prev, down: true })); } else if (e.key === 'ArrowLeft' || e.key === 'a') { setKeysPressed(prev => ({ ...prev, left: true })); } else if (e.key === 'ArrowRight' || e.key === 'd') { setKeysPressed(prev => ({ ...prev, right: true })); } else if (e.key === 'm') { setShowMap(prev => !prev); } else if (e.key === 'e') { setEngineStarted(prev => !prev); } else if (e.key === 'Escape') { setShowSettings(prev => !prev); } else if (e.key === 'i') { setShowInfo(prev => !prev); } }; const handleKeyUp = (e) => { if (e.key === 'ArrowUp' || e.key === 'w') { setKeysPressed(prev => ({ ...prev, up: false })); } else if (e.key === 'ArrowDown' || e.key === 's') { setKeysPressed(prev => ({ ...prev, down: false })); } else if (e.key === 'ArrowLeft' || e.key === 'a') { setKeysPressed(prev => ({ ...prev, left: false })); } else if (e.key === 'ArrowRight' || e.key === 'd') { setKeysPressed(prev => ({ ...prev, right: false })); } }; window.addEventListener('keydown', handleKeyDown); window.addEventListener('keyup', handleKeyUp); return () => { window.removeEventListener('keydown', handleKeyDown); window.removeEventListener('keyup', handleKeyUp); }; }, []); // Game loop useEffect(() => { if (!engineStarted) { setSpeed(0); setRpm(0); return; } const gameLoop = () => { // Update RPM based on acceleration/deceleration let newRpm = rpm; if (keysPressed.up && speed < carSpecs.topSpeed) { newRpm = Math.min(7000, rpm + 100); } else if (keysPressed.down) { newRpm = Math.max(800, rpm - 200); } else { // Idle RPM when no keys are pressed newRpm = rpm > 800 ? rpm - 50 : 800; } setRpm(newRpm); // Update speed based on RPM let newSpeed = speed; if (newRpm > 1500 && keysPressed.up) { newSpeed = Math.min(carSpecs.topSpeed, speed + 0.5); } else if (keysPressed.down) { newSpeed = Math.max(0, speed - 1); } else { // Gradual deceleration newSpeed = Math.max(0, speed - 0.2); } setSpeed(newSpeed); // Update gear based on speed let newGear = gear; if (newSpeed < 20) newGear = 1; else if (newSpeed < 40) newGear = 2; else if (newSpeed < 70) newGear = 3; else if (newSpeed < 100) newGear = 4; else newGear = 5; setGear(newGear); // Update direction based on steering let newDirection = direction; if (keysPressed.left && speed > 0) { newDirection = (direction - 2 + 360) % 360; } else if (keysPressed.right && speed > 0) { newDirection = (direction + 2) % 360; } setDirection(newDirection); // Update position based on speed and direction if (speed > 0) { const radians = (newDirection * Math.PI) / 180; const deltaX = Math.sin(radians) * (speed / 50); const deltaY = -Math.cos(radians) * (speed / 50); setPosition(prev => ({ x: Math.max(0, Math.min(100, prev.x + deltaX)), y: Math.max(0, Math.min(100, prev.y + deltaY)) })); // Update distance traveled setDistance(prev => prev + (speed / 3600)); // Update fuel setFuel(prev => Math.max(0, prev - (speed / 10000))); } // Check if near any locations const nearestLocation = locations.find(loc => { const distance = Math.sqrt( Math.pow(loc.x - position.x, 2) + Math.pow(loc.y - position.y, 2) ); return distance < 5; }); if (nearestLocation && nearestLocation.name !== currentLocation) { setCurrentLocation(nearestLocation.name); } // Draw the scene drawScene(); }; gameLoopRef.current = setInterval(gameLoop, 50); return () => { clearInterval(gameLoopRef.current); }; }, [engineStarted, keysPressed, speed, rpm, direction, position, gear, fuel, distance, currentLocation]); // Draw the scene const drawScene = () => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext('2d'); const width = canvas.width; const height = canvas.height; // Clear canvas ctx.clearRect(0, 0, width, height); // Draw sky const gradient = ctx.createLinearGradient(0, 0, 0, height / 2); gradient.addColorStop(0, '#1a3a63'); gradient.addColorStop(1, '#87CEEB'); ctx.fillStyle = gradient; ctx.fillRect(0, 0, width, height / 2); // Draw ground const groundGradient = ctx.createLinearGradient(0, height / 2, 0, height); groundGradient.addColorStop(0, '#2c5e4c'); groundGradient.addColorStop(1, '#8b5a2b'); ctx.fillStyle = groundGradient; ctx.fillRect(0, height / 2, width, height / 2); // Draw road ctx.fillStyle = '#555555'; ctx.fillRect(0, height / 2, width, height / 4); // Draw road markings ctx.strokeStyle = '#FFFFFF'; ctx.setLineDash([20, 20]); ctx.beginPath(); ctx.moveTo(0, height / 2 + height / 8); ctx.lineTo(width, height / 2 + height / 8); ctx.stroke(); // Draw dashboard ctx.fillStyle = '#333333'; ctx.fillRect(0, height * 0.75, width, height * 0.25); // Draw speedometer ctx.fillStyle = '#FFFFFF'; ctx.font = '16px Inter, sans-serif'; ctx.fillText(`${Math.round(speed)} km/h`, width * 0.1, height * 0.85); // Draw RPM gauge ctx.fillText(`${Math.round(rpm)} RPM`, width * 0.3, height * 0.85); // Draw gear indicator ctx.fillText(`Převod: ${gear}`, width * 0.5, height * 0.85); // Draw fuel gauge ctx.fillText(`Palivo: ${Math.round(fuel)}%`, width * 0.7, height * 0.85); // Draw steering wheel ctx.strokeStyle = '#AAAAAA'; ctx.lineWidth = 3; ctx.setLineDash([]); ctx.beginPath(); ctx.arc(width / 2, height * 0.9, 30, 0, Math.PI * 2); ctx.stroke(); // Draw steering wheel spokes based on direction const steeringAngle = ((direction % 360) / 360) * Math.PI * 2; ctx.beginPath(); ctx.moveTo(width / 2, height * 0.9); ctx.lineTo( width / 2 + Math.cos(steeringAngle) * 25, height * 0.9 + Math.sin(steeringAngle) * 25 ); ctx.stroke(); ctx.beginPath(); ctx.moveTo(width / 2, height * 0.9); ctx.lineTo( width / 2 + Math.cos(steeringAngle + Math.PI) * 25, height * 0.9 + Math.sin(steeringAngle + Math.PI) * 25 ); ctx.stroke(); }; // Initialize canvas useEffect(() => { const canvas = canvasRef.current; if (canvas) { canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; drawScene(); } const handleResize = () => { if (canvas) { canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; drawScene(); } }; window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); return (
{/* Game canvas */}
{/* HUD elements */}
Volvo S60 5D (2004)
{currentLocation}
{distance.toFixed(1)} km
{/* Controls overlay */}
{/* Engine start button */} {/* Mobile controls */}
{/* Map overlay */} {showMap && (

Mapa České republiky

{/* Draw map locations */} {locations.map((loc, index) => (
))} {/* Draw player position */}
{/* Location labels */} {locations.map((loc, index) => (
{loc.name}
))}

Aktuální poloha: {currentLocation}

Souřadnice: X: {position.x.toFixed(1)}, Y: {position.y.toFixed(1)}

Směr: {direction}°

)} {/* Settings overlay */} {showSettings && (

Nastavení

Ovládání

  • W / ↑ - Zrychlit
  • S / ↓ - Zpomalit / Brzdit
  • A / ← - Zatočit doleva
  • D / → - Zatočit doprava
  • E - Nastartovat/Vypnout motor
  • M - Zobrazit mapu
  • I - Informace o vozidle
  • ESC - Nastavení

Grafika

Kvalita grafiky

Zvuk

Hlasitost
)} {/* Vehicle info overlay */} {showInfo && (

Volvo S60 5D (2004)

Volvo S60
{Object.entries(carSpecs).map(([key, value]) => (
{key}
{value}
))}

Statistiky jízdy

Ujetá vzdálenost
{distance.toFixed(1)} km
Aktuální rychlost
{Math.round(speed)} km/h
Aktuální otáčky
{Math.round(rpm)} RPM
Palivo
{Math.round(fuel)}%
)} {/* Welcome screen */} {!engineStarted && distance === 0 && (

Volvo S60 Simulator

Česká republika

Volvo S60

Vítejte v simulátoru Volvo S60! Prozkoumejte krásy České republiky v tomto klasickém švédském voze z roku 2004.

Použijte klávesy W, A, S, D nebo šipky pro ovládání vozidla. Stiskněte M pro zobrazení mapy, I pro informace o vozidle a ESC pro nastavení.
)}
); }