Meta Description" name="description" />
<!DOCTYPE html>
<html>
<head>
<title>Ultimate Rocket Builder</title>
<style>
body { margin:0; overflow:hidden; }
button {
position:absolute;
padding:8px 12px;
font-size:14px;
cursor:pointer;
z-index:2;
}
#engineBtn { top:10px; left:10px; }
#fuelBtn { top:10px; left:120px; }
#finBtn { top:10px; left:250px; }
#boosterBtn { top:10px; left:350px; }
#capsuleBtn { top:10px; left:470px; }
#launchBtn { top:10px; left:600px; }
#altitude {
position:absolute;
top:50px;
left:10px;
font-size:18px;
color:white;
z-index:2;
}
</style>
</head>
<body>
<button id="engineBtn">Engine</button>
<button id="fuelBtn">Fuel</button>
<button id="finBtn">Fins</button>
<button id="boosterBtn">Booster</button>
<button id="capsuleBtn">Capsule</button>
<button id="launchBtn">Launch</button>
<div id="altitude">Height: 0 m</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128/examples/js/controls/OrbitControls.js"></script>
<script>
let scene = new THREE.Scene();
scene.background = new THREE.Color(0x444444);
let camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 100000);
camera.position.set(0,10,30);
let renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
let controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.enablePan = false;
// LIGHT
let light = new THREE.PointLight(0xffffff,2);
light.position.set(0,30,30);
scene.add(light);
// FLOOR
let floor = new THREE.Mesh(
new THREE.PlaneGeometry(200,200),
new THREE.MeshStandardMaterial({color:0x777777})
);
floor.rotation.x=-Math.PI/2;
scene.add(floor);
// STARS
let starGeo=new THREE.BufferGeometry();
let starVertices=[];
for(let i=0;i<4000;i++){
starVertices.push(
THREE.MathUtils.randFloatSpread(50000),
THREE.MathUtils.randFloatSpread(50000),
THREE.MathUtils.randFloatSpread(50000)
);
}
starGeo.setAttribute('position',
new THREE.Float32BufferAttribute(starVertices,3));
let stars=new THREE.Points(
starGeo,
new THREE.PointsMaterial({color:0xffffff})
);
stars.visible=false;
scene.add(stars);
// ROCKET
let rocket=new THREE.Group();
scene.add(rocket);
let currentHeight=4;
let thrust=0,fuel=0,velocity=0,gravity=0.02;
let launched=false,buildMode=true;
let body=new THREE.Mesh(
new THREE.CylinderGeometry(1,1,4,32),
new THREE.MeshStandardMaterial({color:0xffffff})
);
body.position.y=2;
rocket.add(body);
let nose=new THREE.Mesh(
new THREE.ConeGeometry(1,2,32),
new THREE.MeshStandardMaterial({color:0x00ccff})
);
rocket.add(nose);
let fire=new THREE.Mesh(
new THREE.ConeGeometry(0.8,2,32),
new THREE.MeshBasicMaterial({color:0xffaa00})
);
fire.position.y=-1;
fire.visible=false;
rocket.add(fire);
function updateNose(){
nose.position.y=currentHeight+1;
}
updateNose();
function addEngine(){
let engine=new THREE.Mesh(
new THREE.CylinderGeometry(0.8,1,1,32),
new THREE.MeshStandardMaterial({color:0x333333})
);
engine.position.y=0.5;
rocket.add(engine);
thrust+=0.5;
}
function addFuel(){
let tank=new THREE.Mesh(
new THREE.CylinderGeometry(1,1,2,32),
new THREE.MeshStandardMaterial({color:0xff4444})
);
tank.position.y=currentHeight+1;
rocket.add(tank);
currentHeight+=2;
fuel+=80;
updateNose();
}
function addFins(){
let finGeo=new THREE.BoxGeometry(0.3,1,1);
let finMat=new THREE.MeshStandardMaterial({color:0xff0000});
let fin1=new THREE.Mesh(finGeo,finMat);
fin1.position.set(1,1,0);
rocket.add(fin1);
let fin2=fin1.clone();
fin2.position.set(-1,1,0);
rocket.add(fin2);
}
function addBooster(){
let booster=new THREE.Mesh(
new THREE.CylinderGeometry(0.5,0.5,3,32),
new THREE.MeshStandardMaterial({color:0xaaaaaa})
);
booster.position.set(2,2,0);
rocket.add(booster);
thrust+=0.8;
}
function addCapsule(){
let capsule=new THREE.Mesh(
new THREE.SphereGeometry(1,32,32),
new THREE.MeshStandardMaterial({color:0xffffff})
);
capsule.position.y=currentHeight+2;
rocket.add(capsule);
}
document.getElementById("engineBtn").onclick=()=>{if(buildMode)addEngine();}
document.getElementById("fuelBtn").onclick=()=>{if(buildMode)addFuel();}
document.getElementById("finBtn").onclick=()=>{if(buildMode)addFins();}
document.getElementById("boosterBtn").onclick=()=>{if(buildMode)addBooster();}
document.getElementById("capsuleBtn").onclick=()=>{if(buildMode)addCapsule();}
document.getElementById("launchBtn").onclick=()=>{
if(fuel>0 && thrust>0){
launched=true;
buildMode=false;
scene.background=new THREE.Color(0x87CEEB);
} else alert("Add Engine & Fuel First!");
};
function animate(){
requestAnimationFrame(animate);
if(launched){
if(fuel>0){
velocity+=thrust;
fuel-=0.5;
fire.visible=true;
}else{
fire.visible=false;
}
velocity-=gravity;
// Parachute slow landing
if(rocket.position.y<100 && velocity<0){
velocity*=0.95;
}
rocket.position.y+=velocity;
// Crash detection
if(rocket.position.y<=0 && velocity<-2){
alert("Rocket Crashed π₯");
launched=false;
}
if(rocket.position.y>3000){
scene.background=new THREE.Color(0x000000);
stars.visible=true;
}
}
let desired=new THREE.Vector3(
0,
rocket.position.y+12,
30
);
camera.position.lerp(desired,0.05);
controls.target.copy(rocket.position);
controls.update();
document.getElementById("altitude").innerText=
"Height: "+rocket.position.y.toFixed(2)+" m";
renderer.render(scene,camera);
}
animate();
</script>
</body>
</html>3
3
131KB
621KB
2,798.0ms
216.0ms
2,798.0ms