https://sites.google.com/view/coche-3d-minimalista/full-page-embed
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Coche 3D Minimalista - Controles WASD</title>
<!-- Cargamos Three.js desde CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<style>
/* Estilos básicos para que el canvas ocupe toda la pantalla sin barras de desplazamiento */
body {
margin: 0;
overflow: hidden;
background-color: #1a1a1a;
font-family: sans-serif;
}
/* Cartel de instrucciones */
#instrucciones {
position: absolute;
top: 20px;
left: 20px;
color: white;
background: rgba(0, 0, 0, 0.6);
padding: 12px 20px;
border-radius: 8px;
pointer-events: none;
}
</style>
</head>
<body>
<!-- Cuadro informativo simple -->
<div id="instrucciones">
<h3 style="margin: 0 0 5px 0;">Controles:</h3>
<p style="margin: 0;"><b>W / S:</b> Avanzar / Retroceder</p>
<p style="margin: 0;"><b>A / D:</b> Girar Izquierda / Derecha</p>
</div>
<script>
// ==========================================
// 1. CONFIGURACIÓN INICIAL (Escena, Cámara, Renderizador)
// ==========================================
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x87ceeb); // Fondo color cielo
// Cámara de perspectiva
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
// Renderizador WebGL
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// ==========================================
// 2. ILUMINACIÓN
// ==========================================
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambientLight);
const sunLight = new THREE.DirectionalLight(0xffffff, 0.8);
sunLight.position.set(20, 40, 20);
scene.add(sunLight);
// ==========================================
// 3. SUELO
// ==========================================
const planeGeo = new THREE.PlaneGeometry(100, 100);
const planeMat = new THREE.MeshLambertMaterial({ color: 0x3e8e41 }); // Verde hierba
const ground = new THREE.Mesh(planeGeo, planeMat);
ground.rotation.x = -Math.PI / 2; // Acostar el plano horizontalmente
scene.add(ground);
// Grid (Rejilla visual para dar sensación de movimiento)
const grid = new THREE.GridHelper(100, 40, 0x000000, 0x555555);
grid.position.y = 0.01;
scene.add(grid);
// ==========================================
// 4. CREACIÓN DEL COCHE (Grupo de Objetos)
// ==========================================
const car = new THREE.Group();
// Carrocería (Caja azul)
const bodyGeo = new THREE.BoxGeometry(2, 0.8, 4);
const bodyMat = new THREE.MeshLambertMaterial({ color: 0x1e90ff });
const carBody = new THREE.Mesh(bodyGeo, bodyMat);
carBody.position.y = 0.6; // Elevar ligeramente del suelo
car.add(carBody);
// Techo/Cabina (Caja más pequeña sobre la carrocería)
const cabinGeo = new THREE.BoxGeometry(1.6, 0.6, 2);
const cabinMat = new THREE.MeshLambertMaterial({ color: 0x333333 });
const cabin = new THREE.Mesh(cabinGeo, cabinMat);
cabin.position.set(0, 1.3, -0.3);
car.add(cabin);
// Función auxiliar para crear ruedas simples
function createWheel(x, z) {
const wheelGeo = new THREE.CylinderGeometry(0.4, 0.4, 0.3, 16);
const wheelMat = new THREE.MeshLambertMaterial({ color: 0x111111 });
const wheel = new THREE.Mesh(wheelGeo, wheelMat);
wheel.rotation.z = Math.PI / 2; // Orientar rueda hacia los lados
wheel.position.set(x, 0.4, z);
return wheel;
}
// Añadir 4 ruedas al coche
car.add(createWheel(-1.1, 1.2)); // Delantera Izquierda
car.add(createWheel(1.1, 1.2)); // Delantera Derecha
car.add(createWheel(-1.1, -1.2)); // Trasera Izquierda
car.add(createWheel(1.1, -1.2)); // Trasera Derecha
// Agregar el coche a la escena
scene.add(car);
// ==========================================
// 5. CONTROL DE TECLADO (WASD)
// ==========================================
const keys = { w: false, a: false, s: false, d: false };
window.addEventListener('keydown', (e) => {
const key = e.key.toLowerCase();
if (keys.hasOwnProperty(key)) keys[key] = true;
});
window.addEventListener('keyup', (e) => {
const key = e.key.toLowerCase();
if (keys.hasOwnProperty(key)) keys[key] = false;
});
// ==========================================
// 6. LÓGICA DE MOVIMIENTO Y ANIMACIÓN
// ==========================================
let speed = 0;
const maxSpeed = 0.25;
const acceleration = 0.01;
const friction = 0.96; // Resistencia para frenar progresivamente
const turnSpeed = 0.04;
function animate() {
requestAnimationFrame(animate);
// Acelerar / Retroceder
if (keys.w) speed += acceleration;
if (keys.s) speed -= acceleration;
// Limitar velocidad máxima
speed = Math.max(-maxSpeed / 2, Math.min(maxSpeed, speed));
// Aplicar fricción cuando no se presiona ni W ni S
if (!keys.w && !keys.s) {
speed *= friction;
}
// Girar solo si el coche está en movimiento
if (Math.abs(speed) > 0.005) {
const direction = speed > 0 ? 1 : -1; // Invertir giro al ir marcha atrás
if (keys.a) car.rotation.y += turnSpeed * direction;
if (keys.d) car.rotation.y -= turnSpeed * direction;
}
// Mover el coche según su orientación actual
car.translateZ(speed);
// Hacer que la cámara siga al coche suavemente desde atrás
const relativeCameraOffset = new THREE.Vector3(0, 5, -10);
const cameraOffset = relativeCameraOffset.applyMatrix4(car.matrixWorld);
camera.position.x = cameraOffset.x;
camera.position.y = cameraOffset.y;
camera.position.z = cameraOffset.z;
camera.lookAt(car.position);
// Renderizar la escena
renderer.render(scene, camera);
}
// Redimensionar la pantalla dinámicamente
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// Iniciar bucle de animación
window.onload = function() {
animate();
};
</script>
</body>
</html>

No hay comentarios:
Publicar un comentario