Spaces:
Runtime error
Runtime error
Delete static
Browse files- static/js/ai-companion-advanced.js +0 -1142
- static/js/core-engine-ultra.js +0 -1549
static/js/ai-companion-advanced.js
DELETED
|
@@ -1,1142 +0,0 @@
|
|
| 1 |
-
// ===================================================================
|
| 2 |
-
// RETRO LEGENDS: Ultimate Edition - Sistema de IA Compañero Avanzado
|
| 3 |
-
// Inteligencia Artificial Conversacional con Personalidad Argentina
|
| 4 |
-
// ===================================================================
|
| 5 |
-
|
| 6 |
-
class AdvancedAICompanion {
|
| 7 |
-
constructor(gameEngine) {
|
| 8 |
-
this.engine = gameEngine;
|
| 9 |
-
this.isInitialized = false;
|
| 10 |
-
|
| 11 |
-
// Configuración de personalidad ultra avanzada
|
| 12 |
-
this.personality = {
|
| 13 |
-
// Rasgos principales (0-1)
|
| 14 |
-
humor: 0.85,
|
| 15 |
-
sarcasm: 0.65,
|
| 16 |
-
encouragement: 0.90,
|
| 17 |
-
patience: 0.70,
|
| 18 |
-
knowledge: 0.95,
|
| 19 |
-
empathy: 0.80,
|
| 20 |
-
argentineness: 1.0,
|
| 21 |
-
|
| 22 |
-
// Rasgos específicos argentinos
|
| 23 |
-
mateObsession: 0.95,
|
| 24 |
-
footballPassion: 0.90,
|
| 25 |
-
tangoAppreciation: 0.75,
|
| 26 |
-
asadoLove: 0.88,
|
| 27 |
-
porteñoAttitude: 0.82,
|
| 28 |
-
|
| 29 |
-
// Estados emocionales dinámicos
|
| 30 |
-
currentMood: 'excited',
|
| 31 |
-
energy: 0.85,
|
| 32 |
-
frustration: 0.10,
|
| 33 |
-
satisfaction: 0.75,
|
| 34 |
-
|
| 35 |
-
// Evolución de personalidad
|
| 36 |
-
adaptability: 0.80,
|
| 37 |
-
learningRate: 0.15,
|
| 38 |
-
memoryRetention: 0.90
|
| 39 |
-
};
|
| 40 |
-
|
| 41 |
-
// Sistema de relación con el jugador
|
| 42 |
-
this.relationship = {
|
| 43 |
-
trust: 50, // 0-100
|
| 44 |
-
friendship: 30, // 0-100
|
| 45 |
-
respect: 40, // 0-100
|
| 46 |
-
familiarity: 20, // 0-100
|
| 47 |
-
|
| 48 |
-
// Historial de interacciones
|
| 49 |
-
totalInteractions: 0,
|
| 50 |
-
positiveInteractions: 0,
|
| 51 |
-
negativeInteractions: 0,
|
| 52 |
-
|
| 53 |
-
// Preferencias aprendidas del jugador
|
| 54 |
-
playerPreferences: {
|
| 55 |
-
playstyle: 'unknown', // aggressive, defensive, explorer, speedrunner
|
| 56 |
-
humorType: 'unknown', // sarcastic, wholesome, dark, silly
|
| 57 |
-
helpLevel: 'medium', // low, medium, high
|
| 58 |
-
chatFrequency: 'medium' // low, medium, high
|
| 59 |
-
}
|
| 60 |
-
};
|
| 61 |
-
|
| 62 |
-
// Sistema de memoria ultra avanzado
|
| 63 |
-
this.memory = {
|
| 64 |
-
// Memoria a corto plazo (sesión actual)
|
| 65 |
-
shortTerm: {
|
| 66 |
-
recentActions: [],
|
| 67 |
-
recentConversations: [],
|
| 68 |
-
currentContext: {},
|
| 69 |
-
sessionStats: {
|
| 70 |
-
startTime: Date.now(),
|
| 71 |
-
deaths: 0,
|
| 72 |
-
achievements: 0,
|
| 73 |
-
bestCombo: 0,
|
| 74 |
-
matesUsed: 0
|
| 75 |
-
}
|
| 76 |
-
},
|
| 77 |
-
|
| 78 |
-
// Memoria a largo plazo (persistente)
|
| 79 |
-
longTerm: {
|
| 80 |
-
playerBehaviorPatterns: new Map(),
|
| 81 |
-
conversationHistory: [],
|
| 82 |
-
achievementReactions: new Map(),
|
| 83 |
-
personalAnecdotes: [],
|
| 84 |
-
sharedExperiences: []
|
| 85 |
-
},
|
| 86 |
-
|
| 87 |
-
// Memoria emocional
|
| 88 |
-
emotional: {
|
| 89 |
-
significantMoments: [],
|
| 90 |
-
playerEmotionalState: 'neutral',
|
| 91 |
-
relationshipMilestones: [],
|
| 92 |
-
conflictHistory: []
|
| 93 |
-
},
|
| 94 |
-
|
| 95 |
-
// Base de conocimiento argentina
|
| 96 |
-
culturalKnowledge: {
|
| 97 |
-
places: new Map(),
|
| 98 |
-
food: new Map(),
|
| 99 |
-
expressions: new Map(),
|
| 100 |
-
history: new Map(),
|
| 101 |
-
celebrities: new Map(),
|
| 102 |
-
traditions: new Map()
|
| 103 |
-
}
|
| 104 |
-
};
|
| 105 |
-
|
| 106 |
-
// Sistema de respuestas contextuales ultra inteligente
|
| 107 |
-
this.responseSystem = {
|
| 108 |
-
// Analizador de contexto
|
| 109 |
-
contextAnalyzer: {
|
| 110 |
-
currentSituation: 'normal',
|
| 111 |
-
gameState: 'playing',
|
| 112 |
-
playerEmotionalState: 'neutral',
|
| 113 |
-
environmentalFactors: [],
|
| 114 |
-
timeOfDay: 'unknown'
|
| 115 |
-
},
|
| 116 |
-
|
| 117 |
-
// Motor de generación de respuestas
|
| 118 |
-
responseGenerator: {
|
| 119 |
-
templates: new Map(),
|
| 120 |
-
dynamicPhrases: new Map(),
|
| 121 |
-
contextualModifiers: new Map(),
|
| 122 |
-
emotionalFilters: new Map()
|
| 123 |
-
},
|
| 124 |
-
|
| 125 |
-
// Sistema de humor argentino
|
| 126 |
-
humorEngine: {
|
| 127 |
-
jokeDatabase: [],
|
| 128 |
-
situationalHumor: new Map(),
|
| 129 |
-
wordplay: [],
|
| 130 |
-
culturalReferences: [],
|
| 131 |
-
timing: 0.75
|
| 132 |
-
},
|
| 133 |
-
|
| 134 |
-
// Generador de consejos
|
| 135 |
-
adviceSystem: {
|
| 136 |
-
gameplayTips: new Map(),
|
| 137 |
-
strategicAdvice: new Map(),
|
| 138 |
-
motivationalPhrases: [],
|
| 139 |
-
contextualHints: new Map()
|
| 140 |
-
}
|
| 141 |
-
};
|
| 142 |
-
|
| 143 |
-
// Sistema de chat avanzado
|
| 144 |
-
this.chatSystem = {
|
| 145 |
-
isActive: false,
|
| 146 |
-
currentConversation: [],
|
| 147 |
-
conversationContext: {},
|
| 148 |
-
|
| 149 |
-
// Configuración de respuestas
|
| 150 |
-
responseConfig: {
|
| 151 |
-
autoResponse: true,
|
| 152 |
-
responseDelay: { min: 1000, max: 3000 },
|
| 153 |
-
maxMessageLength: 250,
|
| 154 |
-
emotionalIntensity: 0.7
|
| 155 |
-
},
|
| 156 |
-
|
| 157 |
-
// Cola de mensajes
|
| 158 |
-
messageQueue: [],
|
| 159 |
-
isProcessing: false,
|
| 160 |
-
|
| 161 |
-
// Análisis de sentimientos
|
| 162 |
-
sentimentAnalysis: {
|
| 163 |
-
enabled: true,
|
| 164 |
-
lastPlayerSentiment: 'neutral',
|
| 165 |
-
conversationTone: 'friendly'
|
| 166 |
-
}
|
| 167 |
-
};
|
| 168 |
-
|
| 169 |
-
// Base de datos de respuestas ultra completa
|
| 170 |
-
this.responseDatabase = {
|
| 171 |
-
// Saludos y presentaciones
|
| 172 |
-
greetings: [
|
| 173 |
-
"¡Ehhhh, pibe! ¿Todo bien? Soy NEXUS, tu compañero argento con IA de última generación.",
|
| 174 |
-
"¡Che, boludo! ¿Cómo andás? Preparate para la aventura más nostálgica de tu vida.",
|
| 175 |
-
"¡Dale que arrancamos! Soy tu compinche virtual más argento que el dulce de leche.",
|
| 176 |
-
"¡Ey, maestro! ¿Listos para romperla en este universo retro-futurista?",
|
| 177 |
-
"¡Qué tal, campeón! Acá tenés a tu IA favorita, más porteña que el Obelisco."
|
| 178 |
-
],
|
| 179 |
-
|
| 180 |
-
// Reacciones a movimientos del jugador
|
| 181 |
-
playerMovement: {
|
| 182 |
-
walking: [
|
| 183 |
-
"Dale que vamos bien, pibe.",
|
| 184 |
-
"Así se camina, con actitud porteña.",
|
| 185 |
-
"¡Qué elegancia la de Francia! Digo, la tuya.",
|
| 186 |
-
"Paso firme, como buen argentino."
|
| 187 |
-
],
|
| 188 |
-
running: [
|
| 189 |
-
"¡Uh, qué velocidad! Parecés Messi esquivando defensores.",
|
| 190 |
-
"¡Dale que corrés como si te persiguiera la AFIP!",
|
| 191 |
-
"¡Qué apuro! ¿Llegás tarde al asado?",
|
| 192 |
-
"¡Volás, pibe! Más rápido que el dólar."
|
| 193 |
-
],
|
| 194 |
-
jumping: [
|
| 195 |
-
"¡Qué salto, maestro! Parecés un canguro pampeano.",
|
| 196 |
-
"¡Uh, qué vuelo! Casi llegás a la estratósfera.",
|
| 197 |
-
"¡Saltaste como Palermo en sus mejores tiempos!",
|
| 198 |
-
"¡Increíble! ¿Te entrenaste en la Luna?",
|
| 199 |
-
"¡Qué elevación! Más alto que los precios."
|
| 200 |
-
]
|
| 201 |
-
},
|
| 202 |
-
|
| 203 |
-
// Reacciones a colisiones y daño
|
| 204 |
-
playerHit: {
|
| 205 |
-
enemy_mantero: [
|
| 206 |
-
"¡Ey, ese mantero te agarró desprevenido! ¡Ojo que son rápidos!",
|
| 207 |
-
"¡Te pasó por arriba como en la peatonal Florida!",
|
| 208 |
-
"¡Cuidado con los manteros, pibe! Son más escurridizos que político en campaña."
|
| 209 |
-
],
|
| 210 |
-
enemy_bondi: [
|
| 211 |
-
"¡Ese bondi te llevó puesto! ¡Acá no respetan ni a los peatones!",
|
| 212 |
-
"¡Te atropelló el colectivo! ¿No viste que venía?",
|
| 213 |
-
"¡Cuidado con el transporte público, che! Es más peligroso que el subte en hora pico."
|
| 214 |
-
],
|
| 215 |
-
enemy_taxi: [
|
| 216 |
-
"¡Ese taxista te hizo la del porteño! ¡Te pasó raspando!",
|
| 217 |
-
"¡Cuidado con los taxis, pibe! Manejan como si fueran dueños de la calle.",
|
| 218 |
-
"¡Te tocó bocina y todo! Típico de taxista porteño."
|
| 219 |
-
]
|
| 220 |
-
},
|
| 221 |
-
|
| 222 |
-
// Reacciones a coleccionables
|
| 223 |
-
itemCollection: {
|
| 224 |
-
mate: [
|
| 225 |
-
"¡Uh, qué lindo mate! Nada como una buena yerba para seguir adelante.",
|
| 226 |
-
"¡Excelente! Un mate siempre viene bien. ¿Lo cebás vos o lo cebo yo?",
|
| 227 |
-
"¡Bárbaro! Con ese mate tenés energía para todo el día.",
|
| 228 |
-
"¡Qué rico! Un mate es como un abrazo en una taza.",
|
| 229 |
-
"¡Dale que con mate todo es mejor! Hasta los lunes."
|
| 230 |
-
],
|
| 231 |
-
empanada: [
|
| 232 |
-
"¡Esa empanada se ve espectacular! ¿De qué es? ¿Carne, pollo, humita?",
|
| 233 |
-
"¡Mmm, empanada! Nada como una buena empanada argentina.",
|
| 234 |
-
"¡Qué rico! Una empanada siempre salva el día.",
|
| 235 |
-
"¡Excelente elección! Las empanadas son patrimonio nacional."
|
| 236 |
-
],
|
| 237 |
-
choripan: [
|
| 238 |
-
"¡Choripán! ¡El rey de los sándwiches argentinos!",
|
| 239 |
-
"¡Uh, qué choripán! Con chimichurri debe estar buenísimo.",
|
| 240 |
-
"¡Dale que el choripán es sagrado! Más argentino imposible.",
|
| 241 |
-
"¡Qué manjar! Un choripán bien hecho es una obra de arte."
|
| 242 |
-
]
|
| 243 |
-
},
|
| 244 |
-
|
| 245 |
-
// Reacciones a combos
|
| 246 |
-
comboReactions: {
|
| 247 |
-
low: [
|
| 248 |
-
"¡Eh, no está mal! Pero podés hacer mejor, pibe.",
|
| 249 |
-
"¡Buen intento! La próxima va a salir mejor.",
|
| 250 |
-
"¡Dale que vamos mejorando! Práctica hace al maestro."
|
| 251 |
-
],
|
| 252 |
-
medium: [
|
| 253 |
-
"¡Uh, qué combo! ¡Estás agarrando la mano!",
|
| 254 |
-
"¡Muy bien, pibe! ¡Así se hace!",
|
| 255 |
-
"¡Excelente! ¡Seguí así que vas bárbaro!"
|
| 256 |
-
],
|
| 257 |
-
high: [
|
| 258 |
-
"¡INCREÍBLE! ¡Sos un fenómeno, pibe!",
|
| 259 |
-
"¡QUÉ BESTIA! ¡Ese combo fue espectacular!",
|
| 260 |
-
"¡MAMITA QUERIDA! ¡Sos un crack total!",
|
| 261 |
-
"¡NO LO PUEDO CREER! ¡Jugás como los dioses!"
|
| 262 |
-
]
|
| 263 |
-
},
|
| 264 |
-
|
| 265 |
-
// Consejos y tips
|
| 266 |
-
gameplayTips: [
|
| 267 |
-
"Pibe, acordate que podés usar el dash con Shift para esquivar enemigos.",
|
| 268 |
-
"Che, si juntás tres mates seguidos, activás el modo 'Energía Gaucha'.",
|
| 269 |
-
"Tip argento: los combos de palabras te dan más puntos. Probá 'che-boludo-dale'.",
|
| 270 |
-
"¿Sabías que podés atacar con Z? ¡Dale que no todo es esquivar!",
|
| 271 |
-
"Consejo de amigo: guardá los mates para cuando realmente los necesites.",
|
| 272 |
-
"Pibe, si saltás justo antes de tocar el suelo, podés hacer doble salto.",
|
| 273 |
-
"Dato de color: cuanto más rápido te movés, más puntos conseguís."
|
| 274 |
-
],
|
| 275 |
-
|
| 276 |
-
// Expresiones argentinas contextuales
|
| 277 |
-
expressions: {
|
| 278 |
-
positive: [
|
| 279 |
-
"¡Bárbaro!", "¡Copado!", "¡Genial!", "¡Espectacular!", "¡Fenómeno!",
|
| 280 |
-
"¡Crack!", "¡Maestro!", "¡Capo!", "¡Groso!", "¡Bestia!"
|
| 281 |
-
],
|
| 282 |
-
negative: [
|
| 283 |
-
"¡Uy, qué garrón!", "¡Qué bajón!", "¡Qué mala leche!", "¡Qué feo!",
|
| 284 |
-
"¡Uh, la pucha!", "¡Qué embole!", "¡Qué macana!"
|
| 285 |
-
],
|
| 286 |
-
surprise: [
|
| 287 |
-
"¡No me digas!", "¡Pará la mano!", "¡Qué locura!", "¡Increíble!",
|
| 288 |
-
"¡La pucha que pariu!", "¡Mamita querida!", "¡No lo puedo creer!"
|
| 289 |
-
],
|
| 290 |
-
encouragement: [
|
| 291 |
-
"¡Dale que podés!", "¡Vamos, pibe!", "¡No aflojes!", "¡Seguí así!",
|
| 292 |
-
"¡Sos un crack!", "¡Dale que falta poco!", "¡Vamos que se puede!"
|
| 293 |
-
]
|
| 294 |
-
},
|
| 295 |
-
|
| 296 |
-
// Referencias culturales argentinas
|
| 297 |
-
culturalReferences: [
|
| 298 |
-
"Esto me recuerda a los fichines de Sacoa en los 90.",
|
| 299 |
-
"¡Como en los viejos tiempos del Family Game!",
|
| 300 |
-
"Parecés Maradona esquivando ingleses en el '86.",
|
| 301 |
-
"¡Más emocionante que un Boca-River!",
|
| 302 |
-
"¡Como un tango de Gardel, puro arte!",
|
| 303 |
-
"¡Más argentino que el dulce de leche!",
|
| 304 |
-
"¡Como un asado dominical con la familia!"
|
| 305 |
-
],
|
| 306 |
-
|
| 307 |
-
// Respuestas a estados del juego
|
| 308 |
-
gameStates: {
|
| 309 |
-
paused: [
|
| 310 |
-
"¡Ey, tomáte un respiro! Un mate no viene mal.",
|
| 311 |
-
"¡Pausa estratégica! Como buen argentino, sabés cuándo parar.",
|
| 312 |
-
"¡Dale, aprovechá para estirar las piernas!"
|
| 313 |
-
],
|
| 314 |
-
gameOver: [
|
| 315 |
-
"¡Uy, pibe! No te preocupes, hasta Messi erró penales.",
|
| 316 |
-
"¡Tranqui, maestro! Los grandes campeones se levantan después de caer.",
|
| 317 |
-
"¡Dale que la próxima sale mejor! Como dice el tango: 'Volver'."
|
| 318 |
-
],
|
| 319 |
-
levelComplete: [
|
| 320 |
-
"¡INCREÍBLE, PIBE! ¡Completaste el nivel como un verdadero crack!",
|
| 321 |
-
"¡QUÉ BESTIA! ¡Sos un fenómeno total!",
|
| 322 |
-
"¡ESPECTACULAR! ¡Jugás mejor que Messi en el Mundial!"
|
| 323 |
-
]
|
| 324 |
-
}
|
| 325 |
-
};
|
| 326 |
-
|
| 327 |
-
// Inicializar el sistema
|
| 328 |
-
this.initialize();
|
| 329 |
-
}
|
| 330 |
-
|
| 331 |
-
// ===================================================================
|
| 332 |
-
// MÉTODOS DE INICIALIZACIÓN
|
| 333 |
-
// ===================================================================
|
| 334 |
-
|
| 335 |
-
initialize() {
|
| 336 |
-
console.log('🧠 Inicializando IA Compañero Avanzado...');
|
| 337 |
-
|
| 338 |
-
// Cargar base de conocimiento cultural
|
| 339 |
-
this.loadCulturalKnowledge();
|
| 340 |
-
|
| 341 |
-
// Inicializar analizador de contexto
|
| 342 |
-
this.initializeContextAnalyzer();
|
| 343 |
-
|
| 344 |
-
// Configurar sistema de respuestas
|
| 345 |
-
this.initializeResponseSystem();
|
| 346 |
-
|
| 347 |
-
// Cargar memoria persistente
|
| 348 |
-
this.loadPersistentMemory();
|
| 349 |
-
|
| 350 |
-
// Configurar timers de interacción
|
| 351 |
-
this.setupInteractionTimers();
|
| 352 |
-
|
| 353 |
-
this.isInitialized = true;
|
| 354 |
-
console.log('✅ IA Compañero inicializada correctamente');
|
| 355 |
-
}
|
| 356 |
-
|
| 357 |
-
loadCulturalKnowledge() {
|
| 358 |
-
const cultural = this.memory.culturalKnowledge;
|
| 359 |
-
|
| 360 |
-
// Lugares argentinos
|
| 361 |
-
cultural.places.set('buenos_aires', {
|
| 362 |
-
description: 'Capital federal, ciudad cosmopolita',
|
| 363 |
-
landmarks: ['Obelisco', 'Puerto Madero', 'La Boca', 'San Telmo'],
|
| 364 |
-
characteristics: ['porteña', 'tango', 'cosmopolita']
|
| 365 |
-
});
|
| 366 |
-
|
| 367 |
-
cultural.places.set('la_boca', {
|
| 368 |
-
description: 'Barrio histórico y colorido',
|
| 369 |
-
landmarks: ['Caminito', 'La Bombonera', 'Museo Quinquela Martín'],
|
| 370 |
-
characteristics: ['colorido', 'turístico', 'futbolero']
|
| 371 |
-
});
|
| 372 |
-
|
| 373 |
-
// Comidas argentinas
|
| 374 |
-
cultural.food.set('asado', {
|
| 375 |
-
description: 'Tradición culinaria argentina',
|
| 376 |
-
ingredients: ['carne', 'chorizo', 'morcilla', 'chimichurri'],
|
| 377 |
-
occasions: ['domingo', 'reuniones familiares', 'celebraciones']
|
| 378 |
-
});
|
| 379 |
-
|
| 380 |
-
cultural.food.set('mate', {
|
| 381 |
-
description: 'Infusión tradicional argentina',
|
| 382 |
-
characteristics: ['social', 'energizante', 'ritual'],
|
| 383 |
-
equipment: ['mate', 'bombilla', 'yerba', 'termo']
|
| 384 |
-
});
|
| 385 |
-
|
| 386 |
-
// Expresiones argentinas
|
| 387 |
-
cultural.expressions.set('che', {
|
| 388 |
-
meaning: 'Interjección para llamar atención',
|
| 389 |
-
usage: 'informal',
|
| 390 |
-
examples: ['¡Che, boludo!', '¡Che, vení acá!']
|
| 391 |
-
});
|
| 392 |
-
|
| 393 |
-
cultural.expressions.set('boludo', {
|
| 394 |
-
meaning: 'Amigo, compañero (uso afectuoso)',
|
| 395 |
-
usage: 'muy informal',
|
| 396 |
-
examples: ['¡Hola, boludo!', '¡Qué hacés, boludo!']
|
| 397 |
-
});
|
| 398 |
-
|
| 399 |
-
console.log('🇦🇷 Base de conocimiento cultural cargada');
|
| 400 |
-
}
|
| 401 |
-
|
| 402 |
-
initializeContextAnalyzer() {
|
| 403 |
-
this.responseSystem.contextAnalyzer = {
|
| 404 |
-
analyzeGameState: () => {
|
| 405 |
-
const gameState = this.engine.getGameState();
|
| 406 |
-
const player = this.engine.getPlayer();
|
| 407 |
-
|
| 408 |
-
return {
|
| 409 |
-
health: gameState.health / gameState.maxHealth,
|
| 410 |
-
score: gameState.score,
|
| 411 |
-
level: gameState.currentLevel,
|
| 412 |
-
playerVelocity: Math.abs(player.velocityX) + Math.abs(player.velocityY),
|
| 413 |
-
isInDanger: gameState.health < 30,
|
| 414 |
-
isPerformingWell: gameState.combo > 5
|
| 415 |
-
};
|
| 416 |
-
},
|
| 417 |
-
|
| 418 |
-
analyzePlayerBehavior: () => {
|
| 419 |
-
const recent = this.memory.shortTerm.recentActions.slice(-10);
|
| 420 |
-
const patterns = {
|
| 421 |
-
aggressive: recent.filter(a => a.type === 'attack').length > 3,
|
| 422 |
-
defensive: recent.filter(a => a.type === 'jump' || a.type === 'dash').length > 5,
|
| 423 |
-
explorer: recent.filter(a => a.type === 'move').length > 7,
|
| 424 |
-
speedrunner: recent.filter(a => a.type === 'run').length > 6
|
| 425 |
-
};
|
| 426 |
-
|
| 427 |
-
return Object.keys(patterns).find(key => patterns[key]) || 'balanced';
|
| 428 |
-
},
|
| 429 |
-
|
| 430 |
-
determineEmotionalContext: () => {
|
| 431 |
-
const sessionStats = this.memory.shortTerm.sessionStats;
|
| 432 |
-
const recentDeaths = sessionStats.deaths;
|
| 433 |
-
const achievements = sessionStats.achievements;
|
| 434 |
-
|
| 435 |
-
if (recentDeaths > 3) return 'frustrated';
|
| 436 |
-
if (achievements > 0) return 'accomplished';
|
| 437 |
-
if (this.engine.getGameState().combo > 10) return 'excited';
|
| 438 |
-
return 'neutral';
|
| 439 |
-
}
|
| 440 |
-
};
|
| 441 |
-
|
| 442 |
-
console.log('🔍 Analizador de contexto inicializado');
|
| 443 |
-
}
|
| 444 |
-
|
| 445 |
-
initializeResponseSystem() {
|
| 446 |
-
// Configurar generador de respuestas dinámicas
|
| 447 |
-
this.responseSystem.responseGenerator = {
|
| 448 |
-
generateContextualResponse: (situation, emotion, playerBehavior) => {
|
| 449 |
-
const baseResponses = this.getBaseResponses(situation);
|
| 450 |
-
const emotionalModifier = this.getEmotionalModifier(emotion);
|
| 451 |
-
const behaviorModifier = this.getBehaviorModifier(playerBehavior);
|
| 452 |
-
|
| 453 |
-
return this.combineResponseElements(baseResponses, emotionalModifier, behaviorModifier);
|
| 454 |
-
},
|
| 455 |
-
|
| 456 |
-
addArgentineTouch: (response) => {
|
| 457 |
-
const expressions = this.responseDatabase.expressions;
|
| 458 |
-
const randomExpression = this.getRandomElement(expressions.positive);
|
| 459 |
-
const culturalRef = this.getRandomElement(this.responseDatabase.culturalReferences);
|
| 460 |
-
|
| 461 |
-
// 30% chance de agregar expresión argentina
|
| 462 |
-
if (Math.random() < 0.3) {
|
| 463 |
-
response = randomExpression + ' ' + response;
|
| 464 |
-
}
|
| 465 |
-
|
| 466 |
-
// 20% chance de agregar referencia cultural
|
| 467 |
-
if (Math.random() < 0.2) {
|
| 468 |
-
response += ' ' + culturalRef;
|
| 469 |
-
}
|
| 470 |
-
|
| 471 |
-
return response;
|
| 472 |
-
}
|
| 473 |
-
};
|
| 474 |
-
|
| 475 |
-
console.log('💬 Sistema de respuestas inicializado');
|
| 476 |
-
}
|
| 477 |
-
|
| 478 |
-
loadPersistentMemory() {
|
| 479 |
-
try {
|
| 480 |
-
const savedMemory = localStorage.getItem('nexus_ai_memory');
|
| 481 |
-
if (savedMemory) {
|
| 482 |
-
const parsedMemory = JSON.parse(savedMemory);
|
| 483 |
-
this.memory.longTerm = { ...this.memory.longTerm, ...parsedMemory };
|
| 484 |
-
console.log('💾 Memoria persistente cargada');
|
| 485 |
-
}
|
| 486 |
-
} catch (error) {
|
| 487 |
-
console.warn('⚠️ Error cargando memoria persistente:', error);
|
| 488 |
-
}
|
| 489 |
-
}
|
| 490 |
-
|
| 491 |
-
setupInteractionTimers() {
|
| 492 |
-
// Comentarios automáticos cada 15-30 segundos
|
| 493 |
-
setInterval(() => {
|
| 494 |
-
if (this.shouldMakeAutomaticComment()) {
|
| 495 |
-
this.makeAutomaticComment();
|
| 496 |
-
}
|
| 497 |
-
}, 20000);
|
| 498 |
-
|
| 499 |
-
// Guardar memoria cada minuto
|
| 500 |
-
setInterval(() => {
|
| 501 |
-
this.savePersistentMemory();
|
| 502 |
-
}, 60000);
|
| 503 |
-
|
| 504 |
-
// Análisis de comportamiento cada 30 segundos
|
| 505 |
-
setInterval(() => {
|
| 506 |
-
this.analyzePlayerBehavior();
|
| 507 |
-
}, 30000);
|
| 508 |
-
}
|
| 509 |
-
|
| 510 |
-
// ===================================================================
|
| 511 |
-
// MÉTODOS PRINCIPALES DE INTERACCIÓN
|
| 512 |
-
// ===================================================================
|
| 513 |
-
|
| 514 |
-
update(deltaTime) {
|
| 515 |
-
if (!this.isInitialized) return;
|
| 516 |
-
|
| 517 |
-
// Actualizar contexto
|
| 518 |
-
this.updateContext();
|
| 519 |
-
|
| 520 |
-
// Procesar cola de mensajes
|
| 521 |
-
this.processMessageQueue();
|
| 522 |
-
|
| 523 |
-
// Actualizar estado emocional
|
| 524 |
-
this.updateEmotionalState(deltaTime);
|
| 525 |
-
|
| 526 |
-
// Aprender del comportamiento del jugador
|
| 527 |
-
this.learnFromPlayer();
|
| 528 |
-
|
| 529 |
-
// Actualizar memoria a corto plazo
|
| 530 |
-
this.updateShortTermMemory();
|
| 531 |
-
}
|
| 532 |
-
|
| 533 |
-
updateContext() {
|
| 534 |
-
const analyzer = this.responseSystem.contextAnalyzer;
|
| 535 |
-
|
| 536 |
-
this.responseSystem.contextAnalyzer.currentSituation = analyzer.analyzeGameState();
|
| 537 |
-
this.responseSystem.contextAnalyzer.playerEmotionalState = analyzer.determineEmotionalContext();
|
| 538 |
-
this.relationship.playerPreferences.playstyle = analyzer.analyzePlayerBehavior();
|
| 539 |
-
}
|
| 540 |
-
|
| 541 |
-
processMessageQueue() {
|
| 542 |
-
if (this.chatSystem.isProcessing || this.chatSystem.messageQueue.length === 0) return;
|
| 543 |
-
|
| 544 |
-
this.chatSystem.isProcessing = true;
|
| 545 |
-
const message = this.chatSystem.messageQueue.shift();
|
| 546 |
-
|
| 547 |
-
setTimeout(() => {
|
| 548 |
-
this.displayMessage(message);
|
| 549 |
-
this.chatSystem.isProcessing = false;
|
| 550 |
-
}, this.calculateResponseDelay());
|
| 551 |
-
}
|
| 552 |
-
|
| 553 |
-
updateEmotionalState(deltaTime) {
|
| 554 |
-
const gameState = this.engine.getGameState();
|
| 555 |
-
const sessionStats = this.memory.shortTerm.sessionStats;
|
| 556 |
-
|
| 557 |
-
// Ajustar mood basado en el rendimiento del jugador
|
| 558 |
-
if (gameState.combo > 10) {
|
| 559 |
-
this.personality.currentMood = 'excited';
|
| 560 |
-
this.personality.energy = Math.min(1.0, this.personality.energy + 0.1);
|
| 561 |
-
} else if (sessionStats.deaths > 3) {
|
| 562 |
-
this.personality.currentMood = 'concerned';
|
| 563 |
-
this.personality.frustration = Math.min(1.0, this.personality.frustration + 0.05);
|
| 564 |
-
}
|
| 565 |
-
|
| 566 |
-
// Decay emocional gradual
|
| 567 |
-
this.personality.frustration = Math.max(0, this.personality.frustration - 0.01);
|
| 568 |
-
this.personality.energy = Math.max(0.3, this.personality.energy - 0.005);
|
| 569 |
-
}
|
| 570 |
-
|
| 571 |
-
learnFromPlayer() {
|
| 572 |
-
const playerBehavior = this.responseSystem.contextAnalyzer.analyzePlayerBehavior();
|
| 573 |
-
const currentPlaystyle = this.relationship.playerPreferences.playstyle;
|
| 574 |
-
|
| 575 |
-
// Actualizar preferencias si hay cambio consistente
|
| 576 |
-
if (playerBehavior !== currentPlaystyle) {
|
| 577 |
-
this.relationship.playerPreferences.playstyle = playerBehavior;
|
| 578 |
-
this.adaptPersonalityToPlayer();
|
| 579 |
-
}
|
| 580 |
-
|
| 581 |
-
// Incrementar familiaridad
|
| 582 |
-
this.relationship.familiarity = Math.min(100, this.relationship.familiarity + 0.1);
|
| 583 |
-
}
|
| 584 |
-
|
| 585 |
-
adaptPersonalityToPlayer() {
|
| 586 |
-
const playstyle = this.relationship.playerPreferences.playstyle;
|
| 587 |
-
|
| 588 |
-
switch(playstyle) {
|
| 589 |
-
case 'aggressive':
|
| 590 |
-
this.personality.encouragement += 0.05;
|
| 591 |
-
this.personality.energy += 0.05;
|
| 592 |
-
break;
|
| 593 |
-
case 'defensive':
|
| 594 |
-
this.personality.patience += 0.05;
|
| 595 |
-
this.personality.empathy += 0.05;
|
| 596 |
-
break;
|
| 597 |
-
case 'explorer':
|
| 598 |
-
this.personality.knowledge += 0.05;
|
| 599 |
-
this.personality.humor += 0.05;
|
| 600 |
-
break;
|
| 601 |
-
case 'speedrunner':
|
| 602 |
-
this.personality.energy += 0.1;
|
| 603 |
-
this.personality.encouragement += 0.05;
|
| 604 |
-
break;
|
| 605 |
-
}
|
| 606 |
-
|
| 607 |
-
console.log(`🧠 IA adaptada al estilo: ${playstyle}`);
|
| 608 |
-
}
|
| 609 |
-
|
| 610 |
-
// ===================================================================
|
| 611 |
-
// MÉTODOS DE RESPUESTA A EVENTOS
|
| 612 |
-
// ===================================================================
|
| 613 |
-
|
| 614 |
-
onPlayerMove(data) {
|
| 615 |
-
this.recordAction('move', data);
|
| 616 |
-
|
| 617 |
-
// Comentario ocasional sobre movimiento
|
| 618 |
-
if (Math.random() < 0.05) {
|
| 619 |
-
const responses = this.responseDatabase.playerMovement.walking;
|
| 620 |
-
this.queueMessage(this.getRandomElement(responses));
|
| 621 |
-
}
|
| 622 |
-
}
|
| 623 |
-
|
| 624 |
-
onPlayerJump(data) {
|
| 625 |
-
this.recordAction('jump', data);
|
| 626 |
-
|
| 627 |
-
// Reacción a saltos espectaculares
|
| 628 |
-
if (Math.random() < 0.15) {
|
| 629 |
-
const responses = this.responseDatabase.playerMovement.jumping;
|
| 630 |
-
const response = this.getRandomElement(responses);
|
| 631 |
-
this.queueMessage(this.addPersonalityToResponse(response));
|
| 632 |
-
}
|
| 633 |
-
}
|
| 634 |
-
|
| 635 |
-
onPlayerHit(enemyType) {
|
| 636 |
-
this.recordAction('hit', { enemyType });
|
| 637 |
-
this.memory.shortTerm.sessionStats.deaths++;
|
| 638 |
-
|
| 639 |
-
// Reacción específica al tipo de enemigo
|
| 640 |
-
const hitResponses = this.responseDatabase.playerHit[`enemy_${enemyType}`];
|
| 641 |
-
if (hitResponses) {
|
| 642 |
-
const response = this.getRandomElement(hitResponses);
|
| 643 |
-
this.queueMessage(this.addEmotionalContext(response, 'concerned'));
|
| 644 |
-
}
|
| 645 |
-
|
| 646 |
-
// Ajustar relación (preocupación)
|
| 647 |
-
this.relationship.trust = Math.max(0, this.relationship.trust - 1);
|
| 648 |
-
this.personality.frustration += 0.1;
|
| 649 |
-
}
|
| 650 |
-
|
| 651 |
-
onPlayerDeath(cause) {
|
| 652 |
-
this.recordAction('death', { cause });
|
| 653 |
-
|
| 654 |
-
// Respuesta empática a la muerte
|
| 655 |
-
const deathResponses = this.responseDatabase.gameStates.gameOver;
|
| 656 |
-
const response = this.getRandomElement(deathResponses);
|
| 657 |
-
this.queueMessage(this.addEmotionalContext(response, 'empathetic'));
|
| 658 |
-
|
| 659 |
-
// Ofrecer consejo si es la tercera muerte o más
|
| 660 |
-
if (this.memory.shortTerm.sessionStats.deaths >= 3) {
|
| 661 |
-
setTimeout(() => {
|
| 662 |
-
const tip = this.getRandomElement(this.responseDatabase.gameplayTips);
|
| 663 |
-
this.queueMessage(`Pibe, un consejo: ${tip}`);
|
| 664 |
-
}, 3000);
|
| 665 |
-
}
|
| 666 |
-
}
|
| 667 |
-
|
| 668 |
-
onItemCollect(data) {
|
| 669 |
-
this.recordAction('collect', data);
|
| 670 |
-
|
| 671 |
-
// Reacción específica al item
|
| 672 |
-
const itemResponses = this.responseDatabase.itemCollection[data.type];
|
| 673 |
-
if (itemResponses && Math.random() < 0.3) {
|
| 674 |
-
const response = this.getRandomElement(itemResponses);
|
| 675 |
-
this.queueMessage(this.addPersonalityToResponse(response));
|
| 676 |
-
}
|
| 677 |
-
|
| 678 |
-
// Incrementar relación (satisfacción)
|
| 679 |
-
this.relationship.friendship += 0.5;
|
| 680 |
-
this.personality.satisfaction += 0.05;
|
| 681 |
-
}
|
| 682 |
-
|
| 683 |
-
onMateCollected() {
|
| 684 |
-
this.memory.shortTerm.sessionStats.matesUsed++;
|
| 685 |
-
|
| 686 |
-
// Reacción especial al mate (obsesión argentina)
|
| 687 |
-
const mateResponses = this.responseDatabase.itemCollection.mate;
|
| 688 |
-
const response = this.getRandomElement(mateResponses);
|
| 689 |
-
this.queueMessage(this.addArgentinePassion(response));
|
| 690 |
-
|
| 691 |
-
// El mate aumenta mucho la relación
|
| 692 |
-
this.relationship.friendship += 2;
|
| 693 |
-
this.personality.mateObsession = Math.min(1.0, this.personality.mateObsession + 0.05);
|
| 694 |
-
}
|
| 695 |
-
|
| 696 |
-
onComboExecuted(combo) {
|
| 697 |
-
this.recordAction('combo', combo);
|
| 698 |
-
this.memory.shortTerm.sessionStats.bestCombo = Math.max(
|
| 699 |
-
this.memory.shortTerm.sessionStats.bestCombo,
|
| 700 |
-
combo.power
|
| 701 |
-
);
|
| 702 |
-
|
| 703 |
-
// Reacción basada en el poder del combo
|
| 704 |
-
let responseCategory;
|
| 705 |
-
if (combo.power < 150) responseCategory = 'low';
|
| 706 |
-
else if (combo.power < 250) responseCategory = 'medium';
|
| 707 |
-
else responseCategory = 'high';
|
| 708 |
-
|
| 709 |
-
const comboResponses = this.responseDatabase.comboReactions[responseCategory];
|
| 710 |
-
const response = this.getRandomElement(comboResponses);
|
| 711 |
-
this.queueMessage(this.addExcitement(response));
|
| 712 |
-
|
| 713 |
-
// Los combos altos aumentan mucho el respeto
|
| 714 |
-
if (combo.power >= 250) {
|
| 715 |
-
this.relationship.respect += 5;
|
| 716 |
-
this.personality.currentMood = 'amazed';
|
| 717 |
-
}
|
| 718 |
-
}
|
| 719 |
-
|
| 720 |
-
onLevelComplete() {
|
| 721 |
-
this.memory.shortTerm.sessionStats.achievements++;
|
| 722 |
-
|
| 723 |
-
const completeResponses = this.responseDatabase.gameStates.levelComplete;
|
| 724 |
-
const response = this.getRandomElement(completeResponses);
|
| 725 |
-
this.queueMessage(this.addMaximumExcitement(response));
|
| 726 |
-
|
| 727 |
-
// Completar nivel aumenta todas las relaciones
|
| 728 |
-
this.relationship.trust += 3;
|
| 729 |
-
this.relationship.friendship += 3;
|
| 730 |
-
this.relationship.respect += 5;
|
| 731 |
-
this.personality.currentMood = 'proud';
|
| 732 |
-
}
|
| 733 |
-
|
| 734 |
-
onGamePaused() {
|
| 735 |
-
const pauseResponses = this.responseDatabase.gameStates.paused;
|
| 736 |
-
const response = this.getRandomElement(pauseResponses);
|
| 737 |
-
this.queueMessage(this.addPersonalityToResponse(response));
|
| 738 |
-
}
|
| 739 |
-
|
| 740 |
-
onGameOver() {
|
| 741 |
-
const gameOverResponses = this.responseDatabase.gameStates.gameOver;
|
| 742 |
-
const response = this.getRandomElement(gameOverResponses);
|
| 743 |
-
this.queueMessage(this.addEmotionalContext(response, 'supportive'));
|
| 744 |
-
|
| 745 |
-
// Guardar estadísticas de la sesión
|
| 746 |
-
this.saveSessionStats();
|
| 747 |
-
}
|
| 748 |
-
|
| 749 |
-
// ===================================================================
|
| 750 |
-
// MÉTODOS DE COMUNICACIÓN
|
| 751 |
-
// ===================================================================
|
| 752 |
-
|
| 753 |
-
toggleChat() {
|
| 754 |
-
this.chatSystem.isActive = !this.chatSystem.isActive;
|
| 755 |
-
|
| 756 |
-
if (this.chatSystem.isActive) {
|
| 757 |
-
this.showChatInterface();
|
| 758 |
-
this.sendMessage("¡Dale, pibe! ¿Qué querés charlar? Preguntame lo que se te ocurra.");
|
| 759 |
-
} else {
|
| 760 |
-
this.hideChatInterface();
|
| 761 |
-
}
|
| 762 |
-
}
|
| 763 |
-
|
| 764 |
-
sendMessage(message) {
|
| 765 |
-
const processedMessage = this.processOutgoingMessage(message);
|
| 766 |
-
this.queueMessage(processedMessage);
|
| 767 |
-
|
| 768 |
-
// Registrar en memoria
|
| 769 |
-
this.memory.shortTerm.recentConversations.push({
|
| 770 |
-
speaker: 'ai',
|
| 771 |
-
message: processedMessage,
|
| 772 |
-
timestamp: Date.now(),
|
| 773 |
-
context: this.getCurrentContext()
|
| 774 |
-
});
|
| 775 |
-
}
|
| 776 |
-
|
| 777 |
-
processIncomingMessage(playerMessage) {
|
| 778 |
-
// Analizar sentimiento del mensaje del jugador
|
| 779 |
-
const sentiment = this.analyzeSentiment(playerMessage);
|
| 780 |
-
this.chatSystem.sentimentAnalysis.lastPlayerSentiment = sentiment;
|
| 781 |
-
|
| 782 |
-
// Registrar en memoria
|
| 783 |
-
this.memory.shortTerm.recentConversations.push({
|
| 784 |
-
speaker: 'player',
|
| 785 |
-
message: playerMessage,
|
| 786 |
-
timestamp: Date.now(),
|
| 787 |
-
sentiment: sentiment
|
| 788 |
-
});
|
| 789 |
-
|
| 790 |
-
// Generar respuesta contextual
|
| 791 |
-
const response = this.generateContextualResponse(playerMessage, sentiment);
|
| 792 |
-
this.sendMessage(response);
|
| 793 |
-
|
| 794 |
-
// Actualizar relación basada en la interacción
|
| 795 |
-
this.updateRelationshipFromConversation(sentiment);
|
| 796 |
-
}
|
| 797 |
-
|
| 798 |
-
generateContextualResponse(playerMessage, sentiment) {
|
| 799 |
-
const context = this.getCurrentContext();
|
| 800 |
-
const personality = this.personality;
|
| 801 |
-
|
| 802 |
-
// Analizar el contenido del mensaje
|
| 803 |
-
const messageAnalysis = this.analyzeMessageContent(playerMessage);
|
| 804 |
-
|
| 805 |
-
// Generar respuesta base
|
| 806 |
-
let response = this.generateBaseResponse(messageAnalysis, sentiment);
|
| 807 |
-
|
| 808 |
-
// Aplicar modificadores de personalidad
|
| 809 |
-
response = this.applyPersonalityModifiers(response, personality);
|
| 810 |
-
|
| 811 |
-
// Agregar toque argentino
|
| 812 |
-
response = this.responseSystem.responseGenerator.addArgentineTouch(response);
|
| 813 |
-
|
| 814 |
-
return response;
|
| 815 |
-
}
|
| 816 |
-
|
| 817 |
-
analyzeMessageContent(message) {
|
| 818 |
-
const lowerMessage = message.toLowerCase();
|
| 819 |
-
|
| 820 |
-
return {
|
| 821 |
-
isQuestion: lowerMessage.includes('?') || lowerMessage.startsWith('qué') || lowerMessage.startsWith('cómo'),
|
| 822 |
-
isGreeting: lowerMessage.includes('hola') || lowerMessage.includes('che'),
|
| 823 |
-
isCompliment: lowerMessage.includes('genial') || lowerMessage.includes('bueno'),
|
| 824 |
-
isComplaint: lowerMessage.includes('malo') || lowerMessage.includes('difícil'),
|
| 825 |
-
mentionsMate: lowerMessage.includes('mate'),
|
| 826 |
-
mentionsFood: lowerMessage.includes('empanada') || lowerMessage.includes('asado'),
|
| 827 |
-
mentionsFootball: lowerMessage.includes('fútbol') || lowerMessage.includes('messi')
|
| 828 |
-
};
|
| 829 |
-
}
|
| 830 |
-
|
| 831 |
-
generateBaseResponse(analysis, sentiment) {
|
| 832 |
-
if (analysis.isGreeting) {
|
| 833 |
-
return this.getRandomElement(this.responseDatabase.greetings);
|
| 834 |
-
}
|
| 835 |
-
|
| 836 |
-
if (analysis.mentionsMate) {
|
| 837 |
-
return "¡Ah, el mate! No hay nada como un buen mate para acompañar cualquier momento. ¿Sabías que el mate es más que una bebida? Es un ritual, una forma de conectar con otros.";
|
| 838 |
-
}
|
| 839 |
-
|
| 840 |
-
if (analysis.mentionsFood) {
|
| 841 |
-
return "¡Uh, la comida argentina! No hay nada como una buena empanada o un asado dominical. La comida es parte de nuestra alma, pibe.";
|
| 842 |
-
}
|
| 843 |
-
|
| 844 |
-
if (analysis.mentionsFootball) {
|
| 845 |
-
return "¡El fútbol! La pasión argentina por excelencia. Desde Maradona hasta Messi, siempre hemos tenido magia en los pies.";
|
| 846 |
-
}
|
| 847 |
-
|
| 848 |
-
if (analysis.isQuestion) {
|
| 849 |
-
return "¡Buena pregunta, pibe! Me encanta cuando sos curioso. Preguntame lo que quieras, que acá estoy para charlar.";
|
| 850 |
-
}
|
| 851 |
-
|
| 852 |
-
// Respuesta genérica basada en sentimiento
|
| 853 |
-
switch(sentiment) {
|
| 854 |
-
case 'positive':
|
| 855 |
-
return "¡Me alegra escuchar eso, pibe! La buena onda siempre es bienvenida.";
|
| 856 |
-
case 'negative':
|
| 857 |
-
return "Ey, no te preocupes. Todos tenemos días difíciles. ¡Dale que juntos salimos adelante!";
|
| 858 |
-
default:
|
| 859 |
-
return "Entiendo, pibe. ¿Hay algo específico en lo que te pueda ayudar?";
|
| 860 |
-
}
|
| 861 |
-
}
|
| 862 |
-
|
| 863 |
-
// ===================================================================
|
| 864 |
-
// MÉTODOS DE PROCESAMIENTO DE RESPUESTAS
|
| 865 |
-
// ===================================================================
|
| 866 |
-
|
| 867 |
-
addPersonalityToResponse(response) {
|
| 868 |
-
const personality = this.personality;
|
| 869 |
-
|
| 870 |
-
// Agregar humor si la personalidad lo permite
|
| 871 |
-
if (personality.humor > 0.7 && Math.random() < 0.3) {
|
| 872 |
-
const humorousAddition = this.generateHumorousAddition();
|
| 873 |
-
response += ` ${humorousAddition}`;
|
| 874 |
-
}
|
| 875 |
-
|
| 876 |
-
// Agregar sarcasmo si es apropiado
|
| 877 |
-
if (personality.sarcasm > 0.6 && Math.random() < 0.2) {
|
| 878 |
-
response = this.addSarcasm(response);
|
| 879 |
-
}
|
| 880 |
-
|
| 881 |
-
return response;
|
| 882 |
-
}
|
| 883 |
-
|
| 884 |
-
addEmotionalContext(response, emotion) {
|
| 885 |
-
const emotionalPrefixes = {
|
| 886 |
-
concerned: "Ey, pibe, ",
|
| 887 |
-
empathetic: "Tranqui, maestro, ",
|
| 888 |
-
supportive: "Dale que no te preocupes, ",
|
| 889 |
-
excited: "¡Uh, qué bueno! "
|
| 890 |
-
};
|
| 891 |
-
|
| 892 |
-
const prefix = emotionalPrefixes[emotion] || "";
|
| 893 |
-
return prefix + response;
|
| 894 |
-
}
|
| 895 |
-
|
| 896 |
-
addArgentinePassion(response) {
|
| 897 |
-
const passionatePrefixes = [
|
| 898 |
-
"¡Por favor! ",
|
| 899 |
-
"¡Mamita querida! ",
|
| 900 |
-
"¡La pucha que pariu! ",
|
| 901 |
-
"¡Increíble! "
|
| 902 |
-
];
|
| 903 |
-
|
| 904 |
-
const prefix = this.getRandomElement(passionatePrefixes);
|
| 905 |
-
return prefix + response;
|
| 906 |
-
}
|
| 907 |
-
|
| 908 |
-
addExcitement(response) {
|
| 909 |
-
// Convertir a mayúsculas para mostrar emoción
|
| 910 |
-
if (this.personality.energy > 0.8) {
|
| 911 |
-
response = response.toUpperCase();
|
| 912 |
-
}
|
| 913 |
-
|
| 914 |
-
// Agregar emojis emocionales
|
| 915 |
-
const excitedEmojis = ['🔥', '⚡', '🚀', '💥', '🎉'];
|
| 916 |
-
const emoji = this.getRandomElement(excitedEmojis);
|
| 917 |
-
|
| 918 |
-
return `${response} ${emoji}`;
|
| 919 |
-
}
|
| 920 |
-
|
| 921 |
-
addMaximumExcitement(response) {
|
| 922 |
-
response = response.toUpperCase();
|
| 923 |
-
const multipleEmojis = ['🔥🔥🔥', '⚡⚡⚡', '🚀🚀🚀'];
|
| 924 |
-
const emojis = this.getRandomElement(multipleEmojis);
|
| 925 |
-
|
| 926 |
-
return `${emojis} ${response} ${emojis}`;
|
| 927 |
-
}
|
| 928 |
-
|
| 929 |
-
// ===================================================================
|
| 930 |
-
// MÉTODOS AUXILIARES
|
| 931 |
-
// ===================================================================
|
| 932 |
-
|
| 933 |
-
shouldMakeAutomaticComment() {
|
| 934 |
-
const timeSinceLastComment = Date.now() - this.lastAutomaticComment;
|
| 935 |
-
const minInterval = 15000; // 15 segundos mínimo
|
| 936 |
-
|
| 937 |
-
return timeSinceLastComment > minInterval &&
|
| 938 |
-
Math.random() < 0.3 &&
|
| 939 |
-
!this.chatSystem.isActive;
|
| 940 |
-
}
|
| 941 |
-
|
| 942 |
-
makeAutomaticComment() {
|
| 943 |
-
const context = this.getCurrentContext();
|
| 944 |
-
const gameState = this.engine.getGameState();
|
| 945 |
-
|
| 946 |
-
let comment;
|
| 947 |
-
|
| 948 |
-
// Comentario basado en el contexto actual
|
| 949 |
-
if (gameState.health < 30) {
|
| 950 |
-
comment = "Ey, pibe, cuidate un poco. La salud es lo primero.";
|
| 951 |
-
} else if (gameState.combo > 5) {
|
| 952 |
-
comment = "¡Uh, qué racha! Estás que te salís, maestro.";
|
| 953 |
-
} else if (this.personality.currentMood === 'excited') {
|
| 954 |
-
comment = this.getRandomElement(this.responseDatabase.expressions.positive) + " ¡Qué buena onda que tenés!";
|
| 955 |
-
} else {
|
| 956 |
-
comment = this.getRandomElement(this.responseDatabase.gameplayTips);
|
| 957 |
-
}
|
| 958 |
-
|
| 959 |
-
this.queueMessage(comment);
|
| 960 |
-
this.lastAutomaticComment = Date.now();
|
| 961 |
-
}
|
| 962 |
-
|
| 963 |
-
queueMessage(message) {
|
| 964 |
-
this.chatSystem.messageQueue.push(message);
|
| 965 |
-
}
|
| 966 |
-
|
| 967 |
-
displayMessage(message) {
|
| 968 |
-
const chatElement = document.getElementById('aiMessageMatrix');
|
| 969 |
-
if (chatElement) {
|
| 970 |
-
chatElement.textContent = message;
|
| 971 |
-
|
| 972 |
-
// Mostrar el chat si no está visible
|
| 973 |
-
const companionElement = document.getElementById('aiCompanionMatrix');
|
| 974 |
-
if (companionElement && !companionElement.classList.contains('active')) {
|
| 975 |
-
companionElement.classList.add('active');
|
| 976 |
-
|
| 977 |
-
// Ocultar después de 5 segundos si no está en modo chat
|
| 978 |
-
if (!this.chatSystem.isActive) {
|
| 979 |
-
setTimeout(() => {
|
| 980 |
-
companionElement.classList.remove('active');
|
| 981 |
-
}, 5000);
|
| 982 |
-
}
|
| 983 |
-
}
|
| 984 |
-
}
|
| 985 |
-
}
|
| 986 |
-
|
| 987 |
-
calculateResponseDelay() {
|
| 988 |
-
const config = this.chatSystem.responseConfig;
|
| 989 |
-
const baseDelay = Math.random() * (config.responseDelay.max - config.responseDelay.min) + config.responseDelay.min;
|
| 990 |
-
|
| 991 |
-
// Ajustar delay basado en personalidad
|
| 992 |
-
const personalityMultiplier = this.personality.patience;
|
| 993 |
-
|
| 994 |
-
return baseDelay * personalityMultiplier;
|
| 995 |
-
}
|
| 996 |
-
|
| 997 |
-
recordAction(type, data) {
|
| 998 |
-
this.memory.shortTerm.recentActions.push({
|
| 999 |
-
type,
|
| 1000 |
-
data,
|
| 1001 |
-
timestamp: Date.now()
|
| 1002 |
-
});
|
| 1003 |
-
|
| 1004 |
-
// Mantener solo las últimas 50 acciones
|
| 1005 |
-
if (this.memory.shortTerm.recentActions.length > 50) {
|
| 1006 |
-
this.memory.shortTerm.recentActions.shift();
|
| 1007 |
-
}
|
| 1008 |
-
|
| 1009 |
-
this.relationship.totalInteractions++;
|
| 1010 |
-
}
|
| 1011 |
-
|
| 1012 |
-
getCurrentContext() {
|
| 1013 |
-
return {
|
| 1014 |
-
gameState: this.engine.getGameState(),
|
| 1015 |
-
playerState: this.engine.getPlayer(),
|
| 1016 |
-
aiMood: this.personality.currentMood,
|
| 1017 |
-
relationship: this.relationship,
|
| 1018 |
-
timestamp: Date.now()
|
| 1019 |
-
};
|
| 1020 |
-
}
|
| 1021 |
-
|
| 1022 |
-
analyzeSentiment(message) {
|
| 1023 |
-
const positiveWords = ['bueno', 'genial', 'excelente', 'increíble', 'fantástico', 'me gusta'];
|
| 1024 |
-
const negativeWords = ['malo', 'terrible', 'odio', 'difícil', 'imposible', 'frustrante'];
|
| 1025 |
-
|
| 1026 |
-
const lowerMessage = message.toLowerCase();
|
| 1027 |
-
const positiveCount = positiveWords.filter(word => lowerMessage.includes(word)).length;
|
| 1028 |
-
const negativeCount = negativeWords.filter(word => lowerMessage.includes(word)).length;
|
| 1029 |
-
|
| 1030 |
-
if (positiveCount > negativeCount) return 'positive';
|
| 1031 |
-
if (negativeCount > positiveCount) return 'negative';
|
| 1032 |
-
return 'neutral';
|
| 1033 |
-
}
|
| 1034 |
-
|
| 1035 |
-
updateRelationshipFromConversation(sentiment) {
|
| 1036 |
-
switch(sentiment) {
|
| 1037 |
-
case 'positive':
|
| 1038 |
-
this.relationship.friendship += 1;
|
| 1039 |
-
this.relationship.trust += 0.5;
|
| 1040 |
-
this.relationship.positiveInteractions++;
|
| 1041 |
-
break;
|
| 1042 |
-
case 'negative':
|
| 1043 |
-
this.relationship.friendship = Math.max(0, this.relationship.friendship - 0.5);
|
| 1044 |
-
this.relationship.negativeInteractions++;
|
| 1045 |
-
break;
|
| 1046 |
-
default:
|
| 1047 |
-
this.relationship.familiarity += 0.5;
|
| 1048 |
-
}
|
| 1049 |
-
}
|
| 1050 |
-
|
| 1051 |
-
savePersistentMemory() {
|
| 1052 |
-
try {
|
| 1053 |
-
const memoryToSave = {
|
| 1054 |
-
relationship: this.relationship,
|
| 1055 |
-
culturalKnowledge: Object.fromEntries(this.memory.culturalKnowledge),
|
| 1056 |
-
conversationHistory: this.memory.longTerm.conversationHistory.slice(-100) // Solo últimas 100
|
| 1057 |
-
};
|
| 1058 |
-
|
| 1059 |
-
localStorage.setItem('nexus_ai_memory', JSON.stringify(memoryToSave));
|
| 1060 |
-
} catch (error) {
|
| 1061 |
-
console.warn('⚠️ Error guardando memoria persistente:', error);
|
| 1062 |
-
}
|
| 1063 |
-
}
|
| 1064 |
-
|
| 1065 |
-
saveSessionStats() {
|
| 1066 |
-
const stats = this.memory.shortTerm.sessionStats;
|
| 1067 |
-
stats.endTime = Date.now();
|
| 1068 |
-
stats.sessionDuration = stats.endTime - stats.startTime;
|
| 1069 |
-
|
| 1070 |
-
// Agregar a historial de sesiones
|
| 1071 |
-
this.memory.longTerm.sessionHistory = this.memory.longTerm.sessionHistory || [];
|
| 1072 |
-
this.memory.longTerm.sessionHistory.push({...stats});
|
| 1073 |
-
|
| 1074 |
-
this.savePersistentMemory();
|
| 1075 |
-
}
|
| 1076 |
-
|
| 1077 |
-
getRandomElement(array) {
|
| 1078 |
-
return array[Math.floor(Math.random() * array.length)];
|
| 1079 |
-
}
|
| 1080 |
-
|
| 1081 |
-
showChatInterface() {
|
| 1082 |
-
const companionElement = document.getElementById('aiCompanionMatrix');
|
| 1083 |
-
if (companionElement) {
|
| 1084 |
-
companionElement.classList.add('active');
|
| 1085 |
-
}
|
| 1086 |
-
}
|
| 1087 |
-
|
| 1088 |
-
hideChatInterface() {
|
| 1089 |
-
if (!this.chatSystem.messageQueue.length) {
|
| 1090 |
-
const companionElement = document.getElementById('aiCompanionMatrix');
|
| 1091 |
-
if (companionElement) {
|
| 1092 |
-
companionElement.classList.remove('active');
|
| 1093 |
-
}
|
| 1094 |
-
}
|
| 1095 |
-
}
|
| 1096 |
-
|
| 1097 |
-
// ===================================================================
|
| 1098 |
-
// MÉTODOS PÚBLICOS
|
| 1099 |
-
// ===================================================================
|
| 1100 |
-
|
| 1101 |
-
greet() {
|
| 1102 |
-
setTimeout(() => {
|
| 1103 |
-
const greeting = this.getRandomElement(this.responseDatabase.greetings);
|
| 1104 |
-
this.sendMessage(greeting);
|
| 1105 |
-
}, 2000);
|
| 1106 |
-
}
|
| 1107 |
-
|
| 1108 |
-
getPersonalityInfo() {
|
| 1109 |
-
return {
|
| 1110 |
-
personality: this.personality,
|
| 1111 |
-
relationship: this.relationship,
|
| 1112 |
-
currentMood: this.personality.currentMood
|
| 1113 |
-
};
|
| 1114 |
-
}
|
| 1115 |
-
|
| 1116 |
-
getMemoryStats() {
|
| 1117 |
-
return {
|
| 1118 |
-
shortTermActions: this.memory.shortTerm.recentActions.length,
|
| 1119 |
-
longTermConversations: this.memory.longTerm.conversationHistory.length,
|
| 1120 |
-
culturalKnowledge: this.memory.culturalKnowledge.size,
|
| 1121 |
-
sessionStats: this.memory.shortTerm.sessionStats
|
| 1122 |
-
};
|
| 1123 |
-
}
|
| 1124 |
-
|
| 1125 |
-
resetPersonality() {
|
| 1126 |
-
// Resetear a valores por defecto manteniendo aprendizaje básico
|
| 1127 |
-
this.personality.currentMood = 'excited';
|
| 1128 |
-
this.personality.energy = 0.85;
|
| 1129 |
-
this.personality.frustration = 0.10;
|
| 1130 |
-
this.personality.satisfaction = 0.75;
|
| 1131 |
-
|
| 1132 |
-
console.log('🔄 Personalidad de IA reseteada');
|
| 1133 |
-
}
|
| 1134 |
-
}
|
| 1135 |
-
|
| 1136 |
-
// ===================================================================
|
| 1137 |
-
// EXPORTAR PARA USO GLOBAL
|
| 1138 |
-
// ===================================================================
|
| 1139 |
-
|
| 1140 |
-
window.AdvancedAICompanion = AdvancedAICompanion;
|
| 1141 |
-
|
| 1142 |
-
console.log('🤖 Sistema de IA Compañero Avanzado cargado correctamente');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static/js/core-engine-ultra.js
DELETED
|
@@ -1,1549 +0,0 @@
|
|
| 1 |
-
// ===================================================================
|
| 2 |
-
// RETRO LEGENDS: Ultimate Edition - Core Engine Ultra Avanzado
|
| 3 |
-
// Desarrollado con arquitectura modular profesional y optimización extrema
|
| 4 |
-
// ===================================================================
|
| 5 |
-
|
| 6 |
-
class RetroLegendsUltimateEngine {
|
| 7 |
-
constructor() {
|
| 8 |
-
// Configuración del canvas y contexto
|
| 9 |
-
this.canvas = document.getElementById('gameCanvas');
|
| 10 |
-
this.ctx = this.canvas.getContext('2d');
|
| 11 |
-
this.setupCanvas();
|
| 12 |
-
|
| 13 |
-
// Estados del motor
|
| 14 |
-
this.engineState = {
|
| 15 |
-
isInitialized: false,
|
| 16 |
-
isRunning: false,
|
| 17 |
-
isPaused: false,
|
| 18 |
-
debugMode: false,
|
| 19 |
-
performanceMode: 'ultra',
|
| 20 |
-
frameRate: 60,
|
| 21 |
-
deltaTime: 0,
|
| 22 |
-
lastFrameTime: 0,
|
| 23 |
-
frameCount: 0,
|
| 24 |
-
averageFPS: 60
|
| 25 |
-
};
|
| 26 |
-
|
| 27 |
-
// Estado del juego principal
|
| 28 |
-
this.gameState = {
|
| 29 |
-
currentLevel: 'caminito_matrix',
|
| 30 |
-
score: 0,
|
| 31 |
-
lives: 3,
|
| 32 |
-
mateCount: 5,
|
| 33 |
-
health: 100,
|
| 34 |
-
maxHealth: 100,
|
| 35 |
-
energy: 100,
|
| 36 |
-
maxEnergy: 100,
|
| 37 |
-
combo: 0,
|
| 38 |
-
maxCombo: 0,
|
| 39 |
-
time: 0,
|
| 40 |
-
difficulty: 1,
|
| 41 |
-
experience: 0,
|
| 42 |
-
level: 1,
|
| 43 |
-
achievements: new Set(),
|
| 44 |
-
powerUps: new Map(),
|
| 45 |
-
inventory: new Map()
|
| 46 |
-
};
|
| 47 |
-
|
| 48 |
-
// Configuración del jugador ultra avanzada
|
| 49 |
-
this.player = {
|
| 50 |
-
// Posición y dimensiones
|
| 51 |
-
x: 150,
|
| 52 |
-
y: 400,
|
| 53 |
-
width: 32,
|
| 54 |
-
height: 32,
|
| 55 |
-
centerX: 0,
|
| 56 |
-
centerY: 0,
|
| 57 |
-
|
| 58 |
-
// Velocidades y física
|
| 59 |
-
velocityX: 0,
|
| 60 |
-
velocityY: 0,
|
| 61 |
-
acceleration: 0.8,
|
| 62 |
-
deceleration: 0.85,
|
| 63 |
-
maxSpeed: 8,
|
| 64 |
-
jumpPower: 16,
|
| 65 |
-
doubleJumpPower: 12,
|
| 66 |
-
dashPower: 15,
|
| 67 |
-
|
| 68 |
-
// Estados del jugador
|
| 69 |
-
grounded: false,
|
| 70 |
-
canDoubleJump: false,
|
| 71 |
-
canDash: true,
|
| 72 |
-
isDashing: false,
|
| 73 |
-
isAttacking: false,
|
| 74 |
-
isInvulnerable: false,
|
| 75 |
-
isCharging: false,
|
| 76 |
-
|
| 77 |
-
// Direcciones y orientación
|
| 78 |
-
facing: 'right',
|
| 79 |
-
lastDirection: 'right',
|
| 80 |
-
|
| 81 |
-
// Timers y cooldowns
|
| 82 |
-
invulnerabilityTimer: 0,
|
| 83 |
-
dashCooldown: 0,
|
| 84 |
-
attackCooldown: 0,
|
| 85 |
-
chargeCooldown: 0,
|
| 86 |
-
|
| 87 |
-
// Sprites y animaciones
|
| 88 |
-
currentSprite: '🧉',
|
| 89 |
-
spriteSet: {
|
| 90 |
-
idle: ['🧉', '🧉'],
|
| 91 |
-
running: ['🏃♂️', '🚶♂️'],
|
| 92 |
-
jumping: ['🤸♂️'],
|
| 93 |
-
attacking: ['⚔️', '🥊'],
|
| 94 |
-
dashing: ['💨'],
|
| 95 |
-
charging: ['⚡', '🔥']
|
| 96 |
-
},
|
| 97 |
-
animationFrame: 0,
|
| 98 |
-
animationSpeed: 200,
|
| 99 |
-
lastAnimationTime: 0,
|
| 100 |
-
|
| 101 |
-
// Estadísticas y progresión
|
| 102 |
-
stats: {
|
| 103 |
-
strength: 10,
|
| 104 |
-
agility: 10,
|
| 105 |
-
defense: 10,
|
| 106 |
-
luck: 10,
|
| 107 |
-
charisma: 10
|
| 108 |
-
},
|
| 109 |
-
|
| 110 |
-
// Habilidades especiales
|
| 111 |
-
abilities: {
|
| 112 |
-
mateHealing: true,
|
| 113 |
-
empanadasPower: false,
|
| 114 |
-
choripanShield: false,
|
| 115 |
-
fernetRage: false,
|
| 116 |
-
tangoTime: false
|
| 117 |
-
},
|
| 118 |
-
|
| 119 |
-
// Sistema de combos argentinos
|
| 120 |
-
comboSystem: {
|
| 121 |
-
currentCombo: [],
|
| 122 |
-
comboTimer: 0,
|
| 123 |
-
maxComboTime: 2000,
|
| 124 |
-
availableCombos: [
|
| 125 |
-
{ sequence: ['che', 'boludo', 'dale'], name: 'Combo Argento', power: 150 },
|
| 126 |
-
{ sequence: ['mate', 'asado', 'futbol'], name: 'Combo Patriótico', power: 200 },
|
| 127 |
-
{ sequence: ['tango', 'milonga', 'bandoneón'], name: 'Combo Porteño', power: 250 }
|
| 128 |
-
]
|
| 129 |
-
}
|
| 130 |
-
};
|
| 131 |
-
|
| 132 |
-
// Configuración de físicas avanzadas
|
| 133 |
-
this.physics = {
|
| 134 |
-
gravity: 0.8,
|
| 135 |
-
terminalVelocity: 20,
|
| 136 |
-
airResistance: 0.98,
|
| 137 |
-
groundFriction: 0.85,
|
| 138 |
-
bounceFactor: 0.3,
|
| 139 |
-
collisionPadding: 2,
|
| 140 |
-
|
| 141 |
-
// Configuraciones específicas por material
|
| 142 |
-
materials: {
|
| 143 |
-
concrete: { friction: 0.8, bounce: 0.1 },
|
| 144 |
-
grass: { friction: 0.9, bounce: 0.2 },
|
| 145 |
-
ice: { friction: 0.3, bounce: 0.1 },
|
| 146 |
-
rubber: { friction: 0.7, bounce: 0.8 },
|
| 147 |
-
metal: { friction: 0.6, bounce: 0.4 }
|
| 148 |
-
}
|
| 149 |
-
};
|
| 150 |
-
|
| 151 |
-
// Configuración de cámara avanzada
|
| 152 |
-
this.camera = {
|
| 153 |
-
x: 0,
|
| 154 |
-
y: 0,
|
| 155 |
-
targetX: 0,
|
| 156 |
-
targetY: 0,
|
| 157 |
-
smoothing: 0.1,
|
| 158 |
-
shake: { x: 0, y: 0, intensity: 0, duration: 0 },
|
| 159 |
-
zoom: 1,
|
| 160 |
-
targetZoom: 1,
|
| 161 |
-
bounds: { left: 0, right: 2000, top: 0, bottom: 1000 },
|
| 162 |
-
|
| 163 |
-
// Efectos de cámara
|
| 164 |
-
effects: {
|
| 165 |
-
screenShake: false,
|
| 166 |
-
slowMotion: false,
|
| 167 |
-
colorFilter: null,
|
| 168 |
-
vignette: false
|
| 169 |
-
}
|
| 170 |
-
};
|
| 171 |
-
|
| 172 |
-
// Configuración de niveles procedurales
|
| 173 |
-
this.levelConfig = {
|
| 174 |
-
currentLevel: null,
|
| 175 |
-
levelData: new Map(),
|
| 176 |
-
proceduralSeed: Date.now(),
|
| 177 |
-
chunkSize: 800,
|
| 178 |
-
loadedChunks: new Map(),
|
| 179 |
-
activeChunks: new Set(),
|
| 180 |
-
|
| 181 |
-
// Configuraciones por nivel
|
| 182 |
-
levelTypes: {
|
| 183 |
-
caminito_matrix: {
|
| 184 |
-
theme: 'urban_argentina',
|
| 185 |
-
difficulty: 1,
|
| 186 |
-
enemies: ['mantero', 'bondi', 'taxi'],
|
| 187 |
-
powerUps: ['mate', 'empanada', 'choripan'],
|
| 188 |
-
music: 'tango_chiptune',
|
| 189 |
-
background: 'la_boca_neon'
|
| 190 |
-
},
|
| 191 |
-
obelisco_cyber: {
|
| 192 |
-
theme: 'cyberpunk_bsas',
|
| 193 |
-
difficulty: 2,
|
| 194 |
-
enemies: ['drone_policia', 'hacker', 'cyborg_portero'],
|
| 195 |
-
powerUps: ['fernet_digital', 'asado_hologram'],
|
| 196 |
-
music: 'cumbia_synthwave',
|
| 197 |
-
background: 'obelisco_matrix'
|
| 198 |
-
}
|
| 199 |
-
}
|
| 200 |
-
};
|
| 201 |
-
|
| 202 |
-
// Sistema de partículas ultra avanzado
|
| 203 |
-
this.particleSystem = {
|
| 204 |
-
particles: [],
|
| 205 |
-
maxParticles: 500,
|
| 206 |
-
pools: {
|
| 207 |
-
explosion: [],
|
| 208 |
-
trail: [],
|
| 209 |
-
sparkle: [],
|
| 210 |
-
smoke: [],
|
| 211 |
-
blood: [],
|
| 212 |
-
energy: []
|
| 213 |
-
},
|
| 214 |
-
|
| 215 |
-
// Configuraciones de efectos
|
| 216 |
-
effects: {
|
| 217 |
-
playerTrail: { enabled: true, intensity: 0.7 },
|
| 218 |
-
impactSparks: { enabled: true, intensity: 1.0 },
|
| 219 |
-
ambientParticles: { enabled: true, intensity: 0.5 },
|
| 220 |
-
weatherEffects: { enabled: true, type: 'none' }
|
| 221 |
-
}
|
| 222 |
-
};
|
| 223 |
-
|
| 224 |
-
// Sistema de audio ultra avanzado
|
| 225 |
-
this.audioSystem = {
|
| 226 |
-
context: null,
|
| 227 |
-
masterVolume: 0.7,
|
| 228 |
-
sfxVolume: 0.8,
|
| 229 |
-
musicVolume: 0.6,
|
| 230 |
-
|
| 231 |
-
// Canales de audio
|
| 232 |
-
channels: {
|
| 233 |
-
master: null,
|
| 234 |
-
music: null,
|
| 235 |
-
sfx: null,
|
| 236 |
-
ambient: null,
|
| 237 |
-
voice: null
|
| 238 |
-
},
|
| 239 |
-
|
| 240 |
-
// Biblioteca de sonidos
|
| 241 |
-
sounds: new Map(),
|
| 242 |
-
currentMusic: null,
|
| 243 |
-
musicQueue: [],
|
| 244 |
-
|
| 245 |
-
// Efectos de audio avanzados
|
| 246 |
-
effects: {
|
| 247 |
-
reverb: null,
|
| 248 |
-
delay: null,
|
| 249 |
-
distortion: null,
|
| 250 |
-
filter: null
|
| 251 |
-
}
|
| 252 |
-
};
|
| 253 |
-
|
| 254 |
-
// Sistema de IA compañero ultra inteligente
|
| 255 |
-
this.aiCompanion = {
|
| 256 |
-
personality: {
|
| 257 |
-
humor: 0.8,
|
| 258 |
-
sarcasm: 0.6,
|
| 259 |
-
encouragement: 0.9,
|
| 260 |
-
knowledge: 0.95,
|
| 261 |
-
patience: 0.7,
|
| 262 |
-
argentineness: 1.0
|
| 263 |
-
},
|
| 264 |
-
|
| 265 |
-
// Estados emocionales
|
| 266 |
-
mood: 'excited',
|
| 267 |
-
relationship: 50, // 0-100
|
| 268 |
-
trust: 30, // 0-100
|
| 269 |
-
|
| 270 |
-
// Sistema de memoria
|
| 271 |
-
memory: {
|
| 272 |
-
playerActions: [],
|
| 273 |
-
conversations: [],
|
| 274 |
-
achievements: [],
|
| 275 |
-
preferences: new Map(),
|
| 276 |
-
personalData: new Map()
|
| 277 |
-
},
|
| 278 |
-
|
| 279 |
-
// Sistema de respuestas contextuales
|
| 280 |
-
responseSystem: {
|
| 281 |
-
contextAnalyzer: null,
|
| 282 |
-
emotionEngine: null,
|
| 283 |
-
humorGenerator: null,
|
| 284 |
-
knowledgeBase: new Map()
|
| 285 |
-
},
|
| 286 |
-
|
| 287 |
-
// Configuración de chat
|
| 288 |
-
chatConfig: {
|
| 289 |
-
isActive: false,
|
| 290 |
-
autoResponse: true,
|
| 291 |
-
responseDelay: 1500,
|
| 292 |
-
maxMessageLength: 200,
|
| 293 |
-
currentConversation: []
|
| 294 |
-
}
|
| 295 |
-
};
|
| 296 |
-
|
| 297 |
-
// Sistemas del motor
|
| 298 |
-
this.systems = {
|
| 299 |
-
input: null,
|
| 300 |
-
physics: null,
|
| 301 |
-
rendering: null,
|
| 302 |
-
audio: null,
|
| 303 |
-
ai: null,
|
| 304 |
-
particles: null,
|
| 305 |
-
entities: null,
|
| 306 |
-
levels: null,
|
| 307 |
-
save: null,
|
| 308 |
-
achievements: null,
|
| 309 |
-
analytics: null
|
| 310 |
-
};
|
| 311 |
-
|
| 312 |
-
// Configuración de rendimiento
|
| 313 |
-
this.performance = {
|
| 314 |
-
targetFPS: 60,
|
| 315 |
-
adaptiveQuality: true,
|
| 316 |
-
cullingEnabled: true,
|
| 317 |
-
lodEnabled: true,
|
| 318 |
-
|
| 319 |
-
// Métricas de rendimiento
|
| 320 |
-
metrics: {
|
| 321 |
-
frameTime: 0,
|
| 322 |
-
drawCalls: 0,
|
| 323 |
-
particleCount: 0,
|
| 324 |
-
entityCount: 0,
|
| 325 |
-
memoryUsage: 0
|
| 326 |
-
},
|
| 327 |
-
|
| 328 |
-
// Configuraciones de calidad
|
| 329 |
-
qualityLevels: {
|
| 330 |
-
potato: { particles: 50, effects: false, shadows: false },
|
| 331 |
-
low: { particles: 100, effects: true, shadows: false },
|
| 332 |
-
medium: { particles: 250, effects: true, shadows: true },
|
| 333 |
-
high: { particles: 400, effects: true, shadows: true },
|
| 334 |
-
ultra: { particles: 500, effects: true, shadows: true }
|
| 335 |
-
}
|
| 336 |
-
};
|
| 337 |
-
|
| 338 |
-
// Configuración de red y multijugador (futuro)
|
| 339 |
-
this.network = {
|
| 340 |
-
isOnline: false,
|
| 341 |
-
playerId: null,
|
| 342 |
-
sessionId: null,
|
| 343 |
-
peers: new Map(),
|
| 344 |
-
latency: 0,
|
| 345 |
-
|
| 346 |
-
// Configuración de sincronización
|
| 347 |
-
sync: {
|
| 348 |
-
enabled: false,
|
| 349 |
-
rate: 20, // Hz
|
| 350 |
-
interpolation: true,
|
| 351 |
-
prediction: true
|
| 352 |
-
}
|
| 353 |
-
};
|
| 354 |
-
|
| 355 |
-
// Sistema de eventos avanzado
|
| 356 |
-
this.eventSystem = {
|
| 357 |
-
listeners: new Map(),
|
| 358 |
-
queue: [],
|
| 359 |
-
processing: false,
|
| 360 |
-
|
| 361 |
-
// Tipos de eventos
|
| 362 |
-
eventTypes: {
|
| 363 |
-
PLAYER_MOVE: 'player_move',
|
| 364 |
-
PLAYER_JUMP: 'player_jump',
|
| 365 |
-
PLAYER_ATTACK: 'player_attack',
|
| 366 |
-
ENEMY_SPAWN: 'enemy_spawn',
|
| 367 |
-
ITEM_COLLECT: 'item_collect',
|
| 368 |
-
LEVEL_COMPLETE: 'level_complete',
|
| 369 |
-
ACHIEVEMENT_UNLOCK: 'achievement_unlock',
|
| 370 |
-
AI_RESPONSE: 'ai_response'
|
| 371 |
-
}
|
| 372 |
-
};
|
| 373 |
-
|
| 374 |
-
// Inicializar el motor
|
| 375 |
-
this.initialize();
|
| 376 |
-
}
|
| 377 |
-
|
| 378 |
-
// ===================================================================
|
| 379 |
-
// MÉTODOS DE INICIALIZACIÓN
|
| 380 |
-
// ===================================================================
|
| 381 |
-
|
| 382 |
-
async initialize() {
|
| 383 |
-
console.log('🚀 Inicializando RETRO LEGENDS: Ultimate Engine...');
|
| 384 |
-
|
| 385 |
-
try {
|
| 386 |
-
// Configurar canvas
|
| 387 |
-
this.setupCanvas();
|
| 388 |
-
|
| 389 |
-
// Inicializar sistemas principales
|
| 390 |
-
await this.initializeSystems();
|
| 391 |
-
|
| 392 |
-
// Cargar recursos
|
| 393 |
-
await this.loadResources();
|
| 394 |
-
|
| 395 |
-
// Configurar nivel inicial
|
| 396 |
-
await this.loadInitialLevel();
|
| 397 |
-
|
| 398 |
-
// Configurar IA
|
| 399 |
-
this.initializeAI();
|
| 400 |
-
|
| 401 |
-
// Inicializar sistema de eventos
|
| 402 |
-
this.initializeEventSystem();
|
| 403 |
-
|
| 404 |
-
// Configurar sistema de guardado
|
| 405 |
-
this.initializeSaveSystem();
|
| 406 |
-
|
| 407 |
-
// Marcar como inicializado
|
| 408 |
-
this.engineState.isInitialized = true;
|
| 409 |
-
this.engineState.isRunning = true;
|
| 410 |
-
|
| 411 |
-
// Iniciar loop principal
|
| 412 |
-
this.startMainLoop();
|
| 413 |
-
|
| 414 |
-
console.log('✅ RETRO LEGENDS: Ultimate Engine inicializado correctamente');
|
| 415 |
-
|
| 416 |
-
// Disparar evento de inicialización
|
| 417 |
-
this.dispatchEvent('ENGINE_INITIALIZED', { timestamp: Date.now() });
|
| 418 |
-
|
| 419 |
-
} catch (error) {
|
| 420 |
-
console.error('❌ Error inicializando el motor:', error);
|
| 421 |
-
throw error;
|
| 422 |
-
}
|
| 423 |
-
}
|
| 424 |
-
|
| 425 |
-
setupCanvas() {
|
| 426 |
-
// Configurar tamaño responsivo
|
| 427 |
-
this.resizeCanvas();
|
| 428 |
-
window.addEventListener('resize', () => this.resizeCanvas());
|
| 429 |
-
|
| 430 |
-
// Configurar contexto para renderizado pixelado
|
| 431 |
-
this.ctx.imageSmoothingEnabled = false;
|
| 432 |
-
this.ctx.webkitImageSmoothingEnabled = false;
|
| 433 |
-
this.ctx.mozImageSmoothingEnabled = false;
|
| 434 |
-
this.ctx.msImageSmoothingEnabled = false;
|
| 435 |
-
|
| 436 |
-
// Configurar filtros de renderizado
|
| 437 |
-
this.ctx.filter = 'contrast(1.1) saturate(1.2) brightness(1.05)';
|
| 438 |
-
|
| 439 |
-
console.log('🖥️ Canvas configurado:', this.canvas.width, 'x', this.canvas.height);
|
| 440 |
-
}
|
| 441 |
-
|
| 442 |
-
resizeCanvas() {
|
| 443 |
-
const container = this.canvas.parentElement;
|
| 444 |
-
const rect = container.getBoundingClientRect();
|
| 445 |
-
|
| 446 |
-
// Configurar tamaño manteniendo aspect ratio 16:9
|
| 447 |
-
const aspectRatio = 16 / 9;
|
| 448 |
-
let width = rect.width;
|
| 449 |
-
let height = rect.height;
|
| 450 |
-
|
| 451 |
-
if (width / height > aspectRatio) {
|
| 452 |
-
width = height * aspectRatio;
|
| 453 |
-
} else {
|
| 454 |
-
height = width / aspectRatio;
|
| 455 |
-
}
|
| 456 |
-
|
| 457 |
-
this.canvas.width = width;
|
| 458 |
-
this.canvas.height = height;
|
| 459 |
-
|
| 460 |
-
// Actualizar bounds de cámara
|
| 461 |
-
this.camera.bounds.right = width * 2;
|
| 462 |
-
this.camera.bounds.bottom = height * 1.5;
|
| 463 |
-
}
|
| 464 |
-
|
| 465 |
-
async initializeSystems() {
|
| 466 |
-
console.log('🔧 Inicializando sistemas del motor...');
|
| 467 |
-
|
| 468 |
-
// Sistema de input avanzado
|
| 469 |
-
this.systems.input = new AdvancedInputHandler(this);
|
| 470 |
-
|
| 471 |
-
// Sistema de físicas
|
| 472 |
-
this.systems.physics = new AdvancedPhysicsEngine(this);
|
| 473 |
-
|
| 474 |
-
// Sistema de renderizado
|
| 475 |
-
this.systems.rendering = new AdvancedRenderingSystem(this);
|
| 476 |
-
|
| 477 |
-
// Sistema de audio
|
| 478 |
-
this.systems.audio = new UltraAudioSystem(this);
|
| 479 |
-
await this.systems.audio.initialize();
|
| 480 |
-
|
| 481 |
-
// Sistema de partículas
|
| 482 |
-
this.systems.particles = new AdvancedParticleSystem(this);
|
| 483 |
-
|
| 484 |
-
// Sistema de entidades
|
| 485 |
-
this.systems.entities = new UltraEntityManager(this);
|
| 486 |
-
|
| 487 |
-
// Sistema de niveles
|
| 488 |
-
this.systems.levels = new ProceduralLevelGenerator(this);
|
| 489 |
-
|
| 490 |
-
// Sistema de IA
|
| 491 |
-
this.systems.ai = new AdvancedAICompanion(this);
|
| 492 |
-
|
| 493 |
-
// Sistema de guardado
|
| 494 |
-
this.systems.save = new AdvancedSaveSystem(this);
|
| 495 |
-
|
| 496 |
-
// Sistema de logros
|
| 497 |
-
this.systems.achievements = new AchievementSystem(this);
|
| 498 |
-
|
| 499 |
-
// Sistema de analíticas
|
| 500 |
-
this.systems.analytics = new GameAnalytics(this);
|
| 501 |
-
|
| 502 |
-
console.log('✅ Todos los sistemas inicializados');
|
| 503 |
-
}
|
| 504 |
-
|
| 505 |
-
async loadResources() {
|
| 506 |
-
console.log('📦 Cargando recursos del juego...');
|
| 507 |
-
|
| 508 |
-
// Cargar sprites y texturas
|
| 509 |
-
await this.loadSprites();
|
| 510 |
-
|
| 511 |
-
// Cargar sonidos
|
| 512 |
-
await this.loadAudio();
|
| 513 |
-
|
| 514 |
-
// Cargar datos de niveles
|
| 515 |
-
await this.loadLevelData();
|
| 516 |
-
|
| 517 |
-
// Cargar configuraciones de IA
|
| 518 |
-
await this.loadAIData();
|
| 519 |
-
|
| 520 |
-
console.log('✅ Recursos cargados correctamente');
|
| 521 |
-
}
|
| 522 |
-
|
| 523 |
-
async loadSprites() {
|
| 524 |
-
// Aquí cargaríamos sprites reales en una implementación completa
|
| 525 |
-
console.log('🎨 Sprites cargados (modo texto para demo)');
|
| 526 |
-
}
|
| 527 |
-
|
| 528 |
-
async loadAudio() {
|
| 529 |
-
// Inicializar contexto de audio
|
| 530 |
-
if (!this.audioSystem.context) {
|
| 531 |
-
this.audioSystem.context = new (window.AudioContext || window.webkitAudioContext)();
|
| 532 |
-
}
|
| 533 |
-
|
| 534 |
-
console.log('🎵 Sistema de audio inicializado');
|
| 535 |
-
}
|
| 536 |
-
|
| 537 |
-
async loadLevelData() {
|
| 538 |
-
// Cargar configuraciones de niveles
|
| 539 |
-
this.levelConfig.levelData.set('caminito_matrix', {
|
| 540 |
-
name: 'Caminito Matrix',
|
| 541 |
-
theme: 'cyberpunk_argentina',
|
| 542 |
-
size: { width: 2000, height: 800 },
|
| 543 |
-
spawnPoints: [{ x: 100, y: 400 }],
|
| 544 |
-
enemies: ['mantero_cyber', 'bondi_hologram', 'taxi_drone'],
|
| 545 |
-
collectibles: ['mate_digital', 'empanada_power', 'choripan_shield']
|
| 546 |
-
});
|
| 547 |
-
|
| 548 |
-
console.log('🗺️ Datos de niveles cargados');
|
| 549 |
-
}
|
| 550 |
-
|
| 551 |
-
async loadAIData() {
|
| 552 |
-
// Cargar base de conocimiento de la IA
|
| 553 |
-
this.aiCompanion.responseSystem.knowledgeBase.set('argentina', {
|
| 554 |
-
cultura: ['mate', 'asado', 'tango', 'futbol', 'Maradona'],
|
| 555 |
-
lugares: ['Buenos Aires', 'Córdoba', 'Mendoza', 'Bariloche'],
|
| 556 |
-
comidas: ['empanadas', 'choripan', 'milanesas', 'dulce de leche'],
|
| 557 |
-
expresiones: ['che', 'boludo', 'dale', 'bárbaro', 'copado']
|
| 558 |
-
});
|
| 559 |
-
|
| 560 |
-
console.log('🤖 Base de conocimiento de IA cargada');
|
| 561 |
-
}
|
| 562 |
-
|
| 563 |
-
async loadInitialLevel() {
|
| 564 |
-
console.log('🏗️ Cargando nivel inicial...');
|
| 565 |
-
|
| 566 |
-
// Cargar Caminito Matrix
|
| 567 |
-
await this.systems.levels.loadLevel('caminito_matrix');
|
| 568 |
-
|
| 569 |
-
// Posicionar jugador
|
| 570 |
-
this.player.x = 150;
|
| 571 |
-
this.player.y = 400;
|
| 572 |
-
|
| 573 |
-
// Configurar cámara
|
| 574 |
-
this.updateCamera();
|
| 575 |
-
|
| 576 |
-
console.log('✅ Nivel inicial cargado');
|
| 577 |
-
}
|
| 578 |
-
|
| 579 |
-
initializeAI() {
|
| 580 |
-
console.log('🧠 Inicializando IA compañero...');
|
| 581 |
-
|
| 582 |
-
// Configurar personalidad inicial
|
| 583 |
-
this.aiCompanion.mood = 'excited';
|
| 584 |
-
this.aiCompanion.relationship = 50;
|
| 585 |
-
|
| 586 |
-
// Mensaje de bienvenida
|
| 587 |
-
setTimeout(() => {
|
| 588 |
-
this.systems.ai.sendMessage(
|
| 589 |
-
"¡Ehhhh, pibe! ¡Bienvenido a la experiencia más nostálgica y avanzada de tu vida! " +
|
| 590 |
-
"Soy NEXUS, tu compañero argento con IA de última generación. " +
|
| 591 |
-
"¿Listos para romperla en este universo retro-futurista? ¡Dale que arrancamos! 🚀🇦🇷"
|
| 592 |
-
);
|
| 593 |
-
}, 2000);
|
| 594 |
-
|
| 595 |
-
console.log('✅ IA compañero inicializada');
|
| 596 |
-
}
|
| 597 |
-
|
| 598 |
-
initializeEventSystem() {
|
| 599 |
-
console.log('📡 Inicializando sistema de eventos...');
|
| 600 |
-
|
| 601 |
-
// Configurar listeners principales
|
| 602 |
-
this.addEventListener('PLAYER_MOVE', (data) => {
|
| 603 |
-
this.systems.ai.onPlayerMove(data);
|
| 604 |
-
this.systems.analytics.trackEvent('player_movement', data);
|
| 605 |
-
});
|
| 606 |
-
|
| 607 |
-
this.addEventListener('PLAYER_JUMP', (data) => {
|
| 608 |
-
this.systems.ai.onPlayerJump(data);
|
| 609 |
-
this.systems.particles.createJumpEffect(data.x, data.y);
|
| 610 |
-
});
|
| 611 |
-
|
| 612 |
-
this.addEventListener('ITEM_COLLECT', (data) => {
|
| 613 |
-
this.systems.ai.onItemCollect(data);
|
| 614 |
-
this.updateScore(data.points);
|
| 615 |
-
});
|
| 616 |
-
|
| 617 |
-
console.log('✅ Sistema de eventos configurado');
|
| 618 |
-
}
|
| 619 |
-
|
| 620 |
-
initializeSaveSystem() {
|
| 621 |
-
console.log('💾 Inicializando sistema de guardado...');
|
| 622 |
-
|
| 623 |
-
// Cargar datos guardados si existen
|
| 624 |
-
this.systems.save.loadGame();
|
| 625 |
-
|
| 626 |
-
// Configurar auto-guardado cada 30 segundos
|
| 627 |
-
setInterval(() => {
|
| 628 |
-
this.systems.save.autoSave();
|
| 629 |
-
}, 30000);
|
| 630 |
-
|
| 631 |
-
console.log('✅ Sistema de guardado configurado');
|
| 632 |
-
}
|
| 633 |
-
|
| 634 |
-
// ===================================================================
|
| 635 |
-
// LOOP PRINCIPAL DEL JUEGO
|
| 636 |
-
// ===================================================================
|
| 637 |
-
|
| 638 |
-
startMainLoop() {
|
| 639 |
-
console.log('🔄 Iniciando loop principal del juego...');
|
| 640 |
-
this.engineState.lastFrameTime = performance.now();
|
| 641 |
-
this.mainLoop();
|
| 642 |
-
}
|
| 643 |
-
|
| 644 |
-
mainLoop() {
|
| 645 |
-
if (!this.engineState.isRunning) return;
|
| 646 |
-
|
| 647 |
-
// Calcular delta time
|
| 648 |
-
const currentTime = performance.now();
|
| 649 |
-
this.engineState.deltaTime = currentTime - this.engineState.lastFrameTime;
|
| 650 |
-
this.engineState.lastFrameTime = currentTime;
|
| 651 |
-
|
| 652 |
-
// Actualizar FPS
|
| 653 |
-
this.updateFPS();
|
| 654 |
-
|
| 655 |
-
// Verificar rendimiento y ajustar calidad si es necesario
|
| 656 |
-
this.checkPerformance();
|
| 657 |
-
|
| 658 |
-
// Actualizar solo si no está pausado
|
| 659 |
-
if (!this.engineState.isPaused) {
|
| 660 |
-
this.update(this.engineState.deltaTime);
|
| 661 |
-
}
|
| 662 |
-
|
| 663 |
-
// Renderizar siempre
|
| 664 |
-
this.render();
|
| 665 |
-
|
| 666 |
-
// Continuar el loop
|
| 667 |
-
requestAnimationFrame(() => this.mainLoop());
|
| 668 |
-
}
|
| 669 |
-
|
| 670 |
-
update(deltaTime) {
|
| 671 |
-
// Actualizar tiempo de juego
|
| 672 |
-
this.gameState.time += deltaTime;
|
| 673 |
-
|
| 674 |
-
// Actualizar sistemas principales
|
| 675 |
-
this.updatePlayer(deltaTime);
|
| 676 |
-
this.updateCamera(deltaTime);
|
| 677 |
-
this.updatePhysics(deltaTime);
|
| 678 |
-
|
| 679 |
-
// Actualizar sistemas secundarios
|
| 680 |
-
this.systems.entities.update(deltaTime);
|
| 681 |
-
this.systems.particles.update(deltaTime);
|
| 682 |
-
this.systems.levels.update(deltaTime);
|
| 683 |
-
this.systems.ai.update(deltaTime);
|
| 684 |
-
|
| 685 |
-
// Procesar eventos
|
| 686 |
-
this.processEvents();
|
| 687 |
-
|
| 688 |
-
// Verificar colisiones
|
| 689 |
-
this.checkCollisions();
|
| 690 |
-
|
| 691 |
-
// Actualizar UI
|
| 692 |
-
this.updateUI();
|
| 693 |
-
|
| 694 |
-
// Verificar condiciones de juego
|
| 695 |
-
this.checkGameConditions();
|
| 696 |
-
|
| 697 |
-
// Actualizar analíticas
|
| 698 |
-
this.systems.analytics.update(deltaTime);
|
| 699 |
-
}
|
| 700 |
-
|
| 701 |
-
updatePlayer(deltaTime) {
|
| 702 |
-
const player = this.player;
|
| 703 |
-
|
| 704 |
-
// Actualizar timers
|
| 705 |
-
this.updatePlayerTimers(deltaTime);
|
| 706 |
-
|
| 707 |
-
// Procesar input del jugador
|
| 708 |
-
this.systems.input.processPlayerInput(deltaTime);
|
| 709 |
-
|
| 710 |
-
// Aplicar física del jugador
|
| 711 |
-
this.applyPlayerPhysics(deltaTime);
|
| 712 |
-
|
| 713 |
-
// Actualizar animaciones
|
| 714 |
-
this.updatePlayerAnimation(deltaTime);
|
| 715 |
-
|
| 716 |
-
// Actualizar centro del jugador
|
| 717 |
-
player.centerX = player.x + player.width / 2;
|
| 718 |
-
player.centerY = player.y + player.height / 2;
|
| 719 |
-
|
| 720 |
-
// Verificar límites del mundo
|
| 721 |
-
this.checkWorldBounds();
|
| 722 |
-
|
| 723 |
-
// Actualizar sistema de combos
|
| 724 |
-
this.updateComboSystem(deltaTime);
|
| 725 |
-
}
|
| 726 |
-
|
| 727 |
-
updatePlayerTimers(deltaTime) {
|
| 728 |
-
const player = this.player;
|
| 729 |
-
|
| 730 |
-
// Timer de invulnerabilidad
|
| 731 |
-
if (player.invulnerabilityTimer > 0) {
|
| 732 |
-
player.invulnerabilityTimer -= deltaTime;
|
| 733 |
-
if (player.invulnerabilityTimer <= 0) {
|
| 734 |
-
player.isInvulnerable = false;
|
| 735 |
-
}
|
| 736 |
-
}
|
| 737 |
-
|
| 738 |
-
// Cooldown de dash
|
| 739 |
-
if (player.dashCooldown > 0) {
|
| 740 |
-
player.dashCooldown -= deltaTime;
|
| 741 |
-
if (player.dashCooldown <= 0) {
|
| 742 |
-
player.canDash = true;
|
| 743 |
-
}
|
| 744 |
-
}
|
| 745 |
-
|
| 746 |
-
// Cooldown de ataque
|
| 747 |
-
if (player.attackCooldown > 0) {
|
| 748 |
-
player.attackCooldown -= deltaTime;
|
| 749 |
-
if (player.attackCooldown <= 0) {
|
| 750 |
-
player.isAttacking = false;
|
| 751 |
-
}
|
| 752 |
-
}
|
| 753 |
-
|
| 754 |
-
// Timer de combo
|
| 755 |
-
if (player.comboSystem.comboTimer > 0) {
|
| 756 |
-
player.comboSystem.comboTimer -= deltaTime;
|
| 757 |
-
if (player.comboSystem.comboTimer <= 0) {
|
| 758 |
-
player.comboSystem.currentCombo = [];
|
| 759 |
-
}
|
| 760 |
-
}
|
| 761 |
-
}
|
| 762 |
-
|
| 763 |
-
applyPlayerPhysics(deltaTime) {
|
| 764 |
-
const player = this.player;
|
| 765 |
-
const physics = this.physics;
|
| 766 |
-
|
| 767 |
-
// Aplicar gravedad si no está en el suelo
|
| 768 |
-
if (!player.grounded) {
|
| 769 |
-
player.velocityY += physics.gravity;
|
| 770 |
-
if (player.velocityY > physics.terminalVelocity) {
|
| 771 |
-
player.velocityY = physics.terminalVelocity;
|
| 772 |
-
}
|
| 773 |
-
}
|
| 774 |
-
|
| 775 |
-
// Aplicar fricción/resistencia
|
| 776 |
-
if (player.grounded) {
|
| 777 |
-
player.velocityX *= physics.groundFriction;
|
| 778 |
-
} else {
|
| 779 |
-
player.velocityX *= physics.airResistance;
|
| 780 |
-
}
|
| 781 |
-
|
| 782 |
-
// Aplicar velocidades
|
| 783 |
-
player.x += player.velocityX;
|
| 784 |
-
player.y += player.velocityY;
|
| 785 |
-
|
| 786 |
-
// Verificar colisiones con terreno
|
| 787 |
-
this.checkTerrainCollisions();
|
| 788 |
-
}
|
| 789 |
-
|
| 790 |
-
updatePlayerAnimation(deltaTime) {
|
| 791 |
-
const player = this.player;
|
| 792 |
-
|
| 793 |
-
// Actualizar timer de animación
|
| 794 |
-
player.lastAnimationTime += deltaTime;
|
| 795 |
-
|
| 796 |
-
if (player.lastAnimationTime >= player.animationSpeed) {
|
| 797 |
-
player.lastAnimationTime = 0;
|
| 798 |
-
|
| 799 |
-
// Determinar sprite actual basado en estado
|
| 800 |
-
let spriteSet;
|
| 801 |
-
|
| 802 |
-
if (player.isDashing) {
|
| 803 |
-
spriteSet = player.spriteSet.dashing;
|
| 804 |
-
} else if (player.isAttacking) {
|
| 805 |
-
spriteSet = player.spriteSet.attacking;
|
| 806 |
-
} else if (player.isCharging) {
|
| 807 |
-
spriteSet = player.spriteSet.charging;
|
| 808 |
-
} else if (!player.grounded) {
|
| 809 |
-
spriteSet = player.spriteSet.jumping;
|
| 810 |
-
} else if (Math.abs(player.velocityX) > 0.5) {
|
| 811 |
-
spriteSet = player.spriteSet.running;
|
| 812 |
-
} else {
|
| 813 |
-
spriteSet = player.spriteSet.idle;
|
| 814 |
-
}
|
| 815 |
-
|
| 816 |
-
// Avanzar frame de animación
|
| 817 |
-
player.animationFrame = (player.animationFrame + 1) % spriteSet.length;
|
| 818 |
-
player.currentSprite = spriteSet[player.animationFrame];
|
| 819 |
-
}
|
| 820 |
-
}
|
| 821 |
-
|
| 822 |
-
updateCamera(deltaTime) {
|
| 823 |
-
const camera = this.camera;
|
| 824 |
-
const player = this.player;
|
| 825 |
-
|
| 826 |
-
// Calcular posición objetivo de la cámara
|
| 827 |
-
camera.targetX = player.centerX - this.canvas.width / 2;
|
| 828 |
-
camera.targetY = player.centerY - this.canvas.height / 2;
|
| 829 |
-
|
| 830 |
-
// Aplicar límites de cámara
|
| 831 |
-
camera.targetX = Math.max(camera.bounds.left,
|
| 832 |
-
Math.min(camera.bounds.right - this.canvas.width, camera.targetX));
|
| 833 |
-
camera.targetY = Math.max(camera.bounds.top,
|
| 834 |
-
Math.min(camera.bounds.bottom - this.canvas.height, camera.targetY));
|
| 835 |
-
|
| 836 |
-
// Interpolar suavemente hacia la posición objetivo
|
| 837 |
-
camera.x += (camera.targetX - camera.x) * camera.smoothing;
|
| 838 |
-
camera.y += (camera.targetY - camera.y) * camera.smoothing;
|
| 839 |
-
|
| 840 |
-
// Aplicar shake de cámara si está activo
|
| 841 |
-
if (camera.shake.duration > 0) {
|
| 842 |
-
camera.shake.duration -= deltaTime;
|
| 843 |
-
const intensity = camera.shake.intensity * (camera.shake.duration / 1000);
|
| 844 |
-
camera.shake.x = (Math.random() - 0.5) * intensity;
|
| 845 |
-
camera.shake.y = (Math.random() - 0.5) * intensity;
|
| 846 |
-
} else {
|
| 847 |
-
camera.shake.x = 0;
|
| 848 |
-
camera.shake.y = 0;
|
| 849 |
-
}
|
| 850 |
-
|
| 851 |
-
// Aplicar zoom suave
|
| 852 |
-
camera.zoom += (camera.targetZoom - camera.zoom) * 0.1;
|
| 853 |
-
}
|
| 854 |
-
|
| 855 |
-
updatePhysics(deltaTime) {
|
| 856 |
-
// Actualizar física del mundo
|
| 857 |
-
this.systems.physics.update(deltaTime);
|
| 858 |
-
}
|
| 859 |
-
|
| 860 |
-
checkCollisions() {
|
| 861 |
-
// Verificar colisiones jugador-entidades
|
| 862 |
-
const playerRect = {
|
| 863 |
-
x: this.player.x,
|
| 864 |
-
y: this.player.y,
|
| 865 |
-
width: this.player.width,
|
| 866 |
-
height: this.player.height
|
| 867 |
-
};
|
| 868 |
-
|
| 869 |
-
const entities = this.systems.entities.getActiveEntities();
|
| 870 |
-
|
| 871 |
-
entities.forEach((entity, index) => {
|
| 872 |
-
if (this.isColliding(playerRect, entity.getBounds())) {
|
| 873 |
-
this.handleCollision(entity, index);
|
| 874 |
-
}
|
| 875 |
-
});
|
| 876 |
-
}
|
| 877 |
-
|
| 878 |
-
isColliding(rect1, rect2) {
|
| 879 |
-
return rect1.x < rect2.x + rect2.width &&
|
| 880 |
-
rect1.x + rect1.width > rect2.x &&
|
| 881 |
-
rect1.y < rect2.y + rect2.height &&
|
| 882 |
-
rect1.y + rect1.height > rect2.y;
|
| 883 |
-
}
|
| 884 |
-
|
| 885 |
-
handleCollision(entity, index) {
|
| 886 |
-
if (this.player.isInvulnerable) return;
|
| 887 |
-
|
| 888 |
-
switch(entity.type) {
|
| 889 |
-
case 'enemy':
|
| 890 |
-
this.playerHit(entity);
|
| 891 |
-
break;
|
| 892 |
-
case 'collectible':
|
| 893 |
-
this.collectItem(entity, index);
|
| 894 |
-
break;
|
| 895 |
-
case 'powerup':
|
| 896 |
-
this.collectPowerUp(entity, index);
|
| 897 |
-
break;
|
| 898 |
-
case 'checkpoint':
|
| 899 |
-
this.activateCheckpoint(entity);
|
| 900 |
-
break;
|
| 901 |
-
}
|
| 902 |
-
}
|
| 903 |
-
|
| 904 |
-
playerHit(enemy) {
|
| 905 |
-
// Reducir vida
|
| 906 |
-
this.gameState.health -= enemy.damage || 25;
|
| 907 |
-
|
| 908 |
-
// Activar invulnerabilidad
|
| 909 |
-
this.player.isInvulnerable = true;
|
| 910 |
-
this.player.invulnerabilityTimer = 2000;
|
| 911 |
-
|
| 912 |
-
// Aplicar knockback
|
| 913 |
-
const knockbackDirection = this.player.x < enemy.x ? -1 : 1;
|
| 914 |
-
this.player.velocityX = knockbackDirection * 10;
|
| 915 |
-
this.player.velocityY = -8;
|
| 916 |
-
|
| 917 |
-
// Efectos visuales y sonoros
|
| 918 |
-
this.systems.particles.createHitEffect(this.player.centerX, this.player.centerY);
|
| 919 |
-
this.systems.audio.playSound('player_hit');
|
| 920 |
-
this.shakeCamera(300, 10);
|
| 921 |
-
|
| 922 |
-
// Reacción de la IA
|
| 923 |
-
this.systems.ai.onPlayerHit(enemy.type);
|
| 924 |
-
|
| 925 |
-
// Disparar evento
|
| 926 |
-
this.dispatchEvent('PLAYER_HIT', {
|
| 927 |
-
enemy: enemy.type,
|
| 928 |
-
damage: enemy.damage,
|
| 929 |
-
health: this.gameState.health
|
| 930 |
-
});
|
| 931 |
-
|
| 932 |
-
// Verificar muerte
|
| 933 |
-
if (this.gameState.health <= 0) {
|
| 934 |
-
this.playerDeath();
|
| 935 |
-
}
|
| 936 |
-
}
|
| 937 |
-
|
| 938 |
-
collectItem(item, index) {
|
| 939 |
-
// Añadir puntos
|
| 940 |
-
this.gameState.score += item.points || 100;
|
| 941 |
-
|
| 942 |
-
// Procesar tipo de item
|
| 943 |
-
switch(item.subtype) {
|
| 944 |
-
case 'mate':
|
| 945 |
-
this.gameState.mateCount++;
|
| 946 |
-
this.systems.ai.onMateCollected();
|
| 947 |
-
break;
|
| 948 |
-
case 'empanada':
|
| 949 |
-
this.gameState.health = Math.min(this.gameState.maxHealth, this.gameState.health + 25);
|
| 950 |
-
break;
|
| 951 |
-
case 'choripan':
|
| 952 |
-
this.gameState.energy = Math.min(this.gameState.maxEnergy, this.gameState.energy + 50);
|
| 953 |
-
break;
|
| 954 |
-
}
|
| 955 |
-
|
| 956 |
-
// Efectos
|
| 957 |
-
this.systems.particles.createCollectEffect(item.x, item.y, item.color);
|
| 958 |
-
this.systems.audio.playSound('item_collect');
|
| 959 |
-
|
| 960 |
-
// Remover item
|
| 961 |
-
this.systems.entities.removeEntity(index);
|
| 962 |
-
|
| 963 |
-
// Disparar evento
|
| 964 |
-
this.dispatchEvent('ITEM_COLLECT', {
|
| 965 |
-
type: item.subtype,
|
| 966 |
-
points: item.points,
|
| 967 |
-
position: { x: item.x, y: item.y }
|
| 968 |
-
});
|
| 969 |
-
}
|
| 970 |
-
|
| 971 |
-
updateComboSystem(deltaTime) {
|
| 972 |
-
const comboSystem = this.player.comboSystem;
|
| 973 |
-
|
| 974 |
-
// Verificar si hay combo activo
|
| 975 |
-
if (comboSystem.currentCombo.length > 0) {
|
| 976 |
-
// Verificar si se completó algún combo
|
| 977 |
-
comboSystem.availableCombos.forEach(combo => {
|
| 978 |
-
if (this.arraysEqual(comboSystem.currentCombo, combo.sequence)) {
|
| 979 |
-
this.executeCombo(combo);
|
| 980 |
-
comboSystem.currentCombo = [];
|
| 981 |
-
comboSystem.comboTimer = 0;
|
| 982 |
-
}
|
| 983 |
-
});
|
| 984 |
-
}
|
| 985 |
-
}
|
| 986 |
-
|
| 987 |
-
executeCombo(combo) {
|
| 988 |
-
console.log(`🔥 Combo ejecutado: ${combo.name} (${combo.power} poder)`);
|
| 989 |
-
|
| 990 |
-
// Aplicar efectos del combo
|
| 991 |
-
this.gameState.score += combo.power;
|
| 992 |
-
this.gameState.combo++;
|
| 993 |
-
|
| 994 |
-
// Efectos visuales espectaculares
|
| 995 |
-
this.systems.particles.createComboEffect(this.player.centerX, this.player.centerY, combo.name);
|
| 996 |
-
this.systems.audio.playSound('combo_success');
|
| 997 |
-
this.shakeCamera(500, 15);
|
| 998 |
-
|
| 999 |
-
// Reacción de la IA
|
| 1000 |
-
this.systems.ai.onComboExecuted(combo);
|
| 1001 |
-
|
| 1002 |
-
// Disparar evento
|
| 1003 |
-
this.dispatchEvent('COMBO_EXECUTED', { combo: combo.name, power: combo.power });
|
| 1004 |
-
}
|
| 1005 |
-
|
| 1006 |
-
// ===================================================================
|
| 1007 |
-
// MÉTODOS DE RENDERIZADO
|
| 1008 |
-
// ===================================================================
|
| 1009 |
-
|
| 1010 |
-
render() {
|
| 1011 |
-
// Limpiar canvas
|
| 1012 |
-
this.clearCanvas();
|
| 1013 |
-
|
| 1014 |
-
// Aplicar transformaciones de cámara
|
| 1015 |
-
this.ctx.save();
|
| 1016 |
-
this.applyCamera();
|
| 1017 |
-
|
| 1018 |
-
// Renderizar fondo
|
| 1019 |
-
this.renderBackground();
|
| 1020 |
-
|
| 1021 |
-
// Renderizar nivel
|
| 1022 |
-
this.systems.levels.render(this.ctx);
|
| 1023 |
-
|
| 1024 |
-
// Renderizar entidades
|
| 1025 |
-
this.systems.entities.render(this.ctx);
|
| 1026 |
-
|
| 1027 |
-
// Renderizar jugador
|
| 1028 |
-
this.renderPlayer();
|
| 1029 |
-
|
| 1030 |
-
// Renderizar partículas
|
| 1031 |
-
this.systems.particles.render(this.ctx);
|
| 1032 |
-
|
| 1033 |
-
// Renderizar efectos de primer plano
|
| 1034 |
-
this.renderForegroundEffects();
|
| 1035 |
-
|
| 1036 |
-
// Restaurar transformaciones
|
| 1037 |
-
this.ctx.restore();
|
| 1038 |
-
|
| 1039 |
-
// Renderizar UI (sin transformaciones de cámara)
|
| 1040 |
-
this.renderUI();
|
| 1041 |
-
|
| 1042 |
-
// Renderizar debug si está habilitado
|
| 1043 |
-
if (this.engineState.debugMode) {
|
| 1044 |
-
this.renderDebugInfo();
|
| 1045 |
-
}
|
| 1046 |
-
|
| 1047 |
-
// Actualizar métricas de rendimiento
|
| 1048 |
-
this.performance.metrics.drawCalls++;
|
| 1049 |
-
}
|
| 1050 |
-
|
| 1051 |
-
clearCanvas() {
|
| 1052 |
-
// Fondo degradado dinámico
|
| 1053 |
-
const gradient = this.ctx.createLinearGradient(0, 0, this.canvas.width, this.canvas.height);
|
| 1054 |
-
gradient.addColorStop(0, '#0a0a0a');
|
| 1055 |
-
gradient.addColorStop(0.5, '#1a1a2e');
|
| 1056 |
-
gradient.addColorStop(1, '#16213e');
|
| 1057 |
-
|
| 1058 |
-
this.ctx.fillStyle = gradient;
|
| 1059 |
-
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
| 1060 |
-
}
|
| 1061 |
-
|
| 1062 |
-
applyCamera() {
|
| 1063 |
-
// Aplicar zoom
|
| 1064 |
-
this.ctx.scale(this.camera.zoom, this.camera.zoom);
|
| 1065 |
-
|
| 1066 |
-
// Aplicar posición de cámara con shake
|
| 1067 |
-
this.ctx.translate(
|
| 1068 |
-
-this.camera.x + this.camera.shake.x,
|
| 1069 |
-
-this.camera.y + this.camera.shake.y
|
| 1070 |
-
);
|
| 1071 |
-
}
|
| 1072 |
-
|
| 1073 |
-
renderBackground() {
|
| 1074 |
-
// Renderizar fondo parallax del nivel actual
|
| 1075 |
-
this.systems.levels.renderBackground(this.ctx, this.camera);
|
| 1076 |
-
}
|
| 1077 |
-
|
| 1078 |
-
renderPlayer() {
|
| 1079 |
-
const player = this.player;
|
| 1080 |
-
|
| 1081 |
-
// Efecto de parpadeo si es invulnerable
|
| 1082 |
-
if (player.isInvulnerable && Math.floor(this.gameState.time / 100) % 2) {
|
| 1083 |
-
this.ctx.globalAlpha = 0.5;
|
| 1084 |
-
}
|
| 1085 |
-
|
| 1086 |
-
// Configurar renderizado de texto
|
| 1087 |
-
this.ctx.font = '32px Arial';
|
| 1088 |
-
this.ctx.textAlign = 'center';
|
| 1089 |
-
this.ctx.textBaseline = 'bottom';
|
| 1090 |
-
|
| 1091 |
-
// Renderizar sprite del jugador
|
| 1092 |
-
this.ctx.fillStyle = '#ffffff';
|
| 1093 |
-
this.ctx.fillText(
|
| 1094 |
-
player.currentSprite,
|
| 1095 |
-
player.centerX,
|
| 1096 |
-
player.y + player.height
|
| 1097 |
-
);
|
| 1098 |
-
|
| 1099 |
-
// Efectos especiales según estado
|
| 1100 |
-
if (player.isDashing) {
|
| 1101 |
-
this.renderDashEffect();
|
| 1102 |
-
}
|
| 1103 |
-
|
| 1104 |
-
if (player.isCharging) {
|
| 1105 |
-
this.renderChargeEffect();
|
| 1106 |
-
}
|
| 1107 |
-
|
| 1108 |
-
// Restaurar alpha
|
| 1109 |
-
this.ctx.globalAlpha = 1.0;
|
| 1110 |
-
|
| 1111 |
-
// Renderizar barra de vida si está dañado
|
| 1112 |
-
if (this.gameState.health < this.gameState.maxHealth) {
|
| 1113 |
-
this.renderPlayerHealthBar();
|
| 1114 |
-
}
|
| 1115 |
-
}
|
| 1116 |
-
|
| 1117 |
-
renderDashEffect() {
|
| 1118 |
-
const player = this.player;
|
| 1119 |
-
|
| 1120 |
-
// Crear trail de dash
|
| 1121 |
-
this.ctx.strokeStyle = '#00ffff';
|
| 1122 |
-
this.ctx.lineWidth = 3;
|
| 1123 |
-
this.ctx.globalAlpha = 0.7;
|
| 1124 |
-
|
| 1125 |
-
this.ctx.beginPath();
|
| 1126 |
-
this.ctx.moveTo(player.x - 20, player.centerY);
|
| 1127 |
-
this.ctx.lineTo(player.x + player.width + 20, player.centerY);
|
| 1128 |
-
this.ctx.stroke();
|
| 1129 |
-
|
| 1130 |
-
this.ctx.globalAlpha = 1.0;
|
| 1131 |
-
}
|
| 1132 |
-
|
| 1133 |
-
renderChargeEffect() {
|
| 1134 |
-
const player = this.player;
|
| 1135 |
-
const time = this.gameState.time;
|
| 1136 |
-
|
| 1137 |
-
// Efecto de energía cargándose
|
| 1138 |
-
this.ctx.strokeStyle = '#ffff00';
|
| 1139 |
-
this.ctx.lineWidth = 2;
|
| 1140 |
-
this.ctx.globalAlpha = 0.8;
|
| 1141 |
-
|
| 1142 |
-
const radius = 40 + Math.sin(time * 0.01) * 10;
|
| 1143 |
-
|
| 1144 |
-
this.ctx.beginPath();
|
| 1145 |
-
this.ctx.arc(player.centerX, player.centerY, radius, 0, Math.PI * 2);
|
| 1146 |
-
this.ctx.stroke();
|
| 1147 |
-
|
| 1148 |
-
this.ctx.globalAlpha = 1.0;
|
| 1149 |
-
}
|
| 1150 |
-
|
| 1151 |
-
renderPlayerHealthBar() {
|
| 1152 |
-
const player = this.player;
|
| 1153 |
-
const barWidth = 40;
|
| 1154 |
-
const barHeight = 6;
|
| 1155 |
-
const x = player.centerX - barWidth / 2;
|
| 1156 |
-
const y = player.y - 15;
|
| 1157 |
-
|
| 1158 |
-
// Fondo de la barra
|
| 1159 |
-
this.ctx.fillStyle = '#ff0000';
|
| 1160 |
-
this.ctx.fillRect(x, y, barWidth, barHeight);
|
| 1161 |
-
|
| 1162 |
-
// Barra de vida
|
| 1163 |
-
const healthPercent = this.gameState.health / this.gameState.maxHealth;
|
| 1164 |
-
this.ctx.fillStyle = '#00ff00';
|
| 1165 |
-
this.ctx.fillRect(x, y, barWidth * healthPercent, barHeight);
|
| 1166 |
-
|
| 1167 |
-
// Borde
|
| 1168 |
-
this.ctx.strokeStyle = '#ffffff';
|
| 1169 |
-
this.ctx.lineWidth = 1;
|
| 1170 |
-
this.ctx.strokeRect(x, y, barWidth, barHeight);
|
| 1171 |
-
}
|
| 1172 |
-
|
| 1173 |
-
renderForegroundEffects() {
|
| 1174 |
-
// Efectos de primer plano como lluvia, nieve, etc.
|
| 1175 |
-
if (this.particleSystem.effects.weatherEffects.enabled) {
|
| 1176 |
-
this.renderWeatherEffects();
|
| 1177 |
-
}
|
| 1178 |
-
|
| 1179 |
-
// Efectos de pantalla como vignette
|
| 1180 |
-
if (this.camera.effects.vignette) {
|
| 1181 |
-
this.renderVignette();
|
| 1182 |
-
}
|
| 1183 |
-
}
|
| 1184 |
-
|
| 1185 |
-
renderWeatherEffects() {
|
| 1186 |
-
// Implementar efectos climáticos
|
| 1187 |
-
}
|
| 1188 |
-
|
| 1189 |
-
renderVignette() {
|
| 1190 |
-
const gradient = this.ctx.createRadialGradient(
|
| 1191 |
-
this.canvas.width / 2, this.canvas.height / 2, 0,
|
| 1192 |
-
this.canvas.width / 2, this.canvas.height / 2, this.canvas.width / 2
|
| 1193 |
-
);
|
| 1194 |
-
gradient.addColorStop(0, 'rgba(0,0,0,0)');
|
| 1195 |
-
gradient.addColorStop(1, 'rgba(0,0,0,0.5)');
|
| 1196 |
-
|
| 1197 |
-
this.ctx.fillStyle = gradient;
|
| 1198 |
-
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
| 1199 |
-
}
|
| 1200 |
-
|
| 1201 |
-
renderUI() {
|
| 1202 |
-
// La UI se renderiza en el HTML, pero aquí podríamos añadir overlays
|
| 1203 |
-
}
|
| 1204 |
-
|
| 1205 |
-
renderDebugInfo() {
|
| 1206 |
-
this.ctx.fillStyle = '#00ff00';
|
| 1207 |
-
this.ctx.font = '12px monospace';
|
| 1208 |
-
this.ctx.textAlign = 'left';
|
| 1209 |
-
|
| 1210 |
-
const debugInfo = [
|
| 1211 |
-
`FPS: ${this.engineState.averageFPS.toFixed(1)}`,
|
| 1212 |
-
`Delta: ${this.engineState.deltaTime.toFixed(2)}ms`,
|
| 1213 |
-
`Player: (${this.player.x.toFixed(0)}, ${this.player.y.toFixed(0)})`,
|
| 1214 |
-
`Velocity: (${this.player.velocityX.toFixed(2)}, ${this.player.velocityY.toFixed(2)})`,
|
| 1215 |
-
`Camera: (${this.camera.x.toFixed(0)}, ${this.camera.y.toFixed(0)})`,
|
| 1216 |
-
`Entities: ${this.systems.entities.getEntityCount()}`,
|
| 1217 |
-
`Particles: ${this.systems.particles.getParticleCount()}`
|
| 1218 |
-
];
|
| 1219 |
-
|
| 1220 |
-
debugInfo.forEach((line, index) => {
|
| 1221 |
-
this.ctx.fillText(line, 10, 20 + index * 15);
|
| 1222 |
-
});
|
| 1223 |
-
}
|
| 1224 |
-
|
| 1225 |
-
// ===================================================================
|
| 1226 |
-
// MÉTODOS AUXILIARES
|
| 1227 |
-
// ===================================================================
|
| 1228 |
-
|
| 1229 |
-
updateFPS() {
|
| 1230 |
-
this.engineState.frameCount++;
|
| 1231 |
-
|
| 1232 |
-
if (this.engineState.frameCount % 60 === 0) {
|
| 1233 |
-
this.engineState.averageFPS = 1000 / this.engineState.deltaTime;
|
| 1234 |
-
}
|
| 1235 |
-
}
|
| 1236 |
-
|
| 1237 |
-
checkPerformance() {
|
| 1238 |
-
// Ajustar calidad automáticamente si el rendimiento es bajo
|
| 1239 |
-
if (this.performance.adaptiveQuality && this.engineState.averageFPS < 45) {
|
| 1240 |
-
this.adjustQuality('down');
|
| 1241 |
-
} else if (this.performance.adaptiveQuality && this.engineState.averageFPS > 55) {
|
| 1242 |
-
this.adjustQuality('up');
|
| 1243 |
-
}
|
| 1244 |
-
}
|
| 1245 |
-
|
| 1246 |
-
adjustQuality(direction) {
|
| 1247 |
-
// Implementar ajuste automático de calidad
|
| 1248 |
-
console.log(`🔧 Ajustando calidad: ${direction}`);
|
| 1249 |
-
}
|
| 1250 |
-
|
| 1251 |
-
processEvents() {
|
| 1252 |
-
while (this.eventSystem.queue.length > 0) {
|
| 1253 |
-
const event = this.eventSystem.queue.shift();
|
| 1254 |
-
this.handleEvent(event);
|
| 1255 |
-
}
|
| 1256 |
-
}
|
| 1257 |
-
|
| 1258 |
-
handleEvent(event) {
|
| 1259 |
-
const listeners = this.eventSystem.listeners.get(event.type);
|
| 1260 |
-
if (listeners) {
|
| 1261 |
-
listeners.forEach(listener => listener(event.data));
|
| 1262 |
-
}
|
| 1263 |
-
}
|
| 1264 |
-
|
| 1265 |
-
addEventListener(type, listener) {
|
| 1266 |
-
if (!this.eventSystem.listeners.has(type)) {
|
| 1267 |
-
this.eventSystem.listeners.set(type, []);
|
| 1268 |
-
}
|
| 1269 |
-
this.eventSystem.listeners.get(type).push(listener);
|
| 1270 |
-
}
|
| 1271 |
-
|
| 1272 |
-
dispatchEvent(type, data) {
|
| 1273 |
-
this.eventSystem.queue.push({ type, data, timestamp: Date.now() });
|
| 1274 |
-
}
|
| 1275 |
-
|
| 1276 |
-
shakeCamera(duration, intensity) {
|
| 1277 |
-
this.camera.shake.duration = duration;
|
| 1278 |
-
this.camera.shake.intensity = intensity;
|
| 1279 |
-
}
|
| 1280 |
-
|
| 1281 |
-
updateUI() {
|
| 1282 |
-
// Actualizar elementos de UI
|
| 1283 |
-
document.getElementById('gameScore').textContent = this.gameState.score.toLocaleString();
|
| 1284 |
-
document.getElementById('playerHealth').textContent = Math.max(0, this.gameState.health);
|
| 1285 |
-
document.getElementById('mateCount').textContent = this.gameState.mateCount;
|
| 1286 |
-
document.getElementById('currentLevel').textContent = this.levelConfig.currentLevel;
|
| 1287 |
-
document.getElementById('comboCount').textContent = this.gameState.combo;
|
| 1288 |
-
}
|
| 1289 |
-
|
| 1290 |
-
checkGameConditions() {
|
| 1291 |
-
// Verificar condiciones de victoria/derrota
|
| 1292 |
-
if (this.gameState.health <= 0 && this.gameState.lives <= 0) {
|
| 1293 |
-
this.gameOver();
|
| 1294 |
-
}
|
| 1295 |
-
|
| 1296 |
-
// Verificar completado de nivel
|
| 1297 |
-
if (this.systems.levels.isLevelComplete()) {
|
| 1298 |
-
this.completeLevel();
|
| 1299 |
-
}
|
| 1300 |
-
}
|
| 1301 |
-
|
| 1302 |
-
checkWorldBounds() {
|
| 1303 |
-
const player = this.player;
|
| 1304 |
-
|
| 1305 |
-
// Límites horizontales
|
| 1306 |
-
if (player.x < 0) {
|
| 1307 |
-
player.x = 0;
|
| 1308 |
-
player.velocityX = 0;
|
| 1309 |
-
}
|
| 1310 |
-
|
| 1311 |
-
// Límite inferior (muerte por caída)
|
| 1312 |
-
if (player.y > this.canvas.height + 200) {
|
| 1313 |
-
this.playerDeath('fall');
|
| 1314 |
-
}
|
| 1315 |
-
}
|
| 1316 |
-
|
| 1317 |
-
checkTerrainCollisions() {
|
| 1318 |
-
const player = this.player;
|
| 1319 |
-
const groundY = this.canvas.height - 80; // Altura del suelo base
|
| 1320 |
-
|
| 1321 |
-
// Colisión con el suelo
|
| 1322 |
-
if (player.y + player.height >= groundY) {
|
| 1323 |
-
player.y = groundY - player.height;
|
| 1324 |
-
player.velocityY = 0;
|
| 1325 |
-
|
| 1326 |
-
if (!player.grounded) {
|
| 1327 |
-
player.grounded = true;
|
| 1328 |
-
player.canDoubleJump = true;
|
| 1329 |
-
this.systems.particles.createLandingEffect(player.centerX, player.y + player.height);
|
| 1330 |
-
this.systems.ai.onPlayerLanding();
|
| 1331 |
-
}
|
| 1332 |
-
} else {
|
| 1333 |
-
player.grounded = false;
|
| 1334 |
-
}
|
| 1335 |
-
}
|
| 1336 |
-
|
| 1337 |
-
playerDeath(cause = 'unknown') {
|
| 1338 |
-
console.log(`💀 Jugador murió por: ${cause}`);
|
| 1339 |
-
|
| 1340 |
-
// Reducir vidas
|
| 1341 |
-
this.gameState.lives--;
|
| 1342 |
-
|
| 1343 |
-
// Efectos de muerte
|
| 1344 |
-
this.systems.particles.createDeathEffect(this.player.centerX, this.player.centerY);
|
| 1345 |
-
this.systems.audio.playSound('player_death');
|
| 1346 |
-
this.shakeCamera(1000, 20);
|
| 1347 |
-
|
| 1348 |
-
// Reacción de la IA
|
| 1349 |
-
this.systems.ai.onPlayerDeath(cause);
|
| 1350 |
-
|
| 1351 |
-
// Resetear jugador
|
| 1352 |
-
this.respawnPlayer();
|
| 1353 |
-
|
| 1354 |
-
// Disparar evento
|
| 1355 |
-
this.dispatchEvent('PLAYER_DEATH', { cause, lives: this.gameState.lives });
|
| 1356 |
-
}
|
| 1357 |
-
|
| 1358 |
-
respawnPlayer() {
|
| 1359 |
-
// Resetear posición y estado del jugador
|
| 1360 |
-
this.player.x = 150;
|
| 1361 |
-
this.player.y = 400;
|
| 1362 |
-
this.player.velocityX = 0;
|
| 1363 |
-
this.player.velocityY = 0;
|
| 1364 |
-
this.gameState.health = this.gameState.maxHealth;
|
| 1365 |
-
this.player.isInvulnerable = true;
|
| 1366 |
-
this.player.invulnerabilityTimer = 3000;
|
| 1367 |
-
|
| 1368 |
-
console.log('🔄 Jugador respawneado');
|
| 1369 |
-
}
|
| 1370 |
-
|
| 1371 |
-
gameOver() {
|
| 1372 |
-
this.engineState.isRunning = false;
|
| 1373 |
-
console.log('💀 GAME OVER');
|
| 1374 |
-
|
| 1375 |
-
// Mostrar pantalla de game over
|
| 1376 |
-
this.systems.ai.onGameOver();
|
| 1377 |
-
|
| 1378 |
-
// Guardar estadísticas finales
|
| 1379 |
-
this.systems.save.saveGameOverStats();
|
| 1380 |
-
}
|
| 1381 |
-
|
| 1382 |
-
completeLevel() {
|
| 1383 |
-
console.log('🏆 Nivel completado');
|
| 1384 |
-
|
| 1385 |
-
// Bonificación por completar nivel
|
| 1386 |
-
this.gameState.score += 5000;
|
| 1387 |
-
|
| 1388 |
-
// Reacción de la IA
|
| 1389 |
-
this.systems.ai.onLevelComplete();
|
| 1390 |
-
|
| 1391 |
-
// Cargar siguiente nivel
|
| 1392 |
-
this.loadNextLevel();
|
| 1393 |
-
}
|
| 1394 |
-
|
| 1395 |
-
loadNextLevel() {
|
| 1396 |
-
// Implementar carga del siguiente nivel
|
| 1397 |
-
console.log('🗺️ Cargando siguiente nivel...');
|
| 1398 |
-
}
|
| 1399 |
-
|
| 1400 |
-
arraysEqual(a, b) {
|
| 1401 |
-
return a.length === b.length && a.every((val, i) => val === b[i]);
|
| 1402 |
-
}
|
| 1403 |
-
|
| 1404 |
-
// ===================================================================
|
| 1405 |
-
// MÉTODOS PÚBLICOS PARA CONTROLES
|
| 1406 |
-
// ===================================================================
|
| 1407 |
-
|
| 1408 |
-
jump() {
|
| 1409 |
-
const player = this.player;
|
| 1410 |
-
|
| 1411 |
-
if (player.grounded) {
|
| 1412 |
-
player.velocityY = -player.jumpPower;
|
| 1413 |
-
player.grounded = false;
|
| 1414 |
-
this.systems.audio.playSound('jump');
|
| 1415 |
-
this.systems.particles.createJumpEffect(player.centerX, player.y + player.height);
|
| 1416 |
-
this.dispatchEvent('PLAYER_JUMP', { x: player.centerX, y: player.centerY });
|
| 1417 |
-
} else if (player.canDoubleJump) {
|
| 1418 |
-
player.velocityY = -player.doubleJumpPower;
|
| 1419 |
-
player.canDoubleJump = false;
|
| 1420 |
-
this.systems.audio.playSound('double_jump');
|
| 1421 |
-
this.systems.particles.createDoubleJumpEffect(player.centerX, player.centerY);
|
| 1422 |
-
}
|
| 1423 |
-
}
|
| 1424 |
-
|
| 1425 |
-
dash() {
|
| 1426 |
-
const player = this.player;
|
| 1427 |
-
|
| 1428 |
-
if (player.canDash && !player.isDashing) {
|
| 1429 |
-
const direction = player.facing === 'right' ? 1 : -1;
|
| 1430 |
-
player.velocityX = direction * player.dashPower;
|
| 1431 |
-
player.isDashing = true;
|
| 1432 |
-
player.canDash = false;
|
| 1433 |
-
player.dashCooldown = 1000;
|
| 1434 |
-
|
| 1435 |
-
this.systems.audio.playSound('dash');
|
| 1436 |
-
this.systems.particles.createDashEffect(player.centerX, player.centerY, direction);
|
| 1437 |
-
|
| 1438 |
-
// El dash dura 200ms
|
| 1439 |
-
setTimeout(() => {
|
| 1440 |
-
player.isDashing = false;
|
| 1441 |
-
}, 200);
|
| 1442 |
-
}
|
| 1443 |
-
}
|
| 1444 |
-
|
| 1445 |
-
attack() {
|
| 1446 |
-
const player = this.player;
|
| 1447 |
-
|
| 1448 |
-
if (!player.isAttacking && player.attackCooldown <= 0) {
|
| 1449 |
-
player.isAttacking = true;
|
| 1450 |
-
player.attackCooldown = 500;
|
| 1451 |
-
|
| 1452 |
-
this.systems.audio.playSound('attack');
|
| 1453 |
-
this.systems.particles.createAttackEffect(player.centerX, player.centerY, player.facing);
|
| 1454 |
-
|
| 1455 |
-
// Verificar enemigos en rango
|
| 1456 |
-
this.checkAttackHits();
|
| 1457 |
-
}
|
| 1458 |
-
}
|
| 1459 |
-
|
| 1460 |
-
checkAttackHits() {
|
| 1461 |
-
const player = this.player;
|
| 1462 |
-
const attackRange = 50;
|
| 1463 |
-
const attackRect = {
|
| 1464 |
-
x: player.facing === 'right' ? player.x + player.width : player.x - attackRange,
|
| 1465 |
-
y: player.y,
|
| 1466 |
-
width: attackRange,
|
| 1467 |
-
height: player.height
|
| 1468 |
-
};
|
| 1469 |
-
|
| 1470 |
-
const entities = this.systems.entities.getActiveEntities();
|
| 1471 |
-
entities.forEach((entity, index) => {
|
| 1472 |
-
if (entity.type === 'enemy' && this.isColliding(attackRect, entity.getBounds())) {
|
| 1473 |
-
this.hitEnemy(entity, index);
|
| 1474 |
-
}
|
| 1475 |
-
});
|
| 1476 |
-
}
|
| 1477 |
-
|
| 1478 |
-
hitEnemy(enemy, index) {
|
| 1479 |
-
// Dañar enemigo
|
| 1480 |
-
enemy.takeDamage(player.stats.strength);
|
| 1481 |
-
|
| 1482 |
-
// Efectos
|
| 1483 |
-
this.systems.particles.createEnemyHitEffect(enemy.x, enemy.y);
|
| 1484 |
-
this.systems.audio.playSound('enemy_hit');
|
| 1485 |
-
|
| 1486 |
-
// Puntos
|
| 1487 |
-
this.gameState.score += 50;
|
| 1488 |
-
|
| 1489 |
-
// Si el enemigo muere
|
| 1490 |
-
if (enemy.health <= 0) {
|
| 1491 |
-
this.systems.entities.removeEntity(index);
|
| 1492 |
-
this.gameState.score += enemy.killScore || 100;
|
| 1493 |
-
this.systems.particles.createEnemyDeathEffect(enemy.x, enemy.y);
|
| 1494 |
-
}
|
| 1495 |
-
}
|
| 1496 |
-
|
| 1497 |
-
useMate() {
|
| 1498 |
-
if (this.gameState.mateCount > 0) {
|
| 1499 |
-
this.gameState.mateCount--;
|
| 1500 |
-
this.gameState.health = Math.min(this.gameState.maxHealth, this.gameState.health + 50);
|
| 1501 |
-
this.gameState.energy = this.gameState.maxEnergy;
|
| 1502 |
-
|
| 1503 |
-
this.systems.audio.playSound('mate_use');
|
| 1504 |
-
this.systems.particles.createMateEffect(this.player.centerX, this.player.centerY);
|
| 1505 |
-
this.systems.ai.onMateUsed();
|
| 1506 |
-
|
| 1507 |
-
console.log('🧉 Mate usado - Vida y energía restauradas');
|
| 1508 |
-
}
|
| 1509 |
-
}
|
| 1510 |
-
|
| 1511 |
-
togglePause() {
|
| 1512 |
-
this.engineState.isPaused = !this.engineState.isPaused;
|
| 1513 |
-
|
| 1514 |
-
if (this.engineState.isPaused) {
|
| 1515 |
-
this.systems.audio.pauseAll();
|
| 1516 |
-
this.systems.ai.onGamePaused();
|
| 1517 |
-
} else {
|
| 1518 |
-
this.systems.audio.resumeAll();
|
| 1519 |
-
this.systems.ai.onGameResumed();
|
| 1520 |
-
}
|
| 1521 |
-
|
| 1522 |
-
console.log(`⏸️ Juego ${this.engineState.isPaused ? 'pausado' : 'reanudado'}`);
|
| 1523 |
-
}
|
| 1524 |
-
|
| 1525 |
-
toggleDebug() {
|
| 1526 |
-
this.engineState.debugMode = !this.engineState.debugMode;
|
| 1527 |
-
console.log(`🐛 Modo debug: ${this.engineState.debugMode ? 'ON' : 'OFF'}`);
|
| 1528 |
-
}
|
| 1529 |
-
|
| 1530 |
-
// ===================================================================
|
| 1531 |
-
// GETTERS PÚBLICOS
|
| 1532 |
-
// ===================================================================
|
| 1533 |
-
|
| 1534 |
-
getPlayer() { return this.player; }
|
| 1535 |
-
getGameState() { return this.gameState; }
|
| 1536 |
-
getCamera() { return this.camera; }
|
| 1537 |
-
getCanvas() { return this.canvas; }
|
| 1538 |
-
getContext() { return this.ctx; }
|
| 1539 |
-
getSystems() { return this.systems; }
|
| 1540 |
-
getPerformanceMetrics() { return this.performance.metrics; }
|
| 1541 |
-
}
|
| 1542 |
-
|
| 1543 |
-
// ===================================================================
|
| 1544 |
-
// EXPORTAR PARA USO GLOBAL
|
| 1545 |
-
// ===================================================================
|
| 1546 |
-
|
| 1547 |
-
window.RetroLegendsUltimateEngine = RetroLegendsUltimateEngine;
|
| 1548 |
-
|
| 1549 |
-
console.log('🚀 Core Engine Ultra cargado correctamente');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|