_____ ____ __ __ _____ ____ ___ _____ _ / ____| / __ \| \/ || ____|| _ \ |_ _||_ _|/ \ | | __ | | | | |\/| || _| | |_) || | | | / _ \ | | |_ || |__| | | | || |___ | _ < | | | |/ ___ \ \_____| \____/|_| |_||_____||_| \_\___| |_|_/ \_\ 0documentacion.txt ( UTF-8 Unicode text, with CRLF line terminators ) # 🏎️ RETRO RACER — Documentación Técnica & Contexto para IA > **Versión:** Fase 1 (Motor Base Pseudo-3D) > **Stack:** HTML5 Canvas 2D, JavaScript Vanilla (ES5/ES6 híbrido), CSS3 > **Inspiración:** Out Run, Road Rash, Need for Speed 1, estética New Retro Net / Synthwave > **Propósito final:** Un juego arcade de carreras pseudo-3D que funcione como videoclip interactivo para una canción por estrenar. ================================================================================ RETRO RACER — README PARA COPILOT / IA ================================================================================ VERSIÓN: Fase 2 (Física Arcade Pulida) FECHA: Septiembre 2026 ESTADO: ✅ COMPLETADO — Listo para Fase 3 (Sprites) ================================================================================ 1. DESCRIPCIÓN GENERAL DEL PROYECTO ================================================================================ Retro Racer es un juego de carreras pseudo-3D estilo Outrun en HTML5 Canvas. El motor usa proyección 3D→2D clásica (técnica de "franjas horizontales") para simular profundidad sin WebGL. OBJETIVO FINAL: Un juego arcade que funcione como videoclip interactivo para una canción, con estética New Retro Net / Synthwave. INSPIRACIÓN: Out Run, Road Rash, Need for Speed 1. STACK: HTML5 Canvas 2D, JavaScript Vanilla (ES5/ES6 híbrido), CSS3. SIN dependencias externas. SIN frameworks. SIN bundlers. ================================================================================ 2. ESTRUCTURA DE ARCHIVOS ================================================================================ retro-racer/ ├── index.html # Estructura DOM, carga de scripts ├── css/ │ └── style.css # Estilos base, HUD, paleta synthwave └── js/ ├── engine.js # Configuración global, constantes, utilidades, input ├── road.js # Generador procedural de la pista (segmentos) ├── renderer.js # Motor de renderizado pseudo-3D └── main.js # Game loop, física arcade, HUD ================================================================================ 3. ARQUITECTURA Y PATRONES DE CÓDIGO ================================================================================ 3.1 NAMESPACE PATTERN Todos los módulos son objetos globales: - Engine → configuración y utilidades - Road → generador de pista - Renderer → dibujo y proyección - Game → loop y física NO se usan clases ES6 ni módulos ES6. Todo es función/propiedad dentro de objetos. 3.2 CONVENCIONES DE CÓDIGO - Comentarios en ESPAÑOL - Funciones definidas como: nombre: function() { ... } - Propiedades accedidas como: Engine.propiedad - SIN variables globales sueltas (usar siempre Engine.width/height) 3.3 REGLAS DE ORO PARA IA/COPILOT 1. NUNCA uses variables globales sueltas como "width" o "height". Usá SIEMPRE Engine.width y Engine.height. 2. El auto del jugador NO se dibuja en Y fija (height - 120). Su posición en pantalla se calcula proyectando el punto 3D del suelo. Mirá renderer.js → drawPlayer() → parámetro playerScreenY. 3. El auto NO se centra solo. NO agregues código que empuje playerX hacia 0. La única excepción es cuando playerX está fuera de los límites (> 1.5). 4. Las constantes de fricción son factores de decaimiento POR SEGUNDO. Valores entre 0.5 y 10. NO son fuerzas brutas. - lateralFriction: 4 → la inercia se frena en ~0.25s - driftFriction: 0.8 → en derrape se frena más lento 5. Las partículas son 2D relativas al auto (sistema en renderer.js). NO intentes proyectarlas en 3D. Usan coordenadas offset desde el auto. 6. SIEMPRE que agregues una propiedad a Engine, inicializala con valor por defecto. ================================================================================ 4. DESCRIPCIÓN DE CADA ARCHIVO ================================================================================ 4.1 engine.js — "El Cerebro" ──────────────────────────────────────────────────────────────────────────────── PROPÓSITO: Configuración global, constantes, utilidades matemáticas, input. MÓDULOS (14): 1. Canvas y Render → canvas, ctx, width, height 2. Cámara → cameraHeight, cameraDepth, drawDistance, fieldOfView 3. Carretera → segmentLength, roadWidth, lanes, rumbleLength 4. Estado (Longitudinal) → playerX, playerZ, speed 5. Física Básica → maxSpeed, accel, offRoadLimit 6. Movimiento Lateral (Fase 2) → speedX, maxSpeedX, lateralFriction, driftFriction, lean 7. Centrífuga → centrifugal (fuerza en curvas) 8. Turbo → turbo, turboTimer, turboCooldown, turboDuration, etc. 9. Frenado → brakeForce, rollingFriction, brakeLights 10. Efectos Visuales → cameraShake 11. Entrada → keys 12. Utilidades → limit, interpolate, easeIn, easeOut, easeInOut, percentRemaining 13. Inicialización → init(), resize() 14. Sistema Teclado → bindKeys(), keyDown() PARÁMETROS CLAVE PARA AJUSTAR: ──────────────────────────────────────────────────────────────────────────────── | Propiedad | Valor | Efecto | |--------------------|--------|--------| | maxSpeed | 12000 | Velocidad máxima | | accel | 3000 | Aceleración base | | brakeForce | -15000 | Fuerza de frenado (negativo = frena) | | rollingFriction | -800 | Rozamiento al soltar acelerador | | lateralFriction | 4 | Fricción lateral normal (decaimiento/seg) | | driftFriction | 0.8 | Fricción en derrape (más bajo = más derrape) | | maxSpeedX | 2000 | Velocidad lateral máxima | | centrifugal | 0.003 | Fuerza centrífuga en curvas | | turboDuration | 1.5 | Duración del turbo (segundos) | | turboCooldownTime | 3.0 | Cooldown después de turbo (segundos) | | turboMaxSpeedBonus | 1.3 | Multiplicador de velocidad (+30%) | | doubleTapWindow | 300 | Ventana para doble tap (ms) | | cameraShake | 0-2 | Intensidad de vibración (0 = sin shake) | ================================================================================ 4.2 main.js — "El Director de Orquesta" ──────────────────────────────────────────────────────────────────────────────── PROPÓSITO: Game loop, física arcade, integración de todos los módulos. MÓDULOS (11): A — Timing y Estado → init(), loop(), dt, fps B — Aceleración/Frenado → calculateAcceleration(), checkDoubleTap() C — Centrífuga → updateCentrifugal() (NUEVO — empuja en curvas) D — Dirección/Inercia → updateSteering() (giro directo + inercia lateral) E — Colisión (4 Zonas) → updateCollision() (SIN centrado automático) F — Turbo → updateTurbo() (duración, cooldown) G — Inclinación Visual → updateLean() (inclinación del auto) H — Posición Z → updatePosition() (avance y loop) I — Partículas → updateParticles() (humo y chispas) J — Orquestador Principal → updatePhysics() (NO TOCAR el orden) K — HUD → updateHUD() (velocímetro, turbo) ORDEN DE EJECUCIÓN EN updatePhysics() (NO CAMBIAR): ──────────────────────────────────────────────────────────────────────────────── 1. updateTurbo() → Calcula velocidad máxima (con/sin turbo) 2. calculateAcceleration() → Acelera/frena/rozamiento 3. updateCentrifugal() → Empuja en curvas (NUEVO) 4. updateSteering() → Giro directo + inercia lateral 5. updateCollision() → Bordes, tierra, barrera (SIN centrado) 6. updateLean() → Inclinación visual 7. updatePosition() → Avance en Z y loop de pista 8. updateParticles() → Genera humo/chispas PARÁMETROS CLAVE PARA AJUSTAR EN updateSteering(): ──────────────────────────────────────────────────────────────────────────────── | Variable | Valor | Efecto | |-----------------|-------|--------| | steerSpeed | 3.5 | Sensibilidad del giro directo | | inertiaForce | 600 | Fuerza de inercia lateral | | frictionDecay | 1.5x | Multiplicador de fricción normal | | frictionDecay | 0.5x | Multiplicador de fricción en derrape | ================================================================================ 4.3 renderer.js — "El Pintor" ──────────────────────────────────────────────────────────────────────────────── PROPÓSITO: Proyección 3D→2D, dibujo de carretera, partículas, jugador. MÓDULOS (7): 1. Sistema de Partículas → addParticle(), updateParticles(), drawParticles() 2. Proyección 3D→2D → project() (NO TOCAR — matemática central) 3. Dibujo de Polígonos → drawPolygon(), roundRect() 4. Renderizado Principal → render() (ordena toda la escena) 5. Fondo Synthwave → drawSky() (cielo, sol, grid, estrellas) 6. Carretera (Franja) → drawSegment() (césped, bordes, asfalto, líneas) 7. Jugador (Auto) → drawPlayer() (CON playerScreenY para seguir el suelo) FIX CRÍTICO EN RENDERER — EL AUTO YA NO FLOTA EN COLINAS: ──────────────────────────────────────────────────────────────────────────────── El auto se dibuja usando playerScreenY (calculado proyectando el punto 3D del suelo donde está el jugador), NO con height - 120 fijo. CÓDIGO CLAVE EN render(): ──────────────────────────────────────────────────────────────────────────────── const playerWorldY = Engine.interpolate( baseSegment.p1.world.y, baseSegment.p2.world.y, basePercent ); const playerPoint = { world: { x: 0, y: playerWorldY, z: playerZ }, camera: {}, screen: {} }; this.project(playerPoint, cameraX, cameraY, cameraZ, ...); const playerScreenY = playerPoint.screen.y; // Luego se pasa a drawPlayer(): this.drawPlayer(ctx, width, height, resolution, speed, maxSpeed, playerScreenY); ================================================================================ 4.4 road.js — "El Generador de Pista" ──────────────────────────────────────────────────────────────────────────────── PROPÓSITO: Crea la pista como array de segmentos con curvas y elevaciones. MÓDULOS (6): 1. Estado y Colores → segments[], totalLength, colors 2. Construcción Segmentos → addSegment(), lastY() 3. Construcción Tramo → addRoad() (enter, hold, leave, curve, y) 4. Tipos de Tramo → addStraight(), addCurve(), addSCurve(), addHill() 5. Generador de Pista → generate() (LAYOUT COMPLETO — MODIFICAR AQUÍ) 6. Búsqueda de Segmentos → findSegment() PARÁMETROS DE addRoad(enter, hold, leave, curve, height): ──────────────────────────────────────────────────────────────────────────────── | Parámetro | Rango | Efecto | |-----------|----------|--------| | enter | 50-150 | Transición de entrada (más = más suave) | | hold | 50-300 | Duración del tramo | | leave | 50-150 | Transición de salida (más = más suave) | | curve | -4 a 4 | -4 = curva cerrada izq, 0 = recta, 4 = curva cerrada der | | height | -500 a 500 | Elevación (- = bajada, + = subida) | LAYOUT ACTUAL DE LA PISTA (en generate()): ──────────────────────────────────────────────────────────────────────────────── 1. addStraight(25) → Línea de salida 2. addCurve(100, 2, 0) → Curva suave derecha 3. addRoad(80, 160, 80, 0, 200) → Subida suave 4. addSCurve() → S-curvas 5. addStraight(150) → Recta larga 6. addRoad(80, 160, 80, -4, -200) → Bajada suave con curva cerrada 7. addStraight(100) → Recta 8. addRoad(80, 160, 80, 3, 350) → Subida suave con curva 9. addStraight(200) → Recta final ================================================================================ 5. RESUMEN DE CAMBIOS APLICADOS (FASE 2) ================================================================================ 5.1 PROBLEMAS ORIGINALES QUE DEEPSEEK NO SUPO RESOLVER ──────────────────────────────────────────────────────────────────────────────── | Problema | Error de DeepSeek | Fix aplicado | |----------|-------------------|--------------| | Auto flotaba en bajadas | Dibujaba el auto en Y fija (height - 120) | Se calcula playerScreenY proyectando el punto 3D del suelo | | Centrado automático | playerX *= (1 - 0.5 * dt) en zona 1 | ELIMINADO — el auto se queda donde está | | Auto no se iba en curvas | No implementó fuerza centrífuga | Módulo C: updateCentrifugal() | | Freno lento | brakeForce: -6000 | brakeForce: -15000 (2.5x más fuerte) | | Rozamiento bajo | rollingFriction: -60 | rollingFriction: -800 (13x más fuerte) | | Valores de física confusos | lateralFriction: 50 (fuerza bruta) | lateralFriction: 4 (decaimiento/seg) | | Partículas en 3D | Proyectaba partículas con proyección 3D | Sistema 2D relativo al auto | 5.2 NUEVAS FUNCIONALIDADES IMPLEMENTADAS ──────────────────────────────────────────────────────────────────────────────── | Funcionalidad | Módulo | Descripción | |---------------|--------|-------------| | Inercia lateral | main.js — D | speedX se acumula al girar y decae con fricción | | Derrape | main.js — D | Shift/Space reduce fricción lateral | | Turbo | main.js — F | Doble tap de ↑ activa +30% velocidad por 1.5s | | Centrífuga | main.js — C | Empuja al auto hacia afuera en curvas | | 4 Zonas de colisión | main.js — E | Pista, tierra, fuera de pista, barrera | | Inclinación visual | main.js — G | lean interpolado suavemente | | Vibración de cámara | main.js — E | cameraShake en colisiones | | Partículas | main.js — I | Humo en derrape, chispas en turbo | | Luces de freno | renderer.js — 7 | Rojo brillante al frenar | 5.3 PARÁMETROS FINALES (VALORES ACTUALES) ──────────────────────────────────────────────────────────────────────────────── // engine.js — Física Lateral speedX: 0 // Velocidad lateral actual (DEBE SER 0) maxSpeedX: 2000 // Velocidad lateral máxima lateralFriction: 4 // Fricción normal (decaimiento/seg) driftFriction: 0.8 // Fricción en derrape (más bajo = más derrape) // engine.js — Centrífuga centrifugal: 0.003 // Fuerza en curvas // engine.js — Frenado brakeForce: -15000 // Fuerza de frenado (agresivo) rollingFriction: -800 // Rozamiento al soltar acelerador // engine.js — Turbo turboDuration: 1.5 // Segundos de duración turboCooldownTime: 3.0 // Segundos de cooldown turboMaxSpeedBonus: 1.3 // +30% velocidad doubleTapWindow: 300 // Ventana para doble tap (ms) // main.js — Módulo D (Steering) steerSpeed: 3.5 // Sensibilidad de giro directo inertiaForce: 600 // Fuerza de inercia lateral ================================================================================ 6. INSTRUCCIONES PARA FUTURAS MODIFICACIONES ================================================================================ 6.1 CÓMO MODIFICAR CADA ASPECTO DEL JUEGO ──────────────────────────────────────────────────────────────────────────────── | QUERÉS CAMBIAR... | ARCHIVO | MÓDULO | QUÉ EDITAR | |-------------------|---------|--------|------------| | Colores (magenta, cian, fondo) | engine.js | 1 | colors | | Forma de la pista | road.js | 5 | generate() | | Fuerza en curvas | engine.js | 7 | centrifugal | | Sensibilidad del giro | main.js | D | steerSpeed | | Fuerza de frenado | engine.js | 9 | brakeForce | | Rozamiento al soltar | engine.js | 9 | rollingFriction | | Duración del turbo | engine.js | 8 | turboDuration | | Fricción lateral | engine.js | 6 | lateralFriction | | Fricción en derrape | engine.js | 6 | driftFriction | | Velocidad máxima | engine.js | 5 | maxSpeed | | Cielo, sol, estrellas | renderer.js | 5 | drawSky() | | Aspecto del auto | renderer.js | 7 | drawPlayer() | | HUD (velocímetro, etc.) | main.js | K | updateHUD() | 6.2 CÓMO AÑADIR UNA NUEVA FUNCIONALIDAD ──────────────────────────────────────────────────────────────────────────────── 1. Si es una CONFIGURACIÓN → agregar propiedad en engine.js (módulo correspondiente) 2. Si es LÓGICA DE FÍSICA → agregar función en main.js (nuevo módulo o extender existente) 3. Si es DIBUJO → agregar función en renderer.js 4. Si es UN NUEVO TIPO DE TRAMO → agregar helper en road.js (módulo 4) 6.3 QUÉ NO TOCAR BAJO NINGÚN CONCEPTO ──────────────────────────────────────────────────────────────────────────────── - renderer.js → project() (rompe toda la proyección 3D) - main.js → updatePhysics() (orden de ejecución) - road.js → addSegment() y lastY() (estructura interna) - Engine.width y Engine.height (usar siempre, no variables globales) ================================================================================ 7. CONTROLES DEL JUEGO ================================================================================ | TECLA | ACCIÓN | |-------|--------| | ↑ / W | Acelerar (doble tap = turbo) | | ↓ / S | Frenar (frena fuerte) | | ← / A | Girar a la izquierda | | → / D | Girar a la derecha | | Shift / Space | Derrape (mantener mientras se gira) | ================================================================================ 8. ROADMAP DEL PROYECTO ================================================================================ ✅ Fase 1 — Motor Base (completado) - Pseudo-3D con proyección de segmentos - Curvas, colinas, cielo synthwave - Auto placeholder geométrico ✅ Fase 2 — Física Arcade Pulida (COMPLETADO) - Inercia lateral (speedX) - Derrape con Shift/Space - Turbo con doble tap - Centrífuga en curvas - 4 zonas de colisión - Inclinación visual (lean) - Partículas (humo + chispas) - Vibración de cámara - Luces de freno - Frenado agresivo - Rozamiento realista ⏳ Fase 3 — Sistema de Sprites (PRÓXIMO) - Cargar PNG con transparencia - Sprites en segmentos (palmeras, postes, edificios) - Sprite del jugador reemplaza placeholder - Escalado por distancia ⏳ Fase 4 — Audio y Atmósfera - Integrar canción (Web Audio API) - Sincronizar eventos con la música - HUD definitivo - Post-procesado (scanlines, vignette) ⏳ Fase 5 — Combate (opcional) - Rivales tipo Road Rash - Golpes, patadas, caídas ⏳ Fase 6 — Deploy y Polish - Menús, pantallas - Responsive - PWA ================================================================================ 9. CONTACTO Y REFERENCIAS ================================================================================ DOCUMENTACIÓN TÉCNICA COMPLETA: Ver DOCUMENTACION.md MAPA DE ARCHIVOS: Ver "Mapa de archivos ¿dónde está cada cosa.txt" ================================================================================ 10. NOTA FINAL PARA COPILOT/IA ================================================================================ Este proyecto es INTENCIONALMENTE VANILLA. No hay frameworks, no hay bundlers, no hay dependencias externas. Todo corre en el navegador abriendo index.html. RESPETÁ: - El namespace pattern (Engine.propiedad, Game.metodo()) - Los comentarios en español - Las firmas de funciones existentes - La estructura modular (cada módulo tiene un propósito claro) SI TENÉS DUDAS sobre cómo funciona algo, leé los comentarios en el código. CADA MÓDULO tiene una descripción clara de su propósito. ¡BUENA SUERTE! 🏎️💨 ================================================================================ FIN DEL README ================================================================================ ``` --- ## 📋 Resumen del README | Sección | Contenido | |---|---| | **1. Descripción General** | Qué es Retro Racer, stack, inspiración | | **2. Estructura de Archivos** | Árbol de archivos del proyecto | | **3. Arquitectura y Patrones** | Namespace pattern, convenciones, REGLAS DE ORO | | **4. Descripción de cada archivo** | engine.js, main.js, renderer.js, road.js (con módulos y parámetros) | | **5. Resumen de Cambios** | Problemas originales, fixes, nuevas funcionalidades, parámetros finales | | **6. Instrucciones para Futuras Modificaciones** | Qué cambiar para cada aspecto, cómo añadir funcionalidades, qué NO tocar | | **7. Controles del Juego** | Teclas y acciones | | **8. Roadmap** | Fases completadas y pendientes | | **9. Contacto** | Referencias a otros documentos | | **10. Nota Final** | Recordatorio de reglas para IA | ---