import { useState, useEffect, useRef, Suspense } from 'react';
import { Canvas, useFrame, useLoader } from '@react-three/fiber';
import { OrbitControls, Stars, Text, Environment } from '@react-three/drei';
import { TextureLoader } from 'three';
import { Physics, useBox, usePlane } from '@react-three/cannon';
function Ground() {
const [ref] = usePlane(() => ({
rotation: [-Math.PI / 2, 0, 0],
position: [0, -2, 0],
material: { friction: 1 }
}));
return (
);
}
function Rocket({ position, rotation, thrust }) {
const rocketRef = useRef();
// Rocket body
return (
{/* Main body */}
{/* Nose cone */}
{/* Fins */}
{[0, 1, 2, 3].map((i) => (
))}
{/* Thrust effect */}
{thrust > 0 && (
)}
);
}
function GameUI({ altitude, velocity, fuel, gameState, score, onReset, onStart }) {
return (
Flight Data
Altitude: {Math.round(altitude)}m
Velocity: {Math.round(velocity)}m/s
Fuel: {Math.round(fuel)}%
Score: {score}
{gameState === 'ready' && (
)}
{(gameState === 'crashed' || gameState === 'landed') && (
{gameState === 'crashed' ? '💥 Crashed!' : '🎉 Landed!'}
)}
);
}
function Scene({ gameState, setGameState, setScore }) {
const [rocketPosition, setRocketPosition] = useState([0, 1, 0]);
const [rocketRotation, setRocketRotation] = useState([0, 0, 0]);
const [velocity, setVelocity] = useState([0, 0, 0]);
const [fuel, setFuel] = useState(100);
const [thrust, setThrust] = useState(0);
const gravity = -9.81;
const thrustPower = 15;
const fuelConsumption = 0.5;
useFrame((state, delta) => {
if (gameState !== 'flying') return;
// Update physics
const newVelocity = [...velocity];
newVelocity[1] += (gravity + thrust) * delta;
const newPosition = [
rocketPosition[0] + newVelocity[0] * delta,
rocketPosition[1] + newVelocity[1] * delta,
rocketPosition[2] + newVelocity[2] * delta,
];
// Ground collision
if (newPosition[1] <= 0) {
if (Math.abs(newVelocity[1]) > 10) {
setGameState('crashed');
} else {
setGameState('landed');
setScore(prev => prev + Math.round(fuel));
}
newPosition[1] = 0;
setVelocity([0, 0, 0]);
} else {
setVelocity(newVelocity);
}
setRocketPosition(newPosition);
// Update fuel
if (thrust > 0) {
setFuel(prev => {
const newFuel = prev - fuelConsumption;
if (newFuel <= 0) {
setThrust(0);
return 0;
}
return newFuel;
});
}
});
useEffect(() => {
const handleKeyDown = (e) => {
if (gameState !== 'flying') return;
if (e.key === 'ArrowUp' && fuel > 0) {
setThrust(thrustPower);
}
};
const handleKeyUp = (e) => {
if (e.key === 'ArrowUp') {
setThrust(0);
}
};
window.addEventListener('keydown', handleKeyDown);
window.addEventListener('keyup', handleKeyUp);
return () => {
window.removeEventListener('keydown', handleKeyDown);
window.removeEventListener('keyup', handleKeyUp);
};
}, [gameState, fuel]);
return (
<>
>
);
}
export default function RocketSimulator() {
const [gameState, setGameState] = useState('ready');
const [score, setScore] = useState(0);
const handleStart = () => {
setGameState('flying');
};
const handleReset = () => {
setGameState('ready');
};
return (
);
}