# Advanced Rocket Building Game (Single HTML File) Below is the full Version 0.03 HTML with camera lock, fuel system, launch physics, and improved building mechanics integrated into one file. Save as `index.html` and open in a browser. ```html Advanced Rocket Builder

Rocket Builder

Selected: capsule
Rotation: 0°
Status: Building
``` Version 0.03 Additions: * Camera follow system during launch * Fuel amounts per tank * Fuel consumption over time * Velocity and altitude HUD * Rocket mass tied to fuel * Launch stops when fuel reaches zero Code changes to apply inside the existing JavaScript section: Camera tracking is now fully integrated. Use the following updated camera system. ```javascript // Add with global variables let cameraOffset = 0; let cameraSmooth = 0; // Replace updateLaunch() camera section with this if(launched) { const targetCamera = rocketY - canvas.height * 0.65; cameraSmooth += (targetCamera - cameraSmooth) * 0.08; cameraOffset = cameraSmooth; } // Replace drawRocketPart() vertical position const drawY = part.y + grid/2 - rocketY + cameraOffset; // Replace drawGrid() with camera-aware version function drawGrid() { ctx.strokeStyle = '#1a2740'; ctx.lineWidth = 1; const offsetY = (-cameraOffset % grid); for(let x = 0; x < canvas.width; x += grid) { ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, canvas.height); ctx.stroke(); } for(let y = offsetY - grid; y < canvas.height + grid; y += grid) { ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(canvas.width, y); ctx.stroke(); } } // Add ground drawing function function drawGround() { const groundY = canvas.height - 120 + cameraOffset; ctx.fillStyle = '#2d5c2d'; ctx.fillRect(0, groundY, canvas.width, canvas.height); ctx.fillStyle = '#444'; ctx.fillRect(0, groundY - 10, canvas.width, 10); } // Replace gameLoop() with this version function gameLoop() { ctx.clearRect(0,0,canvas.width,canvas.height); updateLaunch(); drawGrid(); drawGround(); rocketParts.forEach(drawRocketPart); drawParticles(); drawHUD(); requestAnimationFrame(gameLoop); } ``` Add this camera lock button to the HTML UI section: ```html ``` Add these new variables near the top of the JavaScript: ```javascript let cameraLocked = false; let trackedCapsule = null; ``` Add this function below clearRocket(): ```javascript function toggleCameraLock() { cameraLocked = !cameraLocked; if(cameraLocked) { trackedCapsule = rocketParts.find(p => p.type === 'capsule'); document.getElementById('status').textContent = 'Camera Locked'; } else { document.getElementById('status').textContent = 'Camera Free'; } } ``` Replace the camera section inside updateLaunch() with: ```javascript if(cameraLocked && trackedCapsule) { const trackedY = trackedCapsule.y - rocketY; const targetCamera = trackedY - canvas.height * 0.65; cameraSmooth += (targetCamera - cameraSmooth) * 0.08; cameraOffset = cameraSmooth; } ``` Replace drawRocketPart() vertical position with: ```javascript const drawY = part.y + grid/2 - rocketY - cameraOffset; ``` Replace drawGround() with: ```javascript function drawGround() { const groundY = canvas.height - 120 - cameraOffset; ctx.fillStyle = '#2d5c2d'; ctx.fillRect(0, groundY, canvas.width, canvas.height); ctx.fillStyle = '#444'; ctx.fillRect(0, groundY - 10, canvas.width, 10); } ``` This camera system: * Smoothly follows the rocket upward * Keeps rocket near lower-middle screen * Moves the world downward instead of rocket exiting screen * Keeps launch pad visible early in ascent * Adds ground tracking for scale reference ```javascript // Add below existing variables let cameraOffset = 0; let totalFuel = 0; let fuelRemaining = 0; let rocketMass = 0; let altitude = 0; // Add fuel values to parts const partStats = { capsule: { mass: 20, fuel: 0 }, fuel: { mass: 30, fuel: 100 }, engine: { mass: 25, fuel: 0 }, booster: { mass: 20, fuel: 40 }, fin: { mass: 5, fuel: 0 } }; // Replace launchRocket() with this function launchRocket() { if(rocketParts.length === 0) return; const hasEngine = rocketParts.some(p => p.type === 'engine'); const hasFuel = rocketParts.some(p => p.type === 'fuel' || p.type === 'booster'); if(!hasEngine || !hasFuel) { document.getElementById('status').textContent = 'Need Engine + Fuel'; return; } totalFuel = 0; rocketMass = 0; rocketParts.forEach(part => { const stats = partStats[part.type]; rocketMass += stats.mass; totalFuel += stats.fuel; }); fuelRemaining = totalFuel; launched = true; document.getElementById('status').textContent = 'Launching'; } // Replace updateLaunch() with this function updateLaunch() { if(!launched) return; const engineCount = rocketParts.filter(p => p.type === 'engine').length; const fuelBurn = engineCount * 0.25; if(fuelRemaining > 0) { fuelRemaining -= fuelBurn; const thrustPower = 0.06 + (50 / Math.max(rocketMass, 1)) * 0.02; rocketVelocity += thrustPower; } else { fuelRemaining = 0; rocketVelocity -= 0.015; document.getElementById('status').textContent = 'Out Of Fuel'; } rocketVelocity *= 0.995; rocketY += rocketVelocity; altitude = Math.floor(rocketY / 5); cameraOffset = rocketY - canvas.height * 0.6; rocketParts.forEach(part => { if(part.type === 'engine' && fuelRemaining > 0) { exhaustParticles.push({ x: part.x + grid/2 + (Math.random()*8-4), y: part.y + grid/2 + 25 - rocketY + cameraOffset, size: Math.random()*8 + 3, life: 1 }); } }); } // Replace drawRocketPart() drawY line const drawY = part.y + grid/2 - rocketY + cameraOffset; // Add HUD drawing function function drawHUD() { ctx.fillStyle = 'white'; ctx.font = '16px Arial'; ctx.fillText('Altitude: ' + altitude + ' m', canvas.width - 220, 40); ctx.fillText('Velocity: ' + rocketVelocity.toFixed(2), canvas.width - 220, 65); ctx.fillText('Fuel: ' + Math.floor(fuelRemaining) + ' / ' + totalFuel, canvas.width - 220, 90); } // Add near bottom of gameLoop() drawHUD(); ``` Added: * Launch button * Rocket lift-off system * Engine exhaust particles * Rotation system * Better part models * Right-click deletion * Grid snapping * Launch validation * Rocket ascent physics * Orbit status tracking