-
<!DOCTYPE html>
<html lang=”es”>
<head>
<meta charset=”UTF-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
<title>Simulador 3D – Ciudad Futurista</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: ‘Arial’, sans-serif;
overflow: hidden;
background-color: #000;
}
#canvas {
display: block;
width: 100%;
height: 100vh;
}
#ui {
position: absolute;
top: 20px;
left: 20px;
color: #00ff00;
font-size: 14px;
font-family: ‘Courier New’, monospace;
text-shadow: 0 0 10px rgba(0, 255, 0, 0.8);
z-index: 100;
}
.info-box {
background-color: rgba(0, 0, 0, 0.7);
border: 2px solid #00ff00;
padding: 15px;
margin-bottom: 10px;
border-radius: 5px;
min-width: 300px;
}
.info-title {
font-weight: bold;
margin-bottom: 8px;
text-decoration: underline;
}
.info-line {
margin: 4px 0;
}
#controls {
position: absolute;
bottom: 20px;
left: 20px;
color: #00ff00;
font-size: 12px;
font-family: ‘Courier New’, monospace;
text-shadow: 0 0 10px rgba(0, 255, 0, 0.8);
background-color: rgba(0, 0, 0, 0.7);
border: 2px solid #00ff00;
padding: 15px;
border-radius: 5px;
z-index: 100;
}
.control-item {
margin: 4px 0;
}
.key {
background-color: #00ff00;
color: #000;
padding: 2px 6px;
border-radius: 3px;
font-weight: bold;
display: inline-block;
min-width: 30px;
text-align: center;
}
</style>
</head>
<body>
<div id=”ui”>
<div class=”info-box”>
<div class=”info-title”>SIMULADOR 3D – CIUDAD FUTURISTA</div>
<div class=”info-line”>Posición: <span id=”posX”>0.00</span>, <span id=”posY”>0.00</span>, <span id=”posZ”>0.00</span></div>
<div class=”info-line”>Rotación: <span id=”rotY”>0.00</span> rad</div>
<div class=”info-line”>Velocidad: <span id=”speed”>0.00</span></div>
<div class=”info-line”>FPS: <span id=”fps”>60</span></div>
</div>
</div>
<div id=”controls”>
<div class=”info-title”>CONTROLES</div>
<div class=”control-item”><span class=”key”>W</span> – Adelante</div>
<div class=”control-item”><span class=”key”>S</span> – Atrás</div>
<div class=”control-item”><span class=”key”>A</span> – Girar Izquierda</div>
<div class=”control-item”><span class=”key”>D</span> – Girar Derecha</div>
<div class=”control-item”><span class=”key”>MOUSE</span> – Rotar Cámara</div>
</div>
<!– Three.js desde CDN –>
<script src=”https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js”></script>
<script>
// ==================== CONFIGURACIÓN INICIAL ====================
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x0a0e27);
scene.fog = new THREE.Fog(0x0a0e27, 200, 500);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowShadowMap;
document.body.appendChild(renderer.domElement);
// ==================== ILUMINACIÓN ====================
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(100, 100, 100);
directionalLight.castShadow = true;
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;
directionalLight.shadow.camera.far = 500;
directionalLight.shadow.camera.left = -200;
directionalLight.shadow.camera.right = 200;
directionalLight.shadow.camera.top = 200;
directionalLight.shadow.camera.bottom = -200;
scene.add(directionalLight);
// Luces neón futuristas
const neonLight1 = new THREE.PointLight(0x00ff00, 1, 150);
neonLight1.position.set(50, 30, 50);
scene.add(neonLight1);
const neonLight2 = new THREE.PointLight(0xff00ff, 1, 150);
neonLight2.position.set(-50, 30, -50);
scene.add(neonLight2);
// ==================== CREACIÓN DEL TERRENO ====================
const groundGeometry = new THREE.PlaneGeometry(400, 400);
const groundMaterial = new THREE.MeshStandardMaterial({
color: 0x1a1f3a,
metalness: 0.3,
roughness: 0.8
});
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
ground.receiveShadow = true;
scene.add(ground);
// Líneas del suelo (efecto de ciudad futurista)
const lineGeometry = new THREE.BufferGeometry();
const linePositions = [];
for (let i = -200; i <= 200; i += 20) {
linePositions.push(i, 0.01, -200);
linePositions.push(i, 0.01, 200);
linePositions.push(-200, 0.01, i);
linePositions.push(200, 0.01, i);
}
lineGeometry.setAttribute(‘position’, new THREE.BufferAttribute(new Float32Array(linePositions), 3));
const lineMaterial = new THREE.LineBasicMaterial({ color: 0x00ff00, linewidth: 1 });
const gridLines = new THREE.LineSegments(lineGeometry, lineMaterial);
scene.add(gridLines);
// ==================== CREACIÓN DE EDIFICIOS ====================
function createBuilding(x, z, width, height, depth, color) {
const geometry = new THREE.BoxGeometry(width, height, depth);
const material = new THREE.MeshStandardMaterial({
color: color,
metalness: 0.6,
roughness: 0.4
});
const building = new THREE.Mesh(geometry, material);
building.position.set(x, height / 2, z);
building.castShadow = true;
building.receiveShadow = true;
// Ventanas neón
const windowGeometry = new THREE.PlaneGeometry(2, 2);
const windowMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
for (let i = 0; i < width – 5; i += 5) {
for (let j = 0; j < height – 5; j += 5) {
const window = new THREE.Mesh(windowGeometry, windowMaterial);
window.position.set(x – width / 2 + i + 2.5, j + 2.5, z + depth / 2 + 0.1);
scene.add(window);
}
}
scene.add(building);
return building;
}
// Crear ciudad futurista
createBuilding(60, 60, 30, 80, 30, 0x0066ff);
createBuilding(-60, 60, 40, 100, 40, 0xff00ff);
createBuilding(60, -60, 35, 90, 35, 0x00ffff);
createBuilding(-60, -60, 45, 110, 45, 0xffff00);
createBuilding(0, 80, 25, 70, 25, 0xff6600);
createBuilding(80, 0, 30, 85, 30, 0x00ff99);
createBuilding(-80, 0, 35, 95, 35, 0xff0099);
createBuilding(0, -80, 28, 75, 28, 0x00ccff);
// ==================== CREACIÓN DEL PERSONAJE HUMANOIDE ====================
const character = new THREE.Group();
character.position.set(0, 0, 0);
// Cuerpo
const bodyGeometry = new THREE.BoxGeometry(2, 4, 1.5);
const bodyMaterial = new THREE.MeshStandardMaterial({
color: 0xff6600,
metalness: 0.3,
roughness: 0.7
});
const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
body.position.y = 2;
body.castShadow = true;
body.receiveShadow = true;
character.add(body);
// Cabeza
const headGeometry = new THREE.SphereGeometry(0.8, 32, 32);
const headMaterial = new THREE.MeshStandardMaterial({
color: 0xffaa88,
metalness: 0.2,
roughness: 0.8
});
const head = new THREE.Mesh(headGeometry, headMaterial);
head.position.y = 5;
head.castShadow = true;
head.receiveShadow = true;
character.add(head);
// Brazo izquierdo
const armGeometry = new THREE.BoxGeometry(0.8, 3, 0.8);
const armMaterial = new THREE.MeshStandardMaterial({
color: 0xffaa88,
metalness: 0.2,
roughness: 0.8
});
const leftArm = new THREE.Mesh(armGeometry, armMaterial);
leftArm.position.set(-1.5, 3, 0);
leftArm.castShadow = true;
leftArm.receiveShadow = true;
character.add(leftArm);
// Brazo derecho
const rightArm = new THREE.Mesh(armGeometry, armMaterial);
rightArm.position.set(1.5, 3, 0);
rightArm.castShadow = true;
rightArm.receiveShadow = true;
character.add(rightArm);
// Pierna izquierda
const legGeometry = new THREE.BoxGeometry(0.8, 3, 0.8);
const legMaterial = new THREE.MeshStandardMaterial({
color: 0x333333,
metalness: 0.4,
roughness: 0.6
});
const leftLeg = new THREE.Mesh(legGeometry, legMaterial);
leftLeg.position.set(-0.6, 1, 0);
leftLeg.castShadow = true;
leftLeg.receiveShadow = true;
character.add(leftLeg);
// Pierna derecha
const rightLeg = new THREE.Mesh(legGeometry, legMaterial);
rightLeg.position.set(0.6, 1, 0);
rightLeg.castShadow = true;
rightLeg.receiveShadow = true;
character.add(rightLeg);
scene.add(character);
// ==================== SISTEMA DE CONTROL ====================
const keys = {};
const characterSpeed = 0.5;
const rotationSpeed = 0.05;
window.addEventListener(‘keydown’, (e) => {
keys[e.key.toUpperCase()] = true;
});
window.addEventListener(‘keyup’, (e) => {
keys[e.key.toUpperCase()] = false;
});
// ==================== CÁMARA EN TERCERA PERSONA ====================
const cameraOffset = new THREE.Vector3(0, 4, -12);
function updateCameraPosition() {
const targetX = character.position.x + cameraOffset.x;
const targetY = character.position.y + cameraOffset.y;
const targetZ = character.position.z + cameraOffset.z;
camera.position.lerp(new THREE.Vector3(targetX, targetY, targetZ), 0.1);
camera.lookAt(character.position.x, character.position.y + 2, character.position.z);
}
// ==================== ANIMACIÓN DE MOVIMIENTO ====================
let armSwing = 0;
let legSwing = 0;
let isMoving = false;
function updateCharacterAnimation() {
if (isMoving) {
armSwing += 0.1;
legSwing += 0.1;
leftArm.rotation.z = Math.sin(armSwing) * 0.5;
rightArm.rotation.z = -Math.sin(armSwing) * 0.5;
leftLeg.rotation.z = Math.sin(legSwing) * 0.3;
rightLeg.rotation.z = -Math.sin(legSwing) * 0.3;
} else {
armSwing = 0;
legSwing = 0;
leftArm.rotation.z = 0;
rightArm.rotation.z = 0;
leftLeg.rotation.z = 0;
rightLeg.rotation.z = 0;
}
}
// ==================== BUCLE DE ANIMACIÓN ====================
let lastTime = Date.now();
let frameCount = 0;
let fps = 60;
function animate() {
requestAnimationFrame(animate);
const currentTime = Date.now();
const deltaTime = (currentTime – lastTime) / 1000;
lastTime = currentTime;
// Actualizar FPS
frameCount++;
if (frameCount % 10 === 0) {
fps = Math.round(1 / deltaTime);
}
// Control del personaje
isMoving = false;
let moveX = 0;
let moveZ = 0;
if (keys[‘W’]) {
moveZ += characterSpeed;
isMoving = true;
}
if (keys[‘S’]) {
moveZ -= characterSpeed;
isMoving = true;
}
if (keys[‘A’]) {
character.rotation.y += rotationSpeed;
}
if (keys[‘D’]) {
character.rotation.y -= rotationSpeed;
}
// Aplicar movimiento relativo a la rotación del personaje
if (moveZ !== 0) {
const angle = character.rotation.y;
character.position.x += Math.sin(angle) * moveZ;
character.position.z += Math.cos(angle) * moveZ;
}
// Limitar el movimiento dentro del mapa
character.position.x = Math.max(-180, Math.min(180, character.position.x));
character.position.z = Math.max(-180, Math.min(180, character.position.z));
// Actualizar animaciones
updateCharacterAnimation();
// Actualizar cámara
updateCameraPosition();
// Actualizar UI
document.getElementById(‘posX’).textContent = character.position.x.toFixed(2);
document.getElementById(‘posY’).textContent = character.position.y.toFixed(2);
document.getElementById(‘posZ’).textContent = character.position.z.toFixed(2);
document.getElementById(‘rotY’).textContent = character.rotation.y.toFixed(2);
document.getElementById(‘speed’).textContent = (isMoving ? characterSpeed : 0).toFixed(2);
document.getElementById(‘fps’).textContent = fps;
renderer.render(scene, camera);
}
// ==================== MANEJO DE REDIMENSIONAMIENTO ====================
window.addEventListener(‘resize’, () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// Iniciar animación
animate();
</script>
</body>
</html>
Miguel García Hernández, Ángel Iván Remigio Paulino y Iván Abdiel Ríos Cerón1 Comentario-
de que va tu codigo bro. saludos desde conta je
-
