diff --git a/frontend/src/views/minigames/Match3Game.vue b/frontend/src/views/minigames/Match3Game.vue index e4bd821..22d4fca 100644 --- a/frontend/src/views/minigames/Match3Game.vue +++ b/frontend/src/views/minigames/Match3Game.vue @@ -472,9 +472,9 @@ export default { // Nach dem Laden der Kampagne, versuche das Level zu finden const levelData = this.campaignData.levels.find(l => l.order === levelOrder); if (levelData) { - return this.loadLevelDataInternal(levelData).then(() => { + return this.loadLevelDataInternal(levelData).then(async () => { // WICHTIG: Nach dem Laden der Level-Daten, initialisiere das Level - this.initializeLevel(); + await this.initializeLevel(); }); } else { throw new Error(`Level ${levelOrder} nicht in Kampagnendaten gefunden`); @@ -485,23 +485,23 @@ export default { const levelData = this.campaignData.levels.find(l => l.order === levelOrder); if (!levelData) { // KEINE REKURSION: Lade Kampagne nur einmal - return this.loadCampaignData().then(() => { + return this.loadCampaignData().then(async () => { const retryLevelData = this.campaignData.levels.find(l => l.order === levelOrder); if (!retryLevelData) { throw new Error(`Level ${levelOrder} nicht gefunden`); } // Verwende die gefundenen Daten direkt, ohne Rekursion - return this.loadLevelDataInternal(retryLevelData).then(() => { + return this.loadLevelDataInternal(retryLevelData).then(async () => { // WICHTIG: Nach dem Laden der Level-Daten, initialisiere das Level - this.initializeLevel(); + await this.initializeLevel(); }); }); } // Verwende die gefundenen Daten direkt - return this.loadLevelDataInternal(levelData).then(() => { + return this.loadLevelDataInternal(levelData).then(async () => { // WICHTIG: Nach dem Laden der Level-Daten, initialisiere das Level - this.initializeLevel(); + await this.initializeLevel(); }); }, @@ -662,7 +662,7 @@ export default { }); }, - initializeLevel() { + async initializeLevel() { // WICHTIG: Verhindere mehrfache Level-Initialisierung if (this.isInitializingLevel) { return; @@ -671,13 +671,13 @@ export default { // Safety check: ensure currentLevelData is loaded if (!this.currentLevelData) { // KEINE REKURSION: Lade Kampagnendaten nur einmal - this.loadCampaignData().then(() => { - // Nach dem Laden der Kampagne, initialisiere das Level direkt - if (this.currentLevelData) { - this.initializeLevelInternal(); - } else { - // Level-Daten konnten nicht geladen werden - } + this.loadCampaignData().then(async () => { + // Nach dem Laden der Kampagne, initialisiere das Level direkt + if (this.currentLevelData) { + await this.initializeLevelInternal(); + } else { + // Level-Daten konnten nicht geladen werden + } }); return; } @@ -686,11 +686,11 @@ export default { this.isInitializingLevel = true; // Verwende die bereits geladenen Level-Daten direkt - this.initializeLevelInternal(); + await this.initializeLevelInternal(); }, // Neue Hilfsmethode ohne Rekursion - initializeLevelInternal() { + async initializeLevelInternal() { const levelData = this.currentLevelData; // Neue Level-Felder verwenden @@ -784,13 +784,17 @@ export default { console.log('🔧 Keine initialen Matches gefunden, Level ist bereit'); } + // WICHTIG: Nach der Korrektur der initialen Matches das Brett erneut überprüfen + console.log('🔍 Überprüfe das Brett nach der Korrektur der initialen Matches...'); + await this.checkBoardAfterSetup(); + // WICHTIG: Setze das Spiel als aktiv, aber prüfe NICHT sofort die Level-Objekte this.gameActive = true; // KEINE Prüfung der Level-Objekte beim Start - diese werden nur nach Spielzügen geprüft - // WICHTIG: Reset Flag für Level-Initialisierung - this.isInitializingLevel = false; + // WICHTIG: Reset Flag für Level-Initialisierung + this.isInitializingLevel = false; }, // Neue Methode: Räume initiale Matches auf (ohne Punkte/Level-Objekte) @@ -1706,19 +1710,32 @@ export default { return; } + // WICHTIG: Prüfe auf Regenbogen-Tile Tausch (vor dem Tausch) + // Prüfe beide Kombinationen der ursprünglichen Tiles + const rainbowSwapResult = await this.handleRainbowSwap(this.board[index1], this.board[index2]); + if (rainbowSwapResult) { + // Regenbogen-Tausch erfolgreich - Zug-Zähler wird bereits in handleRainbowSwap erhöht + // ABER: Wir müssen trotzdem die Matches verarbeiten, die durch den Regenbogen-Tausch entstanden sind + console.log('🌈 Regenbogen-Tausch erfolgreich, verarbeite entstandene Matches...'); + + // Warte kurz, damit die Animation abgeschlossen ist + await new Promise(resolve => setTimeout(resolve, 100)); + + // Prüfe auf Matches nach dem Regenbogen-Tausch + const matchesAfterRainbow = this.findMatchesOnBoard(this.board, false); + if (matchesAfterRainbow.length > 0) { + console.log(`🌈 ${matchesAfterRainbow.length} Matches nach Regenbogen-Tausch gefunden, verarbeite sie...`); + await this.handleMatches(matchesAfterRainbow, true); // true = Spieler-Zug + } + + return; // Beende hier, da Regenbogen-Tausch bereits verarbeitet wurde + } + // Tausche die Tiles const temp = this.board[index1]; this.board[index1] = this.board[index2]; this.board[index2] = temp; - // WICHTIG: Prüfe auf Regenbogen-Tile Tausch (vor normalen Matches) - // Prüfe beide Kombinationen: temp + board[index1] und board[index1] + temp - if (await this.handleRainbowSwap(temp, this.board[index1]) || - await this.handleRainbowSwap(this.board[index1], temp)) { - // Regenbogen-Tausch erfolgreich - Zug-Zähler wird bereits in handleRainbowSwap erhöht - return; // Beende hier, da Regenbogen-Tausch bereits verarbeitet wurde - } - // Spiele Move-Sound this.playSound('move'); @@ -1793,12 +1810,37 @@ export default { } }); - // Verarbeite dann normale Matches (3er, 4er, 5er) + // Verarbeite dann normale Matches (3er, 4er, 5er) und berechne Punkte + let totalMatchPoints = 0; matches.forEach((match, matchIndex) => { if (Array.isArray(match) && match.length >= 3) { // Normale Matches (3er, 4er, 5er) console.log(`🔧 ${match.length}er-Match ${matchIndex + 1}: [${match.join(', ')}]`); + // Berechne Punkte für diesen Match + let matchPoints = 0; + if (match.length === 3) { + matchPoints = 10; // 3er-Match: 10 Punkte + console.log(`🔧 3er-Match: +${matchPoints} Punkte`); + } else if (match.length === 4) { + matchPoints = 20; // 4er-Match (Rakete): 20 Punkte + console.log(`🔧 4er-Match (Rakete): +${matchPoints} Punkte`); + } else if (match.length === 5) { + // Prüfe ob es ein Regenbogen-Match ist + const hasRainbow = match.some(tileIndex => + this.board[tileIndex] && this.board[tileIndex].type === 'rainbow' + ); + if (hasRainbow) { + matchPoints = 50; // 5er-Match mit Regenbogen: 50 Punkte + console.log(`🔧 5er-Match mit Regenbogen: +${matchPoints} Punkte`); + } else { + matchPoints = 35; // 5er-Match (Bombe): 35 Punkte + console.log(`🔧 5er-Match (Bombe): +${matchPoints} Punkte`); + } + } + + totalMatchPoints += matchPoints; + match.forEach(tileIndex => { // WICHTIG: Power-ups dürfen NIE entfernt werden if (this.board[tileIndex] && this.isPowerUpTile(this.board[tileIndex].type)) { @@ -1813,6 +1855,13 @@ export default { } }); + // Füge die Match-Punkte zum Level-Score hinzu + if (totalMatchPoints > 0) { + this.levelScore += totalMatchPoints; + this.score += totalMatchPoints; + console.log(`🎯 Match-Punkte hinzugefügt: +${totalMatchPoints} Punkte (Level: ${this.levelScore}, Gesamt: ${this.score})`); + } + // Debug: Zeige alle Tiles, die zur Entfernung hinzugefügt wurden console.log('🔧 Debug: Alle Tiles, die zur Entfernung hinzugefügt wurden:'); tilesToRemove.forEach(index => { @@ -1945,7 +1994,12 @@ export default { } } - + // WICHTIG: Prüfe Level-Objekte nach dem Verarbeiten der Matches + if (isPlayerMove && !this.isInitializingLevel) { + console.log('🎯 Prüfe Level-Objekte nach Match-Verarbeitung...'); + this.checkLevelObjectives(); + } + } }, @@ -2035,8 +2089,8 @@ export default { this.$forceUpdate(); } - // Kurze Pause zwischen den Iterationen - await this.wait(100); + // Kürzere Pause zwischen den Iterationen für bessere Performance + await this.wait(50); } console.log(`🔧 Fall-Down abgeschlossen nach ${iteration} Iterationen`); @@ -2110,6 +2164,44 @@ export default { } console.log(`🔧 ${newTilesAdded} neue Tiles hinzugefügt`); + + // WICHTIG: Nach dem Füllen der leeren Positionen das Brett auf Matches überprüfen + if (newTilesAdded > 0) { + console.log('🔍 Überprüfe das Brett auf Matches nach dem Füllen der leeren Positionen...'); + + // Warte kurz, damit die neuen Tiles vollständig angezeigt werden + await this.wait(300); + + // Prüfe auf Matches auf dem aktuellen Board + const matchesAfterFill = this.findMatchesOnBoard(this.board, false); + + if (matchesAfterFill.length > 0) { + console.log(`🔍 ${matchesAfterFill.length} Match(es) nach dem Füllen gefunden - starte automatische Behandlung`); + + // Behandle die gefundenen Matches automatisch (kein Spieler-Move) + await this.handleMatches(matchesAfterFill, false); + + // WICHTIG: Rekursiver Aufruf, falls durch die Matches neue leere Positionen entstehen + // Das verhindert Endlosschleifen durch max. 3 Rekursionen + if (this.recursionDepth === undefined) { + this.recursionDepth = 0; + } + + if (this.recursionDepth < 3) { + this.recursionDepth++; + console.log(`🔄 Rekursiver Aufruf ${this.recursionDepth}/3 - prüfe auf weitere leere Positionen`); + + // Prüfe erneut auf leere Positionen und fülle sie auf + await this.checkAndFillEmptyValidFields(); + + this.recursionDepth--; + } else { + console.log('⚠️ Maximale Rekursionstiefe erreicht - stoppe automatische Match-Behandlung'); + } + } else { + console.log('✅ Keine Matches nach dem Füllen gefunden - Board ist bereit'); + } + } }, // Erstelle Power-ups für 4er-Matches, 5er-Matches und L-Form-Matches @@ -2286,6 +2378,42 @@ export default { }))); console.log(`🔧 Alle leeren gültigen Felder gefüllt`); + + // WICHTIG: Nach dem Füllen der leeren gültigen Felder das Brett auf Matches überprüfen + console.log('🔍 Überprüfe das Brett auf Matches nach dem Füllen der leeren gültigen Felder...'); + + // Warte kurz, damit die neuen Tiles vollständig angezeigt werden + await this.wait(300); + + // Prüfe auf Matches auf dem aktuellen Board + const matchesAfterFill = this.findMatchesOnBoard(this.board, false); + + if (matchesAfterFill.length > 0) { + console.log(`🔍 ${matchesAfterFill.length} Match(es) nach dem Füllen der leeren gültigen Felder gefunden - starte automatische Behandlung`); + + // Behandle die gefundenen Matches automatisch (kein Spieler-Move) + await this.handleMatches(matchesAfterFill, false); + + // WICHTIG: Rekursiver Aufruf, falls durch die Matches neue leere Positionen entstehen + // Das verhindert Endlosschleifen durch max. 3 Rekursionen + if (this.recursionDepth === undefined) { + this.recursionDepth = 0; + } + + if (this.recursionDepth < 3) { + this.recursionDepth++; + console.log(`🔄 Rekursiver Aufruf ${this.recursionDepth}/3 - prüfe auf weitere leere gültige Felder`); + + // Prüfe erneut auf leere gültige Felder und fülle sie auf + await this.checkAndFillEmptyValidFields(); + + this.recursionDepth--; + } else { + console.log('⚠️ Maximale Rekursionstiefe erreicht - stoppe automatische Match-Behandlung'); + } + } else { + console.log('✅ Keine Matches nach dem Füllen der leeren gültigen Felder gefunden - Board ist bereit'); + } } else { console.log('🔧 Alle gültigen Felder enthalten Tiles - Board ist vollständig'); } @@ -2343,7 +2471,7 @@ export default { // Setze das Tile an seine ursprüngliche Position (oben) element.style.transform = `translateY(0px)`; - element.style.transition = 'transform 0.5s ease-out'; + element.style.transition = 'transform 0.3s ease-out'; // Füge CSS-Klasse für die Fall-Animation hinzu element.classList.add('falling'); @@ -2375,8 +2503,8 @@ export default { // Spiele Fall-Sound ab this.playSound('falling'); - // Warte auf die Fall-Animation (0,5 Sekunden) - await this.wait(500); + // Warte auf die Fall-Animation (0,3 Sekunden) + await this.wait(300); // Entferne die CSS-Klassen und transform-Eigenschaften tileElements.forEach(element => { @@ -4792,7 +4920,18 @@ export default { this.moves++; this.movesLeft--; - console.log(`🌈 ${tilesToRemove.length} Tiles vom Typ ${targetType} entfernt`); + // Punkte hinzufügen (Regenbogen-Aktivierung) + const points = tilesToRemove.length * 25 * this.currentLevel; + this.levelScore += points; + this.score += points; + + console.log(`🌈 ${tilesToRemove.length} Tiles vom Typ ${targetType} entfernt, +${points} Punkte`); + + // WICHTIG: Prüfe Level-Objekte nach der Regenbogen-Aktivierung + if (!this.isInitializingLevel) { + console.log('🎯 Prüfe Level-Objekte nach Regenbogen-Aktivierung...'); + this.checkLevelObjectives(); + } }, // Neue Methode: Behandle Power-Up Tile Tausch @@ -4932,6 +5071,28 @@ export default { } }, + // Neue Methode: Überprüfe das Brett nach dem Feldaufbau auf Matches + async checkBoardAfterSetup() { + console.log('🔍 Überprüfe das Brett nach dem Feldaufbau auf Matches...'); + + // Warte kurz, damit alle Tiles vollständig angezeigt werden + await this.wait(500); + + // Prüfe auf Matches auf dem aktuellen Board + const matchesAfterSetup = this.findMatchesOnBoard(this.board, false); + + if (matchesAfterSetup.length > 0) { + console.log(`🔍 ${matchesAfterSetup.length} Match(es) nach dem Feldaufbau gefunden - starte automatische Behandlung`); + + // Behandle die gefundenen Matches automatisch (kein Spieler-Move) + await this.handleMatches(matchesAfterSetup, false); + + console.log('✅ Brett nach dem Feldaufbau erfolgreich bereinigt'); + } else { + console.log('✅ Keine Matches nach dem Feldaufbau gefunden - Brett ist bereit'); + } + }, + // Neue Methode: Entferne ALLE Tiles vom Board (einschließlich Regenbögen) async removeAllTilesFromBoardIncludingRainbows() { const allTileIndices = []; @@ -4977,6 +5138,12 @@ export default { this.score += points; console.log(`🌈 Alle Tiles erfolgreich entfernt! +${points} Punkte`); + + // WICHTIG: Prüfe Level-Objekte nach dem Regenbogen-Tausch + if (!this.isInitializingLevel) { + console.log('🎯 Prüfe Level-Objekte nach Regenbogen-Tausch...'); + this.checkLevelObjectives(); + } } },