Create an autonomous drone simulator with custom environment using ThreeJS
Create an autonomous drone simulator (drone flies by itself, isometric god like view, optionally interactive. With a custom environment (optionally creative), using ThreeJS, output a single-page self-contained HTML.
Couldn't render this response
This model didn't return a displayable web page for this challenge.
```html
<!DOCTYPE html>
<html>
<head>
<title>Autonomous Drone Simulator</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
<style>
body {
font-family: sans-serif;
margin: 0;
padding: 0;
background-color: #f0f0f0;
}
.container {
width: 90%;
margin: 20px auto;
text-align: center;
}
#environment {
width: 800px;
height: 600px;
margin: 0 auto;
border: 1px solid #ccc;
}
#controls {
margin-top: 20px;
padding: 10px;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 5px;
}
#status {
margin-top: 10px;
font-weight: bold;
}
</style>
</head>
<body>
<div class="container">
<h1>Autonomous Drone Simulator</h1>
<div id="environment"></div>
<div id="controls">
<label for="speed">Speed:</label>
<input type="number" id="speed" value="5" min="1" max="100">
<button id="start">Start</button>
<button id="stop">Stop</button>
<button id="reset">Reset</button>
</div>
<div id="status">
<!-- Display drone status here (e.g., "Flying", "Error") -->
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/three@0.161.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.161.0/examples/js/loaders/GLTFLoader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.161.0/examples/js/controls/FirstPersonControls.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
const environmentDiv = document.getElementById('environment');
const speedInput = document.getElementById('speed');
const startButton = document.getElementById('start');
const stopButton = document.getElementById('stop');
const resetButton = document.getElementById('reset');
const statusDiv = document.getElementById('status');
let scene;
let drone;
let camera;
let controls;
let speed = 5;
let isRunning = false;
let lastTime = 0;
// --- Environment (Customizable) ---
const environmentData = {
width: 800,
height: 600,
groundColor: '#333',
skyColor: '#87CEEB',
objects: [
{ x: 100, y: 50, z: 0, type: 'cube', color: '#FF0000', size: 20 },
{ x: 300, y: 150, z: 0, type: 'sphere', color: '#00FF00', radius: 30 },
{ x: 500, y: 300, z: 0, type: 'cylinder', color: '#0000FF', height: 50, radius: 10 }
]
};
// --- Drone Class ---
class Drone {
constructor(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
this.rotation = { x: 0, y: 0, z: 0 };
}
update(deltaTime) {
// Simple movement based on speed
this.x += Math.cos(this.rotation.x * 0.1) * speed * deltaTime;
this.y += Math.sin(this.rotation.y * 0.1) * speed * deltaTime;
this.z += speed * deltaTime;
// Keep drone within environment
this.x = Math.max(0, Math.min(this.x, environmentData.width));
this.y = Math.max(0, Math.min(this.y, environmentData.height));
this.z = Math.max(0, Math.min(this.z, environmentData.height * 2)); // Adjust z-axis limit
}
draw() {
// You can add more advanced drawing here (e.g., using a 3D model)
// For now, just a simple cube
const material = new THREE.MeshStandardMaterial({ color: 'purple' });
const geometry = new THREE.BoxGeometry(20, 20, 20);
const mesh = new THREE.Mesh(geometry, material);
mesh.position.set(this.x, this.y, this.z);
scene.add(mesh);
}
}
// --- Initialize Three.js Scene ---
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color(environmentData.skyColor);
const ground = new THREE.PlaneGeometry(environmentData.width * 1.2, environmentData.height * 1.2);
const groundMaterial = new THREE.MeshStandardMaterial({ color: environmentData.groundColor, roughness: 0.5 });
const groundMesh = new THREE.Mesh(ground, groundMaterial);
scene.add(groundMesh);
drone = new Drone(environmentData.width / 2, environmentData.height / 2, environmentData.height * 1.5);
drone.draw();
camera = new THREE.PerspectiveCamera(75, environmentData.width / environmentData.height, 0.1, 1000);
camera.position.set(0, environmentData.height / 2 + 50, 5);
scene.add(camera);
controls = new FirstPersonControls(camera, scene, {
speed: speed,
acceleration: 1,
maxSpeed: 100
});
// Add some objects to the environment
for (const obj of environmentData.objects) {
const geometry = new THREE.Shape( {
segments: obj.size,
bevelDepth: 0
});
const material = new THREE.MeshStandardMaterial({ color: obj.color });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
//--- Add a keypress event to the drone to control the camera ---
document.addEventListener('keydown', (event) => {
if (event.key === 'w') {
camera.position.z += 1;
} else if (event.key === 's') {
camera.position.z -= 1;
}
});
}
// --- Update Function ---
function update(time) {
if (!isRunning) return;
// Update drone position
drone.update(time / 1000);
// Update camera position based on drone movement
camera.position.x = drone.x;
camera.position.y = drone.y;
camera.position.z = drone.z;
// Apply camera movement to the environment
for (const obj of environmentData.objects) {
const geometry = new THREE.Shape( {
segments: obj.size,
bevelDepth: 0
});
const material = new THREE.MeshStandardMaterial({ color: obj.color });
const mesh = new THREE.Mesh(geometry, material);
mesh.position.set(drone.x, drone.y, drone.z);
scene.add(mesh);
}
// Render
renderer.render(scene, camera);
}
// --- Event Handlers ---
startButton.addEventListener('click', () => {
if (!isRunning) {
isRunning = true;
startTime = Date.now();
console.log('Drone started');
}
});
stopButton.addEventListener('click', () => {Couldn't render this response
This model didn't return a displayable web page for this challenge.
I'll create an autonomous drone simulator with a futuristic neon city environment. The drone will navigate automatically through waypoints while avoiding obstacles, and you can interact with it by clicking to set new destinations.
```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>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Arial', sans-serif;
overflow: hidden;
background: #000;
}
#canvas-container {
position: relative;
width: 100vw;
height: 100vh;
}
.ui-panel {
position: absolute;
background: rgba(0, 0, 0, 0.8);
border: 1px solid #00ffff;
border-radius: 10px;
padding: 20px;
color: #00ffff;
font-size: 14px;
backdrop-filter: blur(10px);
box-shadow: 0 0 20px rgba(0, 255, 255, 0.3);
}
.status-panel {
top: 20px;
left: 20px;
min-width: 250px;
}
.controls-panel {
top: 20px;
right: 20px;
min-width: 200px;
}
.info-panel {
bottom: 20px;
left: 20px;
max-width: 400px;
}
.status-item {
margin: 10px 0;
display: flex;
justify-content: space-between;
align-items: center;
}
.status-label {
color: #00cccc;
}
.status-value {
font-weight: bold;
color: #00ff88;
}
.control-btn {
background: linear-gradient(135deg, #00ffff, #0088ff);
border: none;
border-radius: 5px;
padding: 10px 20px;
color: #000;
font-weight: bold;
cursor: pointer;
margin: 5px;
transition: all 0.3s ease;
font-size: 14px;
}
.control-btn:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0, 255, 255, 0.5);
}
.control-btn:active {
transform: translateY(0);
}
.control-btn.active {
background: linear-gradient(135deg, #ff00ff, #ff0088);
}
.slider-container {
margin: 15px 0;
}
.slider {
width: 100%;
height: 5px;
border-radius: 5px;
background: #333;
outline: none;
-webkit-appearance: none;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 20px;
height: 20px;
border-radius: 50%;
background: #00ffff;
cursor: pointer;
box-shadow: 0 0 10px rgba(0, 255, 255, 0.5);
}
.slider::-moz-range-thumb {
width: 20px;
height: 20px;
border-radius: 50%;
background: #00ffff;
cursor: pointer;
box-shadow: 0 0 10px rgba(0, 255, 255, 0.5);
}
.waypoint-indicator {
position: absolute;
width: 20px;
height: 20px;
background: radial-gradient(circle, #ff00ff, transparent);
border-radius: 50%;
pointer-events: none;
animation: pulse 1s infinite;
}
@keyframes pulse {
0% { transform: scale(1); opacity: 1; }
100% { transform: scale(2); opacity: 0; }
}
.title {
font-size: 24px;
font-weight: bold;
text-align: center;
margin-bottom: 20px;
text-shadow: 0 0 10px rgba(0, 255, 255, 0.8);
}
.speed-indicator {
width: 100%;
height: 8px;
background: #333;
border-radius: 4px;
overflow: hidden;
margin-top: 5px;
}
.speed-bar {
height: 100%;
background: linear-gradient(90deg, #00ff00, #ffff00, #ff0000);
transition: width 0.3s ease;
border-radius: 4px;
}
</style>
</head>
<body>
<div id="canvas-container">
<div class="ui-panel status-panel">
<div class="title">DRONE STATUS</div>
<div class="status-item">
<span class="status-label">Mode:</span>
<span class="status-value" id="mode">AUTONOMOUS</span>
</div>
<div class="status-item">
<span class="status-label">Altitude:</span>
<span class="status-value" id="altitude">0m</span>
</div>
<div class="status-item">
<span class="status-label">Speed:</span>
<span class="status-value" id="speed">0 m/s</span>
</div>
<div class="speed-indicator">
<div class="speed-bar" id="speed-bar" style="width: 0%"></div>
</div>
<div class="status-item">
<span class="status-label">Waypoint:</span>
<span class="status-value" id="waypoint">1/5</span>
</div>
<div class="status-item">
<span class="status-label">Battery:</span>
<span class="status-value" id="battery">100%</span>
</div>
</div>
<div class="ui-panel controls-panel">
<div class="title">CONTROLS</div>
<button class="control-btn active" id="auto-btn">AUTO MODE</button>
<button class="control-btn" id="manual-btn">MANUALbutton>
<button class="control-btn" id="reset-btn">RESET</button>
<button class="control-btn" id="add-waypoint">ADD WAYPOINT</button>
<div class="slider-container">
<label class="status-label">Speed Multiplier</label>
<input type="range" class="slider" id="speed-slider" min="0.5" max="3" step="0.1" value="1">
<span class="status-value" id="speed-value">1.0x</span>
</div>
<div class="slider-container">
<label class="status-label">Camera Height</label>
<input type="range" class="slider" id="height-slider" min="50" max="200" step="10" value="100">
<span class="status-value" id="height-value">100m</span>
</div>
</div>
<div class="ui-panel info-panel">
<div class="title">INSTRUCTIONS</div>
<p style="color: #00cccc; line-height: 1.5;">
🚁 The drone flies autonomously through waypoints in the neon city.<br>
🖱️ Click anywhere to add a new waypoint.<br>
🎮 Use controls to switch between auto/manual mode.<br>
⚡ Adjust speed and camera height with sliders.<br>
🎯 Watch as the drone avoids obstacles automatically.
</p>
</div>
</div>
<script>
// Scene setup
const scene = new THREE.Scene();
scene.fog = new THREE.Fog(0x000000, 50, 300);
// Camera setup (isometric view)
const camera = new THREE.OrthographicCamera(
window.innerWidth / -50,
window.innerWidth / 50,
window.innerHeight / -50,
window.innerHeight / 50,
1,
500
);
camera.position.set(50, 100, 50);
camera.lookAt(0, 0, 0);
// Renderer setup
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.getElementById('canvas-container').appendChild(renderer.domElement);
// Lighting
const ambientLight = new THREE.AmbientLight(0x404040, 0.5);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(50, 100, 50);
directionalLight.castShadow = true;
directionalLight.shadow.camera.left = -100;
directionalLight.shadow.camera.right = 100;
directionalLight.shadow.camera.top = 100;
directionalLight.shadow.camera.bottom = -100;
scene.add(directionalLight);
// Ground
const groundGeometry = new THREE.PlaneGeometry(200, 200);
const groundMaterial = new THREE.MeshStandardMaterial({
color: 0x0a0a0a,
roughness: 0.8,
metalness: 0.2
});
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
ground.receiveShadow = true;
scene.add(ground);
// Grid helper
const gridHelper = new THREE.GridHelper(200, 40, 0x00ffff, 0x004444);
scene.add(gridHelper);
// Drone class
class Drone {
constructor() {
this.group = new THREE.Group();
// Drone body
const bodyGeometry = new THREE.BoxGeometry(2, 0.5, 2);
const bodyMaterial = new THREE.MeshStandardMaterial({
color: 0x00ffff,
emissive: 0x004444,
emissiveIntensity: 0.5
});
const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
body.castShadow = true;
this.group.add(body);
// Drone arms and rotors
const armGeometry = new THREE.BoxGeometry(3, 0.2, 0.2);
const armMaterial = new THREE.MeshStandardMaterial({ color: 0x333333 });
const rotorGeometry = new THREE.CylinderGeometry(1, 1, 0.1, 8);
const rotorMaterial = new THREE.MeshStandardMaterial({
color: 0x666666,
emissive: 0x00ff00,
emissiveIntensity: 0.3
});
this.rotors = [];
for (let i = 0; i < 4; i++) {
const angle = (Math.PI / 2) * i;
const arm = new THREE.Mesh(armGeometry, armMaterial);
arm.position.x = Math.cos(angle) * 1.5;
arm.position.z = Math.sin(angle) * 1.5;
arm.rotation.y = angle;
this.group.add(arm);
const rotor = new THREE.Mesh(rotorGeometry, rotorMaterial);
rotor.position.x = Math.cos(angle) * 1.5;
rotor.position.z = Math.sin(angle) * 1.5;
rotor.position.y = 0.3;
rotor.rotation.x = Math.PI / 2;
this.group.add(rotor);
this.rotors.push(rotor);
}
// LED lights
const ledGeometry = new THREE.SphereGeometry(0.1, 8, 8);
const ledMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const led = new THREE.Mesh(ledGeometry, ledMaterial);
led.position.y = -0.3;
this.group.add(led);
this.position = new THREE.Vector3(0, 20, 0);
this.velocity = new THREE.Vector3(0, 0, 0);
this.targetPosition = new THREE.Vector3(0, 20, 0);
this.waypoints = [];
this.currentWaypointIndex = 0;
this.speed = 0.5;
this.battery = 100;
this.mode = 'auto';
this.rotorSpeed = 0;
scene.add(this.group);
}
update(deltaTime) {
// Update rotor rotation
this.rotors.forEach((rotor, index) => {
rotor.rotation.z += this.rotorSpeed * (index % 2 === 0 ? 1 : -1);
});
if (this.mode === 'auto' && this.waypoints.length > 0) {
// Navigate to current waypoint
const target = this.waypoints[this.currentWaypointIndex];
const direction = new THREE.Vector3()
.subVectors(target, this.position)
.normalize();
const distance = this.position.distanceTo(target);
if (distance > 2) {
this.velocity = direction.multiplyScalar(this.speed);
} else {
// Reached waypoint, move to next
this.currentWaypointIndex = (this.currentWaypointIndex + 1) % this.waypoints.length;
this.velocity.multiplyScalar(0.1);
}
}
// Apply velocity with some smoothing
this.position.add(this.velocity);
this.velocity.multiplyScalar(0.95);
// Update battery
this.battery -= deltaTime * 0.5;
if (this.battery < 0) this.battery = 0;
// Update rotor speed based on movement
this.rotorSpeed = this.velocity.length() * 20 + 5;
// Update drone visual position
this.group.position.copy(this.position);
this.group.rotation.y = Math.atan2(this.velocity.x, this.velocity.z);
// Keep drone above ground
if (this.position.y < 5) {
this.position.y = 5;
this.velocity.y = Math.abs(this.velocity.y) * 0.5;
}
}
addWaypoint(position) {
this.waypoints.push(position.clone());
}
setWaypoints(points) {
this.waypoints = points.map(p => p.clone());
this.currentWaypointIndex = 0;
}
reset() {
this.position.set(0, 20, 0);
this.velocity.set(0, 0, 0);
this.battery = 100;
this.currentWaypointIndex = 0;
}
}
// Building creation
function createBuilding(x, z, width, height, depth) {
const geometry = new THREE.BoxGeometry(width, height, depth);
const material = new THREE.MeshStandardMaterial({
color: new THREE.Color().setHSL(Math.random() * 0.1 + 0.5, 0.5, 0.3),
emissive: new THREE.Color().setHSL(Math.random() * 0.1 + 0.5, 0.8, 0.2),
emissiveIntensity: 0.3
});
const building = new THREE.Mesh(geometry, material);
building.position.set(x, height / 2, z);
building.castShadow = true;
building.receiveShadow = true;
// Add windows
const windowGeometry = new THREE.PlaneGeometry(width * 0.8, height * 0.05);
const windowMaterial = new THREE.MeshBasicMaterial({
color: 0x00ffff,
emissive: 0x00ffff,
emissiveIntensity: 0.8
});
for (let i = 0; i < Math.floor(height / 5); i++) {
const window = new THREE.Mesh(windowGeometry, windowMaterial);
window.position.set(0, i * 5 - height / 2 + 2.5, depth / 2 + 0.01);
building.add(window);
}
scene.add(building);
return building;
}
// Create city environment
function createCity() {
const buildings = [];
// Create buildings in a grid pattern
for (let x = -80; x <= 80; x += 20) {
for (let z = -80; z <= 80; z += 20) {
if (Math.random() > 0.3) {
const height = Math.random() * 30 + 10;
const width = Math.random() * 10 + 10;
const depth = Math.random() * 10 + 10;
buildings.push(createBuilding(x, z, width, height, depth));
}
}
}
// Create some neon towers
for (let i = 0; i < 5; i++) {
const angle = (Math.PI * 2 / 5) * i;
const x = Math.cos(angle) * 60Couldn't render this response
This model didn't return a displayable web page for this challenge.
```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>
<style>
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&display=swap');
body {
margin: 0;
overflow: hidden;
font-family: 'Orbitron', monospace;
background: #000;
}
#info {
position: absolute;
top: 10px;
left: 10px;
color: #fff;
background: linear-gradient(135deg, rgba(0, 20, 40, 0.9), rgba(0, 40, 80, 0.8));
padding: 15px;
border-radius: 10px;
z-index: 100;
border: 1px solid rgba(0, 150, 255, 0.3);
box-shadow: 0 0 20px rgba(0, 150, 255, 0.5);
backdrop-filter: blur(10px);
}
#controls {
position: absolute;
bottom: 10px;
left: 10px;
color: #fff;
background: linear-gradient(135deg, rgba(0, 20, 40, 0.9), rgba(0, 40, 80, 0.8));
padding: 15px;
border-radius: 10px;
z-index: 100;
border: 1px solid rgba(0, 150, 255, 0.3);
box-shadow: 0 0 20px rgba(0, 150, 255, 0.5);
backdrop-filter: blur(10px);
}
button {
margin: 5px;
padding: 8px 15px;
background: linear-gradient(135deg, #0066cc, #0088ff);
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-family: 'Orbitron', monospace;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1px;
transition: all 0.3s ease;
box-shadow: 0 2px 10px rgba(0, 136, 255, 0.3);
}
button:hover {
background: linear-gradient(135deg, #0088ff, #00aaff);
transform: translateY(-2px);
box-shadow: 0 4px 20px rgba(0, 170, 255, 0.5);
}
button:active {
transform: translateY(0);
box-shadow: 0 2px 10px rgba(0, 136, 255, 0.3);
}
#stats {
position: absolute;
top: 10px;
right: 10px;
color: #fff;
background: linear-gradient(135deg, rgba(0, 20, 40, 0.9), rgba(0, 40, 80, 0.8));
padding: 15px;
border-radius: 10px;
z-index: 100;
border: 1px solid rgba(0, 150, 255, 0.3);
box-shadow: 0 0 20px rgba(0, 150, 255, 0.5);
backdrop-filter: blur(10px);
font-size: 12px;
min-width: 200px;
}
.stat-row {
display: flex;
justify-content: space-between;
margin: 5px 0;
padding: 2px 0;
border-bottom: 1px solid rgba(0, 150, 255, 0.2);
}
.stat-value {
color: #00ff88;
font-weight: bold;
}
#loading {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #00ff88;
font-size: 24px;
z-index: 1000;
text-shadow: 0 0 20px rgba(0, 255, 136, 0.8);
}
.pulse {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { opacity: 1; }
50% { opacity: 0.5; }
100% { opacity: 1; }
}
</style>
<div id="loading" class="pulse">INITIALIZING AUTONOMOUS DRONE...</div>
</head>
<body>
<div id="info">
<h3 style="margin: 0 0 10px 0; color: #00ff88; text-shadow: 0 0 10px rgba(0, 255, 136, 0.8);">AUTONOMOUS DRONE SIMULATOR</h3>
<p style="margin: 5px 0; font-size: 12px;">Drone is flying autonomously through the obstacle field</p>
<p style="margin: 5px 0; font-size: 12px;">Status: <span id="status" style="color: #00ff88;">ACTIVE</span></p>
</div>
<div id="controls">
<button id="toggleView">Toggle Camera</button>
<button id="togglePause">Pause/Resume</button>
<button id="resetDrone">Reset Drone</button>
<button id="addObstacle">Add Obstacle</button>
</div>
<div id="stats">
<h4 style="margin: 0 0 10px 0; color: #00ff88;">FLIGHT STATS</h4>
<div class="stat-row">
<span>Altitude:</span>
<span class="stat-value" id="altitude">0m</span>
</div>
<div class="stat-row">
<span>Speed:</span>
<span class="stat-value" id="speed">0 km/h</span>
</div>
<div class="stat-row">
<span>Battery:</span>
<span class="stat-value" id="battery">100%</span>
</div>
<div class="stat-row">
<span>Distance:</span>
<span class="stat-value" id="distance">0m</span>
</div>
<div class="stat-row">
<span>Waypoints:</span>
<span class="stat-value" id="waypoints">0/0</span>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/controls/OrbitControls.js"></script>
<script>
// Hide loading screen after a delay
setTimeout(() => {
document.getElementById('loading').style.display = 'none';
}, 2000);
// Initialize Three.js scene
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x001122);
scene.fog = new THREE.FogExp2(0x001122, 0.001);
// Add stars to the background
const starsGeometry = new THREE.BufferGeometry();
const starsMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 0.5 });
const starsVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starsVertices.push(x, y, z);
}
starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starsVertices, 3));
const stars = new THREE.Points(starsGeometry, starsMaterial);
scene.add(stars);
// Add ambient light
const ambientLight = new THREE.AmbientLight(0x404040, 0.5);
scene.add(ambientLight);
// Add directional light (sun)
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(100, 100, 50);
directionalLight.castShadow = true;
directionalLight.shadow.camera.near = 0.1;
directionalLight.shadow.camera.far = 500;
directionalLight.shadow.camera.left = -100;
directionalLight.shadow.camera.right = 100;
directionalLight.shadow.camera.top = 100;
directionalLight.shadow.camera.bottom = -100;
scene.add(directionalLight);
// Add hemisphere light for better ambient lighting
const hemisphereLight = new THREE.HemisphereLight(0x0088ff, 0x002244, 0.5);
scene.add(hemisphereLight);
// Camera setup
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(30, 30, 30);
camera.lookAt(0, 0, 0);
// Renderer setup
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
// Add orbit controls
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
// Create ground plane with custom texture
const groundGeometry = new THREE.PlaneGeometry(100, 100, 50, 50);
const groundMaterial = new THREE.MeshStandardMaterial({
color: 0x002244,
metalness: 0.3,
roughness: 0.7,
wireframe: false
});
// Add displacement to ground vertices for terrain effect
const groundVertices = groundGeometry.attributes.position.array;
for (let i = 0; i < groundVertices.length; i += 3) {
groundVertices[i + 2] = Math.sin(groundVertices[i] * 0.1) * Math.cos(groundVertices[i + 1] * 0.1) * 2;
}
groundGeometry.computeVertexNormals();
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
ground.receiveShadow = true;
scene.add(ground);
// Add animated grid
const gridHelper = new THREE.GridHelper(100, 20, 0x0088ff, 0x004466);
gridHelper.material.opacity = 0.5;
gridHelper.material.transparent = true;
scene.add(gridHelper);
// Create drone body with metallic material
const droneGroup = new THREE.Group();
const droneBodyGeometry = new THREE.BoxGeometry(2, 0.5, 2);
const droneBodyMaterial = new THREE.MeshStandardMaterial({
color: 0x0066cc,
metalness: 0.8,
roughness: 0.2,
emissive: 0x003366,
emissiveIntensity: 0.2
});
const droneBody = new THREE.Mesh(droneBodyGeometry, droneBodyMaterial);
droneBody.castShadow = true;
droneBody.receiveShadow = true;
droneGroup.add(droneBody);
// Add LED lights to drone
const ledGeometry = new THREE.SphereGeometry(0.1, 8, 8);
const ledMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const leds = [];
for (let i = 0; i < 4; i++) {
const led = new THREE.Mesh(ledGeometry, ledMaterial);
const angle = (i / 4) * Math.PI * 2;
led.position.set(Math.cos(angle) * 1.2, 0.3, Math.sin(angle) * 1.2);
droneGroup.add(led);
leds.push(led);
}
// Create drone propellers with metallic finish
const propellerGeometry = new THREE.BoxGeometry(0.1, 0.1, 1.5);
const propellerMaterial = new THREE.MeshStandardMaterial({
color: 0xcccccc,
metalness: 0.9,
roughness: 0.1
});
const propellers = [];
const propellerPositions = [
{ x: -1, y: 0.2, z: -1 },
{ x: 1, y: 0.2, z: -1 },
{ x: 1, y: 0.2, z: 1 },
{ x: -1, y: 0.2, z: 1 }
];
for (let i = 0; i < 4; i++) {
const propeller = new THREE.Mesh(propellerGeometry, propellerMaterial);
propeller.position.set(
propellerPositions[i].x,
propellerPositions[i].y,
propellerPositions[i].z
);
propeller.castShadow = true;
droneGroup.add(propeller);
const propeller2 = new THREE.Mesh(propellerGeometry, propellerMaterial);
propeller2.position.set(
propellerPositions[i].x,
propellerPositions[i].y + 0.2,
propellerPositions[i].z
);
propeller2.rotation.y = Math.PI / 2;
propeller2.castShadow = true;
droneGroup.add(propeller2);
propellers.push(propeller, propeller2);
}
// Add drone to scene
scene.add(droneGroup);
// Create obstacles with variety
const obstacles = [];
const obstacleTypes = [
{ geometry: new THREE.BoxGeometry(5, 10, 5), material: new THREE.MeshStandardMaterial({ color: 0xff4444, metalness: 0.6, roughness: 0.4 }) },
{ geometry: new THREE.CylinderGeometry(3, 3, 12, 8), material: new THREE.MeshStandardMaterial({ color: 0x44ff44, metalness: 0.6, roughness: 0.4 }) },
{ geometry: new THREE.SphereGeometry(4, 16, 16), material: new THREE.MeshStandardMaterial({ color: 0x4444ff, metalness: 0.6, roughness: 0.4 }) },
{ geometry: new THREE.TorusGeometry(3, 1, 8, 16), material: new THREE.MeshStandardMaterial({ color: 0xffff44, metalness: 0.6, roughness: 0.4 }) }
];
for (let i = 0; i < 15; i++) {
const type = obstacleTypes[Math.floor(Math.random() * obstacleTypes.length)];
const obstacle = new THREE.Mesh(type.geometry, type.material);
obstacle.position.set(
Math.random() * 80 - 40,
5 + Math.random() * 10,
Math.random() * 80 - 40
);
if (Math.abs(obstacle.position.x) < 5 && Math.abs(obstacle.position.z) < 5) {
obstacle.position.x += 10;
obstacle.position.z += 10;
}
obstacle.castShadow = true;
obstacle.receiveShadow = true;
scene.add(obstacle);
obstacles.push(obstacle);
}
// Create waypoints with glow effect
const waypoints = [];
const waypointGeometry = new THREE.SphereGeometry(1, 16, 16);
const waypointMaterial = new THREE.MeshBasicMaterial({
color: 0x00ffff,
transparent: true,
opacity: 0.6
});
for (let i = 0; i < 8; i++) {
const waypoint = new THREE.Mesh(waypointGeometry, waypointMaterial);
waypoint.position.set(
Math.random() * 60 - 30,
5 + Math.random() * 15,
Math.random() * 60 - 30
);
scene.add(waypoint);
waypoints.push(waypoint);
// Add glow effect
const glowGeometry = new THREE.SphereGeometry(1.5, 16, 16);
const glowMaterial = new THREE.MeshBasicMaterial({
color: 0x00ffff,
transparent: true,
opacity: 0.2
});
const glow = new THREE.Mesh(glowGeometry, glowMaterial);
waypoint.add(glow);
}
// Add particle trail
const trailGeometry = new THREE.BufferGeometry();
const trailMaterial = new THREE.PointsMaterial({
color: 0x00ff88,
size: 0.2,
transparent: true,
opacity: 0.6
});
const trailPositions = [];
const trailMaxPoints = 50;
const trail = new THREE.Points(trailGeometry, trailMaterial);
scene.add(trail);
// Drone flight variables
let currentWaypointIndex = 0;
let droneSpeed = 0.05;
let propellerRotation = 0;
let isPaused = false;
let cameraFollow = false;
let totalDistance = 0;
let lastPosition = new THREE.Vector3();
let battery = 100;
let ledBlink = 0;
// Handle window resize
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
Couldn't render this response
This model didn't return a displayable web page for this challenge.
```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>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
overflow: hidden;
background: linear-gradient(135deg, #0a0a2a 0%, #1a1a4a 50%, #0a0a2a 100%);
color: #e0e0ff;
}
#canvas-container {
position: relative;
width: 100vw;
height: 100vh;
}
#info-panel {
position: absolute;
top: 20px;
left: 20px;
background: rgba(10, 15, 40, 0.9);
padding: 20px;
border-radius: 15px;
min-width: 280px;
backdrop-filter: blur(15px);
border: 2px solid rgba(100, 180, 255, 0.4);
box-shadow: 0 8px 32px rgba(0, 20, 80, 0.4);
z-index: 10;
}
#info-panel h2 {
color: #64b4ff;
margin-bottom: 15px;
font-size: 1.4em;
text-shadow: 0 0 15px rgba(100, 180, 255, 0.7);
font-weight: 600;
}
.info-item {
margin: 10px 0;
font-size: 14px;
display: flex;
justify-content: space-between;
align-items: center;
}
.info-label {
color: #a0b0ff;
font-weight: 500;
}
.info-value {
color: #64ffda;
font-weight: 600;
font-family: 'Courier New', monospace;
}
.control-button {
background: linear-gradient(45deg, #0066cc, #0099ff);
border: none;
color: white;
padding: 10px 18px;
margin: 8px 5px;
border-radius: 8px;
cursor: pointer;
font-size: 13px;
font-weight: 600;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(0, 102, 204, 0.4);
min-width: 120px;
}
.control-button:hover {
transform: translateY(-3px);
box-shadow: 0 6px 25px rgba(0, 153, 255, 0.7);
background: linear-gradient(45deg, #0099ff, #00ccff);
}
.control-button.danger {
background: linear-gradient(45deg, #cc3300, #ff6600);
box-shadow: 0 4px 15px rgba(204, 51, 0, 0.4);
}
.control-button.danger:hover {
background: linear-gradient(45deg, #ff6600, #ff9933);
box-shadow: 0 6px 25px rgba(255, 102, 0, 0.7);
}
.control-button.active {
background: linear-gradient(45deg, #00cc66, #00ff99);
box-shadow: 0 4px 15px rgba(0, 204, 102, 0.4);
}
.slider-container {
margin: 15px 0;
}
.slider-label {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
font-size: 13px;
color: #a0b0ff;
font-weight: 500;
}
input[type="range"] {
width: 100%;
height: 8px;
border-radius: 4px;
background: rgba(100, 180, 255, 0.2);
outline: none;
-webkit-appearance: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 20px;
height: 20px;
border-radius: 50%;
background: linear-gradient(45deg, #64b4ff, #00ccff);
cursor: pointer;
box-shadow: 0 0 15px rgba(100, 180, 255, 0.8);
border: 2px solid rgba(255, 255, 255, 0.8);
}
#loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
z-index: 100;
background: rgba(10, 15, 40, 0.95);
padding: 40px;
border-radius: 20px;
border: 2px solid rgba(100, 180, 255, 0.4);
box-shadow: 0 0 50px rgba(0, 102, 204, 0.6);
}
.loader {
border: 4px solid rgba(100, 180, 255, 0.2);
border-top: 4px solid #64b4ff;
border-radius: 50%;
width: 60px;
height: 60px;
animation: spin 1.2s cubic-bezier(0.5, 0.1, 0.5, 0.9) infinite;
margin: 0 auto 25px;
box-shadow: 0 0 25px rgba(100, 180, 255, 0.6);
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.section-title {
color: #64b4ff;
margin: 20px 0 10px 0;
font-size: 1.1em;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 1px;
text-shadow: 0 0 10px rgba(100, 180, 255, 0.5);
}
#controls {
margin-top: 20px;
padding-top: 20px;
border-top: 2px solid rgba(100, 180, 255, 0.3);
}
.status-indicator {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 50%;
margin-left: 8px;
box-shadow: 0 0 10px currentColor;
}
.status-active { background: #00ff99; color: #00ff99; }
.status-inactive { background: #ff4444; color: #ff4444; }
.status-idle { background: #ffaa00; color: #ffaa00; }
.mode-selector {
display: flex;
gap: 10px;
margin: 15px 0;
}
.mode-button {
flex: 1;
padding: 10px;
background: rgba(100, 180, 255, 0.1);
border: 2px solid rgba(100, 180, 255, 0.3);
border-radius: 8px;
color: #a0b0ff;
cursor: pointer;
transition: all 0.3s ease;
font-size: 12px;
font-weight: 500;
text-align: center;
}
.mode-button:hover {
background: rgba(100, 180, 255, 0.2);
border-color: rgba(100, 180, 255, 0.5);
}
.mode-button.active {
background: linear-gradient(45deg, #0066cc, #0099ff);
border-color: #64b4ff;
color: white;
box-shadow: 0 0 20px rgba(100, 180, 255, 0.6);
}
</style>
</head>
<body>
<div id="loading">
<div class="loader"></div>
<h2>Initializing Drone Simulator</h2>
<p>Loading advanced systems...</p>
</div>
<div id="canvas-container">
<div id="info-panel">
<h2>🚁 DRONE COMMAND</h2>
<div class="section-title">Flight Status</div>
<div class="info-item">
<span class="info-label">Altitude:</span>
<span class="info-value" id="altitude">0m</span>
</div>
<div class="info-item">
<span class="info-label">Speed:</span>
<span class="info-value" id="speed">0 km/h</span>
</div>
<div class="info-item">
<span class="info-label">Position:</span>
<span class="info-value" id="position">X:0 Z:0</span>
</div>
<div class="info-item">
<span class="info-label">Battery:</span>
<span class="info-value" id="battery">100%</span>
</div>
<div class="info-item">
<span class="info-label">Flight Mode:</span>
<span class="info-value" id="flight-mode">AUTO</span>
</div>
<div class="section-title">Environment</div>
<div class="info-item">
<span class="info-label">Wind Speed:</span>
<span class="info-value" id="wind-speed">5 km/h</span>
</div>
<div class="info-item">
<span class="info-label">Time:</span>
<span class="info-value" id="time">12:00</span>
</div>
<div class="section-title">Control Mode</div>
<div class="mode-selector">
<div class="mode-button active" data-mode="auto">AUTO</div>
<div class="mode-button" data-mode="manual">MANUAL</div>
<div class="mode-button" data-mode="waypoint">WAYPOINT</div>
</div>
<div class="section-title">Drone Controls</div>
<div id="controls">
<button class="control-button" id="takeoff-btn">🚀 Takeoff</button>
<button class="control-button danger" id="land-btn">🛬 Land</button>
<button class="control-button" id="rtl-btn">🏠 Return Home</button>
<div class="slider-container">
<div class="slider-label">
<span>Flight Speed</span>
<span id="speed-value">50%</span>
</div>
<input type="range" id="speed-slider" min="10" max="100" value="50">
</div>
<div class="slider-container">
<div class="slider-label">
<span>Altitude Limit</span>
<span id="altitude-value">100m</span>
</div>
<input type="range" id="altitude-slider" min="20" max="200" value="100">
</div>
<button class="control-button" id="camera-btn">📷 Toggle Camera</button>
<button class="control-button" id="lights-btn">💡 Lights</button>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Global variables
let scene, camera, renderer, drone, environment, clock;
let droneController, physicsEngine, environmentManager;
let isInitialized = false;
let currentMode = 'auto';
let animationId;
// Hide loading screen
function hideLoading() {
const loading = document.getElementById('loading');
loading.style.opacity = '0';
setTimeout(() => {
loading.style.display = 'none';
isInitialized = true;
}, 500);
}
// Initialize ThreeJS scene
function initScene() {
// Scene setup
scene = new THREE.Scene();
scene.fog = new THREE.Fog(0x0a0a2a, 100, 2000);
// Camera setup (isometric view)
camera = new THREE.PerspectiveCamera(
60,
window.innerWidth / window.innerHeight,
0.1,
10000
);
camera.position.set(300, 400, 300);
camera.lookAt(0, 0, 0);
// Renderer setup
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
powerPreference: "high-performance"
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.2;
const container = document.getElementById('canvas-container');
container.appendChild(renderer.domElement);
// Clock for animations
clock = new THREE.Clock();
// Initialize systems
initLighting();
initEnvironment();
initDrone();
initControls();
initEventListeners();
// Start render loop
animate();
// Hide loading screen
setTimeout(hideLoading, 1000);
}
// Initialize lighting system
function initLighting() {
// Ambient light
const ambientLight = new THREE.AmbientLight(0x404080, 0.3);
scene.add(ambientLight);
// Main directional light (sun)
const sunLight = new THREE.DirectionalLight(0xffffff, 1.2);
sunLight.position.set(200, 300, 100);
sunLight.castShadow = true;
sunLight.shadow.mapSize.width = 4096;
sunLight.shadow.mapSize.height = 4096;
sunLight.shadow.camera.near = 0.5;
sunLight.shadow.camera.far = 1000;
sunLight.shadow.camera.left = -300;
sunLight.shadow.camera.right = 300;
sunLight.shadow.camera.top = 300;
sunLight.shadow.camera.bottom = -300;
sunLight.shadow.bias = -0.0001;
scene.add(sunLight);
// Hemisphere light for natural lighting
const hemisphereLight = new THREE.HemisphereLight(0x87CEEB, 0x1a1a4a, 0.6);
scene.add(hemisphereLight);
// Point lights for dramatic effect
const pointLight1 = new THREE.PointLight(0x64b4ff, 0.8, 200);
pointLight1.position.set(-100, 50, -100);
scene.add(pointLight1);
const pointLight2 = new THREE.PointLight(0xff6b6b, 0.6, 150);
pointLight2.position.set(100, 30, 100);
scene.add(pointLight2);
}
// Initialize environment
function initEnvironment() {
environmentManager = new EnvironmentManager(scene);
environmentManager.createTerrain();
environmentManager.createBuildings();
environmentManager.createTrees();
environmentManager.createWaterFeatures();
environmentManager.createClouds();
environment = environmentManager.getEnvironment();
}
// Initialize drone
function initDrone() {
droneController = new DroneController(scene);
drone = droneController.getDrone();
physicsEngine = new PhysicsEngine();
}
// Initialize UI controls
function initControls() {
// Takeoff/Landing
document.getElementById('takeoff-btn').addEventListener('click', () => {
droneController.takeoff();
updateButtonStates();
});
document.getElementById('land-btn').addEventListener('click', () => {
droneController.land();
updateButtonStates();
});
// Return to launch
document.getElementById('rtl-btn').addEventListener('click', () => {
droneController.returnToLaunch();
});
// Speed control
const speedSlider = document.getElementById('speed-slider');
speedSlider.addEventListener('input', (e) => {
const value = e.target.value;
document.getElementById('speed-value').textContent = value + '%';
droneController.setSpeedMultiplier(value / 100);
});
// Altitude control
const altitudeSlider = document.getElementById('altitude-slider');
altitudeSlider.addEventListener('input', (e) => {
const value = e.target.value;
document.getElementById('altitude-value').textContent = value + 'm';
droneController.setAltitudeLimit(parseInt(value));
});
// Camera toggle
document.getElementById('camera-btn').addEventListener('click', () => {
droneController.toggleCamera();
});
// Lights toggle
document.getElementById('lights-btn').addEventListener('click', () => {
droneController.toggleLights();
});
// Mode selection
document.querySelectorAll('.mode-button').forEach(button => {
button.addEventListener('click', (e) => {
document.querySelectorAll('.mode-button').forEach(b => b.classList.remove('active'));
e.target.classList.add('active');
currentMode = e.target.dataset.mode;
droneController.setFlightMode(currentMode);
document.getElementById('flight-mode').textContent = currentMode.toUpperCase();
});
});
}
// Initialize event listeners
function initEventListeners() {
// Window resize
window.addEventListener('resize', onWindowResize);
// Mouse controls for camera
let mouseX = 0, mouseY = 0;
let isMouseDown = false;
renderer.domElement.addEventListener('mousedown', () => { isMouseDown = true; });
renderer.domElement.addEventListener('mouseup', () => { isMouseDown = false; });
renderer.domElement.addEventListener('mousemove', (e) => {
if (isMouseDown) {
const deltaX = e.clientX - mouseX;
const deltaY = e.clientY - mouseY;
// Rotate camera around scene
const spherical = new THREE.Spherical();
spherical.setFromVector3(camera.position);
spherical.theta -= deltaX * 0.01;
spherical.phi += deltaY * 0.01;
spherical.phi = Math.max(0.1, Math.min(Math.PI - 0.1, spherical.phi));
camera.position.setFromSpherical(spherical);
camera.lookAt(0, 50, 0);
}
mouseX = e.clientX;
mouseY = e.clientY;
});
// Scroll to zoom
renderer.domElement.addEventListener('wheel', (e) => {
const scale = e.deltaY > 0 ? 1.1 : 0.9;
camera.position.multiplyScalar(scale);
camera.position.clampLength(100, 1000);
camera.lookAt(0, 50, 0);
});
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Update UI
function updateUI() {
if (!drone || !isInitialized) return;
const position = drone.position;
const velocity = droneController.getVelocity();
const altitude = Math.max(0, position.y);
const speed = velocity.length() * 3.6; // Convert to km/h
const battery = droneController.getBatteryLevel();
const flightMode = droneController.getFlightMode();
document.getElementById('altitude').textContent = altitude.toFixed(1) + 'm';
document.getElementById('speed').textContent = speed.toFixed(1) + ' km/h';
document.getElementById('position').textContent = `X:${position.x.toFixed(0)} Z:${position.z.toFixed(0)}`;
document.getElementById('battery').textContent = battery.toFixed(0) + '%';
document.getElementById('flight-mode').textContent = flightMode.toUpperCase();
// Update environment info
const windSpeed = environmentManager.getWindSpeed();
const time = environmentManager.getTimeOfDay();
document.getElementById('wind-speed').textContent = windSpeed.toFixed(0) + ' km/h';
document.getElementById('time').textContent = time;
// Update button states
updateButtonStates();
}
// Update button states
function updateButtonStates() {
const isFlying = droneController.isFlying();
const isLanding = droneController.isLanding();
document.getElementById('takeoff-btn').disabled = isFlying;
document.getElementById('land-btn').disabled = !isFlying || isLanding;
document.getElementById('rtl-btn').disabled = !isFlying;
}
// Animation loop
function animate() {
animationId = requestAnimationFrame(animate);
if (!isInitialized) return;
const deltaTime = clock.getDelta();
const elapsedTime = clock.getElapsedTime();
// Update systems
droneController.update(deltaTime, elapsedTime);
environmentManager.update(deltaTime, elapsedTime);
physicsEngine.update(deltaTime);
// Update UI
updateUI();
// Render scene
renderer.render(scene, camera);
}
// Environment Manager Class
class EnvironmentCouldn't render this response
This model didn't return a displayable web page for this challenge.
I'll create a self-contained HTML page with a ThreeJS-based drone simulator. This will include an isometric view, autonomous drone movement, and a custom environment. Let me build this for you.
Couldn't render this response
This model didn't return a displayable web page for this challenge.
drone-simulator/ |-- index.html |-- styles.css |-- script.js |-- assets/ | |-- drone.png | |-- environment.png
Couldn't render this response
This model didn't return a displayable web page for this challenge.
```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 =