Lukeetah commited on
Commit
b65e007
·
verified ·
1 Parent(s): a8a4a10

Delete static

Browse files
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');