This model didn't return a displayable web page for this challenge.
View raw output
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Autonomous Drone Simulator</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<style>
body { margin: 0; overflow: hidden; }
canvas { display: block; }
#info {
position: absolute;
top: 10px;
left: 10px;
color: white;
background-color: rgba(0,0,0,0.5);
padding: 10px;
border-radius: 5px;
font-family: Arial, sans-serif;
}
#controls {
position: absolute;
top: 10px;
right: 10px;
color: white;
background-color: rgba(0,0,0,0.5);
padding: 10px;
border-radius: 5px;
font-family: Arial, sans-serif;
}
button {
margin: 5px;
padding: 8px;
cursor: pointer;
}
</style>
</head>
<body>
<div id="info">
<h3>Autonomous Drone Simulator</h3>
<p>Drone is flying autonomously through the environment</p>
<p><strong>Camera:</strong> Drag to rotate, Scroll to zoom</p>
</div>
<div id="controls">
<button id="resetBtn">Reset Drone</button>
<button id="toggleMode">Toggle Creative Mode</button>
<div>
<label for="speedRange">Speed: </label>
<input type="range" id="speedRange" min="0.5" max="5" step="0.5" value="2">
<span id="speedValue">2</span>
</div>
</div>
<script>
// Main variables
let scene, camera, renderer;
let drone, droneBody, droneProps = [];
let controls = {
rotateX: 0,
rotateY: 0,
distance: 80
};
let mouse = { x: 0, y: 0 }, isDragging = false;
let targets = [];
let currentTargetIndex = 0;
let dronePosition, droneVelocity;
let droneSpeed = 2;
let creativeMode = false;
let environmentObjects = [];
// Initialize the simulation
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x87CEEB); // Sky blue
// Create camera (isometric perspective)
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
updateCamera();
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Add lights
const ambientLight = new THREE.AmbientLight(0x404040, 1);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(100, 100, 50);
directionalLight.castShadow = true;
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;
scene.add(directionalLight);
// Create environment
createEnvironment();
// Create drone
createDrone();
// Set initial drone position and velocity
dronePosition = new THREE.Vector3(0, 10, 0);
droneVelocity = new THREE.Vector3(0, 0, -1);
// Create targets for the drone to navigate to
createTargets();
// Add event listeners
window.addEventListener('resize', onWindowResize);
window.addEventListener('mousedown', onMouseDown);
window.addEventListener('mouseup', onMouseUp);
window.addEventListener('mousemove', onMouseMove);
window.addEventListener('wheel', onMouseWheel);
document.getElementById('resetBtn').addEventListener('click', resetDrone);
document.getElementById('toggleMode').addEventListener('click', toggleCreativeMode);
document.getElementById('speedRange').addEventListener('input', function(e) {
droneSpeed = parseFloat(e.target.value);
document.getElementById('speedValue').textContent = droneSpeed;
});
// Start animation loop
animate();
}
function createEnvironment() {
// Create ground
const groundGeometry = new THREE.PlaneGeometry(200, 200, 32, 32);
const groundMaterial = new THREE.MeshLambertMaterial({ color: 0x228B22 });
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
ground.receiveShadow = true;
scene.add(ground);
environmentObjects.push(ground);
// Add some terrain variation
const vertices = groundGeometry.attributes.position;
for (let i = 0; i < vertices.count; i++) {
const x = vertices.getX(i);
const y = vertices.getY(i);
const z = vertices.getZ(i);
// Create hills and valleys
const distortion = 3 * Math.sin(0.05 * x) * Math.cos(0.05 * z);
vertices.setZ(i, distortion);
}
groundGeometry.computeVertexNormals();
// Add buildings in regular mode
if (!creativeMode) {
for (let i = 0; i < 15; i++) {
createBuilding(
Math.random() * 160 - 80,
Math.random() * 4 + 2,
Math.random() * 160 - 80,
Math.random() * 10 + 5,
Math.random() * 10 + 5,
Math.random() * 15 + 5
);
}
}
// Add trees
for (let i = 0; i < 30; i++) {
createTree(
Math.random() * 180 - 90,
0,
Math.random() * 180 - 90
);
}
// Add some decorative elements in creative mode
if (creativeMode) {
createCreativeEnvironment();
}
}
function createBuilding(x, baseY, z, width, depth, height) {
const buildingGeometry = new THREE.BoxGeometry(width, height, depth);
const colors = [0xff5555, 0x55ff55, 0x5555ff, 0xffff55, 0xff55ff, 0x55ffff];
const color = colors[Math.floor(Math.random() * colors.length)];
const buildingMaterial = new THREE.MeshLambertMaterial({ color: color });
const building = new THREE.Mesh(buildingGeometry, buildingMaterial);
building.position.set(x, baseY + height/2, z);
building.castShadow = true;
building.receiveShadow = true;
scene.add(building);
environmentObjects.push(building);
}
function createTree(x, baseY, z) {
// Tree trunk
const trunkGeometry = new THREE.CylinderGeometry(0.5, 0.7, 4, 8);
const trunkMaterial = new THREE.MeshLambertMaterial({ color: 0x8B4513 });
const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);
trunk.position.set(x, baseY + 2, z);
trunk.castShadow = true;
scene.add(trunk);
environmentObjects.push(trunk);
// Tree leaves
const leavesGeometry = new THREE.ConeGeometry(3, 6, 8);
const leavesMaterial = new THREE.MeshLambertMaterial({ color: 0x228B22 });
const leaves = new THREE.Mesh(leavesGeometry, leavesMaterial);
leaves.position.set(x, baseY + 6, z);
leaves.castShadow = true;
scene.add(leaves);
environmentObjects.push(leaves);
}
function createCreativeEnvironment() {
// Add floating platforms
for (let i = 0; i < 8; i++) {
const platformGeometry = new THREE.BoxGeometry(
Math.random() * 15 + 5,
1,
Math.random() * 15 + 5
);
const platformMaterial = new THREE.MeshLambertMaterial({
color: Math.random() * 0xffffff
});
const platform = new THREE.Mesh(platformGeometry, platformMaterial);
platform.position.set(
Math.random() * 120 - 60,
Math.random() * 30 + 15,
Math.random() * 120 - 60
);
platform.castShadow = true;
platform.receiveShadow = true;
scene.add(platform);
environmentObjects.push(platform);
}
// Add floating spheres
for (let i = 0; i < 12; i++) {
const sphereGeometry = new THREE.SphereGeometry(
Math.random() * 3 + 1, 16, 16
);
const sphereMaterial = new THREE.MeshLambertMaterial({
color: Math.random() * 0xffffff,
transparent: true,
opacity: 0.8
});
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(
Math.random() * 160 - 80,
Math.random() * 40 + 5,
Math.random() * 160 - 80
);
sphere.castShadow = true;
scene.add(sphere);
environmentObjects.push(sphere);
}
}
function createDrone() {
// Create drone group
drone = new THREE.Group();
scene.add(drone);
// Drone body
const bodyGeometry = new THREE.BoxGeometry(2, 0.5, 2);
const bodyMaterial = new THREE.MeshLambertMaterial({ color: 0x333333 });
droneBody = new THREE.Mesh(bodyGeometry, bodyMaterial);
droneBody.castShadow = true;
drone.add(droneBody);
// Add camera/lights to drone
const droneLight = new THREE.PointLight(0xffffff, 0.5, 10);
droneLight.position.set(0, -0.5, 0);
drone.add(droneLight);
// Create propellers
const propGeometry = new THREE.BoxGeometry(0.3, 0.3, 1.2);
const propMaterial = new THREE.MeshLambertMaterial({ color: 0x666666 });
// Front-left propeller
const prop1 = new THREE.Mesh(propGeometry, propMaterial);
prop1.position.set(-0.7, 0.5, -0.7);
drone.add(prop1);
droneProps.push(prop1);
// Front-right propeller
const prop2 = new THREE.Mesh(propGeometry, propMaterial);
prop2.position.set(0.7, 0.5, -0.7);
drone.add(prop2);
droneProps.push(prop2);
// Back-left propeller
const prop3 = new THREE.Mesh(propGeometry, propMaterial);
prop3.position.set(-0.7, 0.5, 0.7);
drone.add(prop3);
droneProps.push(prop3);
// Back-right propeller
const prop4 = new THREE.Mesh(propGeometry, propMaterial);
prop4.position.set(0.7, 0.5, 0.7);
drone.add(prop4);
droneProps.push(prop4);
// Add propeller arms
const armGeometry = new THREE.BoxGeometry(1.8, 0.2, 0.2);
const armMaterial = new THREE.MeshLambertMaterial({ color: 0x555555 });
const arm1 = new THREE.Mesh(armGeometry, armMaterial);
arm1.position.set(0, 0.2, -0.7);
drone.add(arm1);
const arm2 = new THREE.Mesh(armGeometry, armMaterial);
arm2.position.set(0, 0.2, 0.7);
arm2.rotation.z = Math.PI;
drone.add(arm2);
}
function createTargets() {
// Clear existing targets
targets.forEach(target => scene.remove(target));
targets = [];
// Create new targets based on mode
if (creativeMode) {
// In creative mode, navigate through floating platforms
environmentObjects.forEach(obj => {
if (obj.geometry instanceof THREE.BoxGeometry && obj.position.y > 10) {
targets.push(new THREE.Vector3(obj.position.x, obj.position.y + 5, obj.position.z));
}
});
// Add some additional targets
for (let i = 0; i < 5; i++) {
targets.push(new THREE.Vector3(
Math.random() * 100 - 50,
Math.random() * 20 + 10,
Math.random() * 100 - 50
));
}
} else {
// In regular mode, navigate around buildings
for (let i = 0; i < 10; i++) {
targets.push(new THREE.Vector3(
Math.random() * 120 - 60,
Math.random() * 15 + 8,
Math.random() * 120 - 60
));
}
}
// Visualize targets
targets.forEach(target => {
const targetGeometry = new THREE.SphereGeometry(0.5, 8, 8);
const targetMaterial = new THREE.MeshBasicMaterial({
color: 0xffff00,
transparent: true,
opacity: 0.7
});
const targetMesh = new THREE.Mesh(targetGeometry, targetMaterial);
targetMesh.position.copy(target);
scene.add(targetMesh);
// Add pulsing animation to targets
targetMesh.userData = {
originalScale: targetMesh.scale.clone(),
pulseFactor: 0.2,
pulseSpeed: 2 + Math.random() * 2
};
});
}
function updateDrone() {
if (!targets.length) return;
// Get current target
const target = targets[currentTargetIndex];
// Calculate direction to target
const direction = new THREE.Vector3().subVectors(target, dronePosition);
const distanceToTarget = direction.length();
// If close to target, switch to next target
if (distanceToTarget < 3) {
currentTargetIndex = (currentTargetIndex + 1) % targets.length;
return;
}
// Normalize direction and apply speed
direction.normalize().multiplyScalar(droneSpeed * 0.05);
droneVelocity.lerp(direction, 0.05);
// Update position
dronePosition.add(droneVelocity);
// Update drone mesh position and rotation
drone.position.copy(dronePosition);
// Orient drone in direction of movement
if (droneVelocity.length() > 0.01) {
drone.lookAt(new THREE.Vector3().addVectors(dronePosition, droneVelocity));
// Add banking effect when turning
const yaw = Math.atan2(droneVelocity.x, droneVelocity.z);
drone.rotation.x = Math.max(Math.min(droneVelocity.length() * 0.2, 0.5), -0.5);
drone.rotation.z = -yaw * 0.2;
}
// Rotate propellers
droneProps.forEach(prop => {
prop.rotation.x += 0.5;
});
// Keep drone above ground
if (dronePosition.y < 2) {
dronePosition.y = 2;
droneVelocity.y = Math.abs(droneVelocity.y);
}
// Check collisions with buildings
for (let obj of environmentObjects) {
if (obj.geometry instanceof THREE.BoxGeometry && obj !== droneBody) {
const box = new THREE.Box3().setFromObject(obj);
const droneBox = new THREE.Box3().setFromObject(drone);
if (droneBox.intersectsBox(box)) {
// Simple collision response - push drone away
const center = box.getCenter(new THREE.Vector3());
const away = new THREE.Vector3().subVectors(dronePosition, center).normalize();
dronePosition.add(away.multiplyScalar(1));
droneVelocity.reflect(away).multiplyScalar(0.5);
}
}
}
}
function animateTargets() {
scene.children.forEach(child => {
if (child.userData && child.userData.originalScale) {
const time = Date.now() * 0.001;
const scale = child.userData.originalScale.clone();
const pulse = 1 + child.userData.pulseFactor * Math.sin(time * child.userData.pulseSpeed);
child.scale.set(scale.x * pulse, scale.y * pulse, scale.z * pulse);
}
});
}
function updateCamera() {
// Isometric-like view with ability to rotate
const x = controls.distance * Math.sin(controls.rotateY) * Math.cos(controls.rotateX);
const y = controls.distance * Math.sin(controls.rotateX);
const z = controls.distance * Math.cos(controls.rotateY) * Math.cos(controls.rotateX);
camera.position.set(x, y, z);
camera.lookAt(0, 10, 0);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onMouseDown(event) {
isDragging = true;
mouse.x = event.clientX;
mouse.y = event.clientY;
}
function onMouseUp() {
isDragging = false;
}
function onMouseMove(event) {
if (isDragging) {
const deltaX = event.clientX - mouse.x;
const deltaY = event.clientY - mouse.y;
controls.rotateY -= deltaX * 0.01;
controls.rotateX += deltaY * 0.01;
// Limit vertical rotation
controls.rotateX =