// =================================================================== // RETRO LEGENDS: Ultimate Edition - Core Engine Ultra Avanzado // Desarrollado con arquitectura modular profesional y optimización extrema // =================================================================== class RetroLegendsUltimateEngine { constructor() { // Configuración del canvas y contexto this.canvas = document.getElementById('gameCanvas'); this.ctx = this.canvas.getContext('2d'); this.setupCanvas(); // Estados del motor this.engineState = { isInitialized: false, isRunning: false, isPaused: false, debugMode: false, performanceMode: 'ultra', frameRate: 60, deltaTime: 0, lastFrameTime: 0, frameCount: 0, averageFPS: 60 }; // Estado del juego principal this.gameState = { currentLevel: 'caminito_matrix', score: 0, lives: 3, mateCount: 5, health: 100, maxHealth: 100, energy: 100, maxEnergy: 100, combo: 0, maxCombo: 0, time: 0, difficulty: 1, experience: 0, level: 1, achievements: new Set(), powerUps: new Map(), inventory: new Map() }; // Configuración del jugador ultra avanzada this.player = { // Posición y dimensiones x: 150, y: 400, width: 32, height: 32, centerX: 0, centerY: 0, // Velocidades y física velocityX: 0, velocityY: 0, acceleration: 0.8, deceleration: 0.85, maxSpeed: 8, jumpPower: 16, doubleJumpPower: 12, dashPower: 15, // Estados del jugador grounded: false, canDoubleJump: false, canDash: true, isDashing: false, isAttacking: false, isInvulnerable: false, isCharging: false, // Direcciones y orientación facing: 'right', lastDirection: 'right', // Timers y cooldowns invulnerabilityTimer: 0, dashCooldown: 0, attackCooldown: 0, chargeCooldown: 0, // Sprites y animaciones currentSprite: '🧉', spriteSet: { idle: ['🧉', '🧉'], running: ['🏃‍♂️', '🚶‍♂️'], jumping: ['🤸‍♂️'], attacking: ['⚔️', '🥊'], dashing: ['💨'], charging: ['⚡', '🔥'] }, animationFrame: 0, animationSpeed: 200, lastAnimationTime: 0, // Estadísticas y progresión stats: { strength: 10, agility: 10, defense: 10, luck: 10, charisma: 10 }, // Habilidades especiales abilities: { mateHealing: true, empanadasPower: false, choripanShield: false, fernetRage: false, tangoTime: false }, // Sistema de combos argentinos comboSystem: { currentCombo: [], comboTimer: 0, maxComboTime: 2000, availableCombos: [ { sequence: ['che', 'boludo', 'dale'], name: 'Combo Argento', power: 150 }, { sequence: ['mate', 'asado', 'futbol'], name: 'Combo Patriótico', power: 200 }, { sequence: ['tango', 'milonga', 'bandoneón'], name: 'Combo Porteño', power: 250 } ] } }; // Configuración de físicas avanzadas this.physics = { gravity: 0.8, terminalVelocity: 20, airResistance: 0.98, groundFriction: 0.85, bounceFactor: 0.3, collisionPadding: 2, // Configuraciones específicas por material materials: { concrete: { friction: 0.8, bounce: 0.1 }, grass: { friction: 0.9, bounce: 0.2 }, ice: { friction: 0.3, bounce: 0.1 }, rubber: { friction: 0.7, bounce: 0.8 }, metal: { friction: 0.6, bounce: 0.4 } } }; // Configuración de cámara avanzada this.camera = { x: 0, y: 0, targetX: 0, targetY: 0, smoothing: 0.1, shake: { x: 0, y: 0, intensity: 0, duration: 0 }, zoom: 1, targetZoom: 1, bounds: { left: 0, right: 2000, top: 0, bottom: 1000 }, // Efectos de cámara effects: { screenShake: false, slowMotion: false, colorFilter: null, vignette: false } }; // Configuración de niveles procedurales this.levelConfig = { currentLevel: null, levelData: new Map(), proceduralSeed: Date.now(), chunkSize: 800, loadedChunks: new Map(), activeChunks: new Set(), // Configuraciones por nivel levelTypes: { caminito_matrix: { theme: 'urban_argentina', difficulty: 1, enemies: ['mantero', 'bondi', 'taxi'], powerUps: ['mate', 'empanada', 'choripan'], music: 'tango_chiptune', background: 'la_boca_neon' }, obelisco_cyber: { theme: 'cyberpunk_bsas', difficulty: 2, enemies: ['drone_policia', 'hacker', 'cyborg_portero'], powerUps: ['fernet_digital', 'asado_hologram'], music: 'cumbia_synthwave', background: 'obelisco_matrix' } } }; // Sistema de partículas ultra avanzado this.particleSystem = { particles: [], maxParticles: 500, pools: { explosion: [], trail: [], sparkle: [], smoke: [], blood: [], energy: [] }, // Configuraciones de efectos effects: { playerTrail: { enabled: true, intensity: 0.7 }, impactSparks: { enabled: true, intensity: 1.0 }, ambientParticles: { enabled: true, intensity: 0.5 }, weatherEffects: { enabled: true, type: 'none' } } }; // Sistema de audio ultra avanzado this.audioSystem = { context: null, masterVolume: 0.7, sfxVolume: 0.8, musicVolume: 0.6, // Canales de audio channels: { master: null, music: null, sfx: null, ambient: null, voice: null }, // Biblioteca de sonidos sounds: new Map(), currentMusic: null, musicQueue: [], // Efectos de audio avanzados effects: { reverb: null, delay: null, distortion: null, filter: null } }; // Sistema de IA compañero ultra inteligente this.aiCompanion = { personality: { humor: 0.8, sarcasm: 0.6, encouragement: 0.9, knowledge: 0.95, patience: 0.7, argentineness: 1.0 }, // Estados emocionales mood: 'excited', relationship: 50, // 0-100 trust: 30, // 0-100 // Sistema de memoria memory: { playerActions: [], conversations: [], achievements: [], preferences: new Map(), personalData: new Map() }, // Sistema de respuestas contextuales responseSystem: { contextAnalyzer: null, emotionEngine: null, humorGenerator: null, knowledgeBase: new Map() }, // Configuración de chat chatConfig: { isActive: false, autoResponse: true, responseDelay: 1500, maxMessageLength: 200, currentConversation: [] } }; // Sistemas del motor this.systems = { input: null, physics: null, rendering: null, audio: null, ai: null, particles: null, entities: null, levels: null, save: null, achievements: null, analytics: null }; // Configuración de rendimiento this.performance = { targetFPS: 60, adaptiveQuality: true, cullingEnabled: true, lodEnabled: true, // Métricas de rendimiento metrics: { frameTime: 0, drawCalls: 0, particleCount: 0, entityCount: 0, memoryUsage: 0 }, // Configuraciones de calidad qualityLevels: { potato: { particles: 50, effects: false, shadows: false }, low: { particles: 100, effects: true, shadows: false }, medium: { particles: 250, effects: true, shadows: true }, high: { particles: 400, effects: true, shadows: true }, ultra: { particles: 500, effects: true, shadows: true } } }; // Configuración de red y multijugador (futuro) this.network = { isOnline: false, playerId: null, sessionId: null, peers: new Map(), latency: 0, // Configuración de sincronización sync: { enabled: false, rate: 20, // Hz interpolation: true, prediction: true } }; // Sistema de eventos avanzado this.eventSystem = { listeners: new Map(), queue: [], processing: false, // Tipos de eventos eventTypes: { PLAYER_MOVE: 'player_move', PLAYER_JUMP: 'player_jump', PLAYER_ATTACK: 'player_attack', ENEMY_SPAWN: 'enemy_spawn', ITEM_COLLECT: 'item_collect', LEVEL_COMPLETE: 'level_complete', ACHIEVEMENT_UNLOCK: 'achievement_unlock', AI_RESPONSE: 'ai_response' } }; // Inicializar el motor this.initialize(); } // =================================================================== // MÉTODOS DE INICIALIZACIÓN // =================================================================== async initialize() { console.log('🚀 Inicializando RETRO LEGENDS: Ultimate Engine...'); try { // Configurar canvas this.setupCanvas(); // Inicializar sistemas principales await this.initializeSystems(); // Cargar recursos await this.loadResources(); // Configurar nivel inicial await this.loadInitialLevel(); // Configurar IA this.initializeAI(); // Inicializar sistema de eventos this.initializeEventSystem(); // Configurar sistema de guardado this.initializeSaveSystem(); // Marcar como inicializado this.engineState.isInitialized = true; this.engineState.isRunning = true; // Iniciar loop principal this.startMainLoop(); console.log('✅ RETRO LEGENDS: Ultimate Engine inicializado correctamente'); // Disparar evento de inicialización this.dispatchEvent('ENGINE_INITIALIZED', { timestamp: Date.now() }); } catch (error) { console.error('❌ Error inicializando el motor:', error); throw error; } } setupCanvas() { // Configurar tamaño responsivo this.resizeCanvas(); window.addEventListener('resize', () => this.resizeCanvas()); // Configurar contexto para renderizado pixelado this.ctx.imageSmoothingEnabled = false; this.ctx.webkitImageSmoothingEnabled = false; this.ctx.mozImageSmoothingEnabled = false; this.ctx.msImageSmoothingEnabled = false; // Configurar filtros de renderizado this.ctx.filter = 'contrast(1.1) saturate(1.2) brightness(1.05)'; console.log('🖥️ Canvas configurado:', this.canvas.width, 'x', this.canvas.height); } resizeCanvas() { const container = this.canvas.parentElement; const rect = container.getBoundingClientRect(); // Configurar tamaño manteniendo aspect ratio 16:9 const aspectRatio = 16 / 9; let width = rect.width; let height = rect.height; if (width / height > aspectRatio) { width = height * aspectRatio; } else { height = width / aspectRatio; } this.canvas.width = width; this.canvas.height = height; // Actualizar bounds de cámara this.camera.bounds.right = width * 2; this.camera.bounds.bottom = height * 1.5; } async initializeSystems() { console.log('🔧 Inicializando sistemas del motor...'); // Sistema de input avanzado this.systems.input = new AdvancedInputHandler(this); // Sistema de físicas this.systems.physics = new AdvancedPhysicsEngine(this); // Sistema de renderizado this.systems.rendering = new AdvancedRenderingSystem(this); // Sistema de audio this.systems.audio = new UltraAudioSystem(this); await this.systems.audio.initialize(); // Sistema de partículas this.systems.particles = new AdvancedParticleSystem(this); // Sistema de entidades this.systems.entities = new UltraEntityManager(this); // Sistema de niveles this.systems.levels = new ProceduralLevelGenerator(this); // Sistema de IA this.systems.ai = new AdvancedAICompanion(this); // Sistema de guardado this.systems.save = new AdvancedSaveSystem(this); // Sistema de logros this.systems.achievements = new AchievementSystem(this); // Sistema de analíticas this.systems.analytics = new GameAnalytics(this); console.log('✅ Todos los sistemas inicializados'); } async loadResources() { console.log('📦 Cargando recursos del juego...'); // Cargar sprites y texturas await this.loadSprites(); // Cargar sonidos await this.loadAudio(); // Cargar datos de niveles await this.loadLevelData(); // Cargar configuraciones de IA await this.loadAIData(); console.log('✅ Recursos cargados correctamente'); } async loadSprites() { // Aquí cargaríamos sprites reales en una implementación completa console.log('🎨 Sprites cargados (modo texto para demo)'); } async loadAudio() { // Inicializar contexto de audio if (!this.audioSystem.context) { this.audioSystem.context = new (window.AudioContext || window.webkitAudioContext)(); } console.log('🎵 Sistema de audio inicializado'); } async loadLevelData() { // Cargar configuraciones de niveles this.levelConfig.levelData.set('caminito_matrix', { name: 'Caminito Matrix', theme: 'cyberpunk_argentina', size: { width: 2000, height: 800 }, spawnPoints: [{ x: 100, y: 400 }], enemies: ['mantero_cyber', 'bondi_hologram', 'taxi_drone'], collectibles: ['mate_digital', 'empanada_power', 'choripan_shield'] }); console.log('🗺️ Datos de niveles cargados'); } async loadAIData() { // Cargar base de conocimiento de la IA this.aiCompanion.responseSystem.knowledgeBase.set('argentina', { cultura: ['mate', 'asado', 'tango', 'futbol', 'Maradona'], lugares: ['Buenos Aires', 'Córdoba', 'Mendoza', 'Bariloche'], comidas: ['empanadas', 'choripan', 'milanesas', 'dulce de leche'], expresiones: ['che', 'boludo', 'dale', 'bárbaro', 'copado'] }); console.log('🤖 Base de conocimiento de IA cargada'); } async loadInitialLevel() { console.log('🏗️ Cargando nivel inicial...'); // Cargar Caminito Matrix await this.systems.levels.loadLevel('caminito_matrix'); // Posicionar jugador this.player.x = 150; this.player.y = 400; // Configurar cámara this.updateCamera(); console.log('✅ Nivel inicial cargado'); } initializeAI() { console.log('🧠 Inicializando IA compañero...'); // Configurar personalidad inicial this.aiCompanion.mood = 'excited'; this.aiCompanion.relationship = 50; // Mensaje de bienvenida setTimeout(() => { this.systems.ai.sendMessage( "¡Ehhhh, pibe! ¡Bienvenido a la experiencia más nostálgica y avanzada de tu vida! " + "Soy NEXUS, tu compañero argento con IA de última generación. " + "¿Listos para romperla en este universo retro-futurista? ¡Dale que arrancamos! 🚀🇦🇷" ); }, 2000); console.log('✅ IA compañero inicializada'); } initializeEventSystem() { console.log('📡 Inicializando sistema de eventos...'); // Configurar listeners principales this.addEventListener('PLAYER_MOVE', (data) => { this.systems.ai.onPlayerMove(data); this.systems.analytics.trackEvent('player_movement', data); }); this.addEventListener('PLAYER_JUMP', (data) => { this.systems.ai.onPlayerJump(data); this.systems.particles.createJumpEffect(data.x, data.y); }); this.addEventListener('ITEM_COLLECT', (data) => { this.systems.ai.onItemCollect(data); this.updateScore(data.points); }); console.log('✅ Sistema de eventos configurado'); } initializeSaveSystem() { console.log('💾 Inicializando sistema de guardado...'); // Cargar datos guardados si existen this.systems.save.loadGame(); // Configurar auto-guardado cada 30 segundos setInterval(() => { this.systems.save.autoSave(); }, 30000); console.log('✅ Sistema de guardado configurado'); } // =================================================================== // LOOP PRINCIPAL DEL JUEGO // =================================================================== startMainLoop() { console.log('🔄 Iniciando loop principal del juego...'); this.engineState.lastFrameTime = performance.now(); this.mainLoop(); } mainLoop() { if (!this.engineState.isRunning) return; // Calcular delta time const currentTime = performance.now(); this.engineState.deltaTime = currentTime - this.engineState.lastFrameTime; this.engineState.lastFrameTime = currentTime; // Actualizar FPS this.updateFPS(); // Verificar rendimiento y ajustar calidad si es necesario this.checkPerformance(); // Actualizar solo si no está pausado if (!this.engineState.isPaused) { this.update(this.engineState.deltaTime); } // Renderizar siempre this.render(); // Continuar el loop requestAnimationFrame(() => this.mainLoop()); } update(deltaTime) { // Actualizar tiempo de juego this.gameState.time += deltaTime; // Actualizar sistemas principales this.updatePlayer(deltaTime); this.updateCamera(deltaTime); this.updatePhysics(deltaTime); // Actualizar sistemas secundarios this.systems.entities.update(deltaTime); this.systems.particles.update(deltaTime); this.systems.levels.update(deltaTime); this.systems.ai.update(deltaTime); // Procesar eventos this.processEvents(); // Verificar colisiones this.checkCollisions(); // Actualizar UI this.updateUI(); // Verificar condiciones de juego this.checkGameConditions(); // Actualizar analíticas this.systems.analytics.update(deltaTime); } updatePlayer(deltaTime) { const player = this.player; // Actualizar timers this.updatePlayerTimers(deltaTime); // Procesar input del jugador this.systems.input.processPlayerInput(deltaTime); // Aplicar física del jugador this.applyPlayerPhysics(deltaTime); // Actualizar animaciones this.updatePlayerAnimation(deltaTime); // Actualizar centro del jugador player.centerX = player.x + player.width / 2; player.centerY = player.y + player.height / 2; // Verificar límites del mundo this.checkWorldBounds(); // Actualizar sistema de combos this.updateComboSystem(deltaTime); } updatePlayerTimers(deltaTime) { const player = this.player; // Timer de invulnerabilidad if (player.invulnerabilityTimer > 0) { player.invulnerabilityTimer -= deltaTime; if (player.invulnerabilityTimer <= 0) { player.isInvulnerable = false; } } // Cooldown de dash if (player.dashCooldown > 0) { player.dashCooldown -= deltaTime; if (player.dashCooldown <= 0) { player.canDash = true; } } // Cooldown de ataque if (player.attackCooldown > 0) { player.attackCooldown -= deltaTime; if (player.attackCooldown <= 0) { player.isAttacking = false; } } // Timer de combo if (player.comboSystem.comboTimer > 0) { player.comboSystem.comboTimer -= deltaTime; if (player.comboSystem.comboTimer <= 0) { player.comboSystem.currentCombo = []; } } } applyPlayerPhysics(deltaTime) { const player = this.player; const physics = this.physics; // Aplicar gravedad si no está en el suelo if (!player.grounded) { player.velocityY += physics.gravity; if (player.velocityY > physics.terminalVelocity) { player.velocityY = physics.terminalVelocity; } } // Aplicar fricción/resistencia if (player.grounded) { player.velocityX *= physics.groundFriction; } else { player.velocityX *= physics.airResistance; } // Aplicar velocidades player.x += player.velocityX; player.y += player.velocityY; // Verificar colisiones con terreno this.checkTerrainCollisions(); } updatePlayerAnimation(deltaTime) { const player = this.player; // Actualizar timer de animación player.lastAnimationTime += deltaTime; if (player.lastAnimationTime >= player.animationSpeed) { player.lastAnimationTime = 0; // Determinar sprite actual basado en estado let spriteSet; if (player.isDashing) { spriteSet = player.spriteSet.dashing; } else if (player.isAttacking) { spriteSet = player.spriteSet.attacking; } else if (player.isCharging) { spriteSet = player.spriteSet.charging; } else if (!player.grounded) { spriteSet = player.spriteSet.jumping; } else if (Math.abs(player.velocityX) > 0.5) { spriteSet = player.spriteSet.running; } else { spriteSet = player.spriteSet.idle; } // Avanzar frame de animación player.animationFrame = (player.animationFrame + 1) % spriteSet.length; player.currentSprite = spriteSet[player.animationFrame]; } } updateCamera(deltaTime) { const camera = this.camera; const player = this.player; // Calcular posición objetivo de la cámara camera.targetX = player.centerX - this.canvas.width / 2; camera.targetY = player.centerY - this.canvas.height / 2; // Aplicar límites de cámara camera.targetX = Math.max(camera.bounds.left, Math.min(camera.bounds.right - this.canvas.width, camera.targetX)); camera.targetY = Math.max(camera.bounds.top, Math.min(camera.bounds.bottom - this.canvas.height, camera.targetY)); // Interpolar suavemente hacia la posición objetivo camera.x += (camera.targetX - camera.x) * camera.smoothing; camera.y += (camera.targetY - camera.y) * camera.smoothing; // Aplicar shake de cámara si está activo if (camera.shake.duration > 0) { camera.shake.duration -= deltaTime; const intensity = camera.shake.intensity * (camera.shake.duration / 1000); camera.shake.x = (Math.random() - 0.5) * intensity; camera.shake.y = (Math.random() - 0.5) * intensity; } else { camera.shake.x = 0; camera.shake.y = 0; } // Aplicar zoom suave camera.zoom += (camera.targetZoom - camera.zoom) * 0.1; } updatePhysics(deltaTime) { // Actualizar física del mundo this.systems.physics.update(deltaTime); } checkCollisions() { // Verificar colisiones jugador-entidades const playerRect = { x: this.player.x, y: this.player.y, width: this.player.width, height: this.player.height }; const entities = this.systems.entities.getActiveEntities(); entities.forEach((entity, index) => { if (this.isColliding(playerRect, entity.getBounds())) { this.handleCollision(entity, index); } }); } isColliding(rect1, rect2) { return rect1.x < rect2.x + rect2.width && rect1.x + rect1.width > rect2.x && rect1.y < rect2.y + rect2.height && rect1.y + rect1.height > rect2.y; } handleCollision(entity, index) { if (this.player.isInvulnerable) return; switch(entity.type) { case 'enemy': this.playerHit(entity); break; case 'collectible': this.collectItem(entity, index); break; case 'powerup': this.collectPowerUp(entity, index); break; case 'checkpoint': this.activateCheckpoint(entity); break; } } playerHit(enemy) { // Reducir vida this.gameState.health -= enemy.damage || 25; // Activar invulnerabilidad this.player.isInvulnerable = true; this.player.invulnerabilityTimer = 2000; // Aplicar knockback const knockbackDirection = this.player.x < enemy.x ? -1 : 1; this.player.velocityX = knockbackDirection * 10; this.player.velocityY = -8; // Efectos visuales y sonoros this.systems.particles.createHitEffect(this.player.centerX, this.player.centerY); this.systems.audio.playSound('player_hit'); this.shakeCamera(300, 10); // Reacción de la IA this.systems.ai.onPlayerHit(enemy.type); // Disparar evento this.dispatchEvent('PLAYER_HIT', { enemy: enemy.type, damage: enemy.damage, health: this.gameState.health }); // Verificar muerte if (this.gameState.health <= 0) { this.playerDeath(); } } collectItem(item, index) { // Añadir puntos this.gameState.score += item.points || 100; // Procesar tipo de item switch(item.subtype) { case 'mate': this.gameState.mateCount++; this.systems.ai.onMateCollected(); break; case 'empanada': this.gameState.health = Math.min(this.gameState.maxHealth, this.gameState.health + 25); break; case 'choripan': this.gameState.energy = Math.min(this.gameState.maxEnergy, this.gameState.energy + 50); break; } // Efectos this.systems.particles.createCollectEffect(item.x, item.y, item.color); this.systems.audio.playSound('item_collect'); // Remover item this.systems.entities.removeEntity(index); // Disparar evento this.dispatchEvent('ITEM_COLLECT', { type: item.subtype, points: item.points, position: { x: item.x, y: item.y } }); } updateComboSystem(deltaTime) { const comboSystem = this.player.comboSystem; // Verificar si hay combo activo if (comboSystem.currentCombo.length > 0) { // Verificar si se completó algún combo comboSystem.availableCombos.forEach(combo => { if (this.arraysEqual(comboSystem.currentCombo, combo.sequence)) { this.executeCombo(combo); comboSystem.currentCombo = []; comboSystem.comboTimer = 0; } }); } } executeCombo(combo) { console.log(`🔥 Combo ejecutado: ${combo.name} (${combo.power} poder)`); // Aplicar efectos del combo this.gameState.score += combo.power; this.gameState.combo++; // Efectos visuales espectaculares this.systems.particles.createComboEffect(this.player.centerX, this.player.centerY, combo.name); this.systems.audio.playSound('combo_success'); this.shakeCamera(500, 15); // Reacción de la IA this.systems.ai.onComboExecuted(combo); // Disparar evento this.dispatchEvent('COMBO_EXECUTED', { combo: combo.name, power: combo.power }); } // =================================================================== // MÉTODOS DE RENDERIZADO // =================================================================== render() { // Limpiar canvas this.clearCanvas(); // Aplicar transformaciones de cámara this.ctx.save(); this.applyCamera(); // Renderizar fondo this.renderBackground(); // Renderizar nivel this.systems.levels.render(this.ctx); // Renderizar entidades this.systems.entities.render(this.ctx); // Renderizar jugador this.renderPlayer(); // Renderizar partículas this.systems.particles.render(this.ctx); // Renderizar efectos de primer plano this.renderForegroundEffects(); // Restaurar transformaciones this.ctx.restore(); // Renderizar UI (sin transformaciones de cámara) this.renderUI(); // Renderizar debug si está habilitado if (this.engineState.debugMode) { this.renderDebugInfo(); } // Actualizar métricas de rendimiento this.performance.metrics.drawCalls++; } clearCanvas() { // Fondo degradado dinámico const gradient = this.ctx.createLinearGradient(0, 0, this.canvas.width, this.canvas.height); gradient.addColorStop(0, '#0a0a0a'); gradient.addColorStop(0.5, '#1a1a2e'); gradient.addColorStop(1, '#16213e'); this.ctx.fillStyle = gradient; this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); } applyCamera() { // Aplicar zoom this.ctx.scale(this.camera.zoom, this.camera.zoom); // Aplicar posición de cámara con shake this.ctx.translate( -this.camera.x + this.camera.shake.x, -this.camera.y + this.camera.shake.y ); } renderBackground() { // Renderizar fondo parallax del nivel actual this.systems.levels.renderBackground(this.ctx, this.camera); } renderPlayer() { const player = this.player; // Efecto de parpadeo si es invulnerable if (player.isInvulnerable && Math.floor(this.gameState.time / 100) % 2) { this.ctx.globalAlpha = 0.5; } // Configurar renderizado de texto this.ctx.font = '32px Arial'; this.ctx.textAlign = 'center'; this.ctx.textBaseline = 'bottom'; // Renderizar sprite del jugador this.ctx.fillStyle = '#ffffff'; this.ctx.fillText( player.currentSprite, player.centerX, player.y + player.height ); // Efectos especiales según estado if (player.isDashing) { this.renderDashEffect(); } if (player.isCharging) { this.renderChargeEffect(); } // Restaurar alpha this.ctx.globalAlpha = 1.0; // Renderizar barra de vida si está dañado if (this.gameState.health < this.gameState.maxHealth) { this.renderPlayerHealthBar(); } } renderDashEffect() { const player = this.player; // Crear trail de dash this.ctx.strokeStyle = '#00ffff'; this.ctx.lineWidth = 3; this.ctx.globalAlpha = 0.7; this.ctx.beginPath(); this.ctx.moveTo(player.x - 20, player.centerY); this.ctx.lineTo(player.x + player.width + 20, player.centerY); this.ctx.stroke(); this.ctx.globalAlpha = 1.0; } renderChargeEffect() { const player = this.player; const time = this.gameState.time; // Efecto de energía cargándose this.ctx.strokeStyle = '#ffff00'; this.ctx.lineWidth = 2; this.ctx.globalAlpha = 0.8; const radius = 40 + Math.sin(time * 0.01) * 10; this.ctx.beginPath(); this.ctx.arc(player.centerX, player.centerY, radius, 0, Math.PI * 2); this.ctx.stroke(); this.ctx.globalAlpha = 1.0; } renderPlayerHealthBar() { const player = this.player; const barWidth = 40; const barHeight = 6; const x = player.centerX - barWidth / 2; const y = player.y - 15; // Fondo de la barra this.ctx.fillStyle = '#ff0000'; this.ctx.fillRect(x, y, barWidth, barHeight); // Barra de vida const healthPercent = this.gameState.health / this.gameState.maxHealth; this.ctx.fillStyle = '#00ff00'; this.ctx.fillRect(x, y, barWidth * healthPercent, barHeight); // Borde this.ctx.strokeStyle = '#ffffff'; this.ctx.lineWidth = 1; this.ctx.strokeRect(x, y, barWidth, barHeight); } renderForegroundEffects() { // Efectos de primer plano como lluvia, nieve, etc. if (this.particleSystem.effects.weatherEffects.enabled) { this.renderWeatherEffects(); } // Efectos de pantalla como vignette if (this.camera.effects.vignette) { this.renderVignette(); } } renderWeatherEffects() { // Implementar efectos climáticos } renderVignette() { const gradient = this.ctx.createRadialGradient( this.canvas.width / 2, this.canvas.height / 2, 0, this.canvas.width / 2, this.canvas.height / 2, this.canvas.width / 2 ); gradient.addColorStop(0, 'rgba(0,0,0,0)'); gradient.addColorStop(1, 'rgba(0,0,0,0.5)'); this.ctx.fillStyle = gradient; this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); } renderUI() { // La UI se renderiza en el HTML, pero aquí podríamos añadir overlays } renderDebugInfo() { this.ctx.fillStyle = '#00ff00'; this.ctx.font = '12px monospace'; this.ctx.textAlign = 'left'; const debugInfo = [ `FPS: ${this.engineState.averageFPS.toFixed(1)}`, `Delta: ${this.engineState.deltaTime.toFixed(2)}ms`, `Player: (${this.player.x.toFixed(0)}, ${this.player.y.toFixed(0)})`, `Velocity: (${this.player.velocityX.toFixed(2)}, ${this.player.velocityY.toFixed(2)})`, `Camera: (${this.camera.x.toFixed(0)}, ${this.camera.y.toFixed(0)})`, `Entities: ${this.systems.entities.getEntityCount()}`, `Particles: ${this.systems.particles.getParticleCount()}` ]; debugInfo.forEach((line, index) => { this.ctx.fillText(line, 10, 20 + index * 15); }); } // =================================================================== // MÉTODOS AUXILIARES // =================================================================== updateFPS() { this.engineState.frameCount++; if (this.engineState.frameCount % 60 === 0) { this.engineState.averageFPS = 1000 / this.engineState.deltaTime; } } checkPerformance() { // Ajustar calidad automáticamente si el rendimiento es bajo if (this.performance.adaptiveQuality && this.engineState.averageFPS < 45) { this.adjustQuality('down'); } else if (this.performance.adaptiveQuality && this.engineState.averageFPS > 55) { this.adjustQuality('up'); } } adjustQuality(direction) { // Implementar ajuste automático de calidad console.log(`🔧 Ajustando calidad: ${direction}`); } processEvents() { while (this.eventSystem.queue.length > 0) { const event = this.eventSystem.queue.shift(); this.handleEvent(event); } } handleEvent(event) { const listeners = this.eventSystem.listeners.get(event.type); if (listeners) { listeners.forEach(listener => listener(event.data)); } } addEventListener(type, listener) { if (!this.eventSystem.listeners.has(type)) { this.eventSystem.listeners.set(type, []); } this.eventSystem.listeners.get(type).push(listener); } dispatchEvent(type, data) { this.eventSystem.queue.push({ type, data, timestamp: Date.now() }); } shakeCamera(duration, intensity) { this.camera.shake.duration = duration; this.camera.shake.intensity = intensity; } updateUI() { // Actualizar elementos de UI document.getElementById('gameScore').textContent = this.gameState.score.toLocaleString(); document.getElementById('playerHealth').textContent = Math.max(0, this.gameState.health); document.getElementById('mateCount').textContent = this.gameState.mateCount; document.getElementById('currentLevel').textContent = this.levelConfig.currentLevel; document.getElementById('comboCount').textContent = this.gameState.combo; } checkGameConditions() { // Verificar condiciones de victoria/derrota if (this.gameState.health <= 0 && this.gameState.lives <= 0) { this.gameOver(); } // Verificar completado de nivel if (this.systems.levels.isLevelComplete()) { this.completeLevel(); } } checkWorldBounds() { const player = this.player; // Límites horizontales if (player.x < 0) { player.x = 0; player.velocityX = 0; } // Límite inferior (muerte por caída) if (player.y > this.canvas.height + 200) { this.playerDeath('fall'); } } checkTerrainCollisions() { const player = this.player; const groundY = this.canvas.height - 80; // Altura del suelo base // Colisión con el suelo if (player.y + player.height >= groundY) { player.y = groundY - player.height; player.velocityY = 0; if (!player.grounded) { player.grounded = true; player.canDoubleJump = true; this.systems.particles.createLandingEffect(player.centerX, player.y + player.height); this.systems.ai.onPlayerLanding(); } } else { player.grounded = false; } } playerDeath(cause = 'unknown') { console.log(`💀 Jugador murió por: ${cause}`); // Reducir vidas this.gameState.lives--; // Efectos de muerte this.systems.particles.createDeathEffect(this.player.centerX, this.player.centerY); this.systems.audio.playSound('player_death'); this.shakeCamera(1000, 20); // Reacción de la IA this.systems.ai.onPlayerDeath(cause); // Resetear jugador this.respawnPlayer(); // Disparar evento this.dispatchEvent('PLAYER_DEATH', { cause, lives: this.gameState.lives }); } respawnPlayer() { // Resetear posición y estado del jugador this.player.x = 150; this.player.y = 400; this.player.velocityX = 0; this.player.velocityY = 0; this.gameState.health = this.gameState.maxHealth; this.player.isInvulnerable = true; this.player.invulnerabilityTimer = 3000; console.log('🔄 Jugador respawneado'); } gameOver() { this.engineState.isRunning = false; console.log('💀 GAME OVER'); // Mostrar pantalla de game over this.systems.ai.onGameOver(); // Guardar estadísticas finales this.systems.save.saveGameOverStats(); } completeLevel() { console.log('🏆 Nivel completado'); // Bonificación por completar nivel this.gameState.score += 5000; // Reacción de la IA this.systems.ai.onLevelComplete(); // Cargar siguiente nivel this.loadNextLevel(); } loadNextLevel() { // Implementar carga del siguiente nivel console.log('🗺️ Cargando siguiente nivel...'); } arraysEqual(a, b) { return a.length === b.length && a.every((val, i) => val === b[i]); } // =================================================================== // MÉTODOS PÚBLICOS PARA CONTROLES // =================================================================== jump() { const player = this.player; if (player.grounded) { player.velocityY = -player.jumpPower; player.grounded = false; this.systems.audio.playSound('jump'); this.systems.particles.createJumpEffect(player.centerX, player.y + player.height); this.dispatchEvent('PLAYER_JUMP', { x: player.centerX, y: player.centerY }); } else if (player.canDoubleJump) { player.velocityY = -player.doubleJumpPower; player.canDoubleJump = false; this.systems.audio.playSound('double_jump'); this.systems.particles.createDoubleJumpEffect(player.centerX, player.centerY); } } dash() { const player = this.player; if (player.canDash && !player.isDashing) { const direction = player.facing === 'right' ? 1 : -1; player.velocityX = direction * player.dashPower; player.isDashing = true; player.canDash = false; player.dashCooldown = 1000; this.systems.audio.playSound('dash'); this.systems.particles.createDashEffect(player.centerX, player.centerY, direction); // El dash dura 200ms setTimeout(() => { player.isDashing = false; }, 200); } } attack() { const player = this.player; if (!player.isAttacking && player.attackCooldown <= 0) { player.isAttacking = true; player.attackCooldown = 500; this.systems.audio.playSound('attack'); this.systems.particles.createAttackEffect(player.centerX, player.centerY, player.facing); // Verificar enemigos en rango this.checkAttackHits(); } } checkAttackHits() { const player = this.player; const attackRange = 50; const attackRect = { x: player.facing === 'right' ? player.x + player.width : player.x - attackRange, y: player.y, width: attackRange, height: player.height }; const entities = this.systems.entities.getActiveEntities(); entities.forEach((entity, index) => { if (entity.type === 'enemy' && this.isColliding(attackRect, entity.getBounds())) { this.hitEnemy(entity, index); } }); } hitEnemy(enemy, index) { // Dañar enemigo enemy.takeDamage(player.stats.strength); // Efectos this.systems.particles.createEnemyHitEffect(enemy.x, enemy.y); this.systems.audio.playSound('enemy_hit'); // Puntos this.gameState.score += 50; // Si el enemigo muere if (enemy.health <= 0) { this.systems.entities.removeEntity(index); this.gameState.score += enemy.killScore || 100; this.systems.particles.createEnemyDeathEffect(enemy.x, enemy.y); } } useMate() { if (this.gameState.mateCount > 0) { this.gameState.mateCount--; this.gameState.health = Math.min(this.gameState.maxHealth, this.gameState.health + 50); this.gameState.energy = this.gameState.maxEnergy; this.systems.audio.playSound('mate_use'); this.systems.particles.createMateEffect(this.player.centerX, this.player.centerY); this.systems.ai.onMateUsed(); console.log('🧉 Mate usado - Vida y energía restauradas'); } } togglePause() { this.engineState.isPaused = !this.engineState.isPaused; if (this.engineState.isPaused) { this.systems.audio.pauseAll(); this.systems.ai.onGamePaused(); } else { this.systems.audio.resumeAll(); this.systems.ai.onGameResumed(); } console.log(`⏸️ Juego ${this.engineState.isPaused ? 'pausado' : 'reanudado'}`); } toggleDebug() { this.engineState.debugMode = !this.engineState.debugMode; console.log(`🐛 Modo debug: ${this.engineState.debugMode ? 'ON' : 'OFF'}`); } // =================================================================== // GETTERS PÚBLICOS // =================================================================== getPlayer() { return this.player; } getGameState() { return this.gameState; } getCamera() { return this.camera; } getCanvas() { return this.canvas; } getContext() { return this.ctx; } getSystems() { return this.systems; } getPerformanceMetrics() { return this.performance.metrics; } } // =================================================================== // EXPORTAR PARA USO GLOBAL // =================================================================== window.RetroLegendsUltimateEngine = RetroLegendsUltimateEngine; console.log('🚀 Core Engine Ultra cargado correctamente');