# 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