feat(match3): Verbesserung der Level-Initialisierung und Match-Verarbeitung

- Umstellung der Level-Initialisierung auf asynchrone Funktionen zur besseren Handhabung von Ladezeiten.
- Einführung neuer Methoden zur Überprüfung des Boards nach dem Füllen und nach der Initialisierung.
- Erweiterung der Logik zur Punktevergabe bei Matches und Regenbogen-Aktivierungen.
- Optimierung der Debug-Ausgaben zur Nachverfolgbarkeit von Spielereignissen und Match-Verarbeitungen.
- Anpassung der Animationen und Wartezeiten für eine flüssigere Spielerfahrung.
This commit is contained in:
Torsten Schulz (local)
2025-08-28 16:56:00 +02:00
parent 3d97b5ce2c
commit b5b1a90319

View File

@@ -472,9 +472,9 @@ export default {
// Nach dem Laden der Kampagne, versuche das Level zu finden // Nach dem Laden der Kampagne, versuche das Level zu finden
const levelData = this.campaignData.levels.find(l => l.order === levelOrder); const levelData = this.campaignData.levels.find(l => l.order === levelOrder);
if (levelData) { if (levelData) {
return this.loadLevelDataInternal(levelData).then(() => { return this.loadLevelDataInternal(levelData).then(async () => {
// WICHTIG: Nach dem Laden der Level-Daten, initialisiere das Level // WICHTIG: Nach dem Laden der Level-Daten, initialisiere das Level
this.initializeLevel(); await this.initializeLevel();
}); });
} else { } else {
throw new Error(`Level ${levelOrder} nicht in Kampagnendaten gefunden`); 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); const levelData = this.campaignData.levels.find(l => l.order === levelOrder);
if (!levelData) { if (!levelData) {
// KEINE REKURSION: Lade Kampagne nur einmal // 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); const retryLevelData = this.campaignData.levels.find(l => l.order === levelOrder);
if (!retryLevelData) { if (!retryLevelData) {
throw new Error(`Level ${levelOrder} nicht gefunden`); throw new Error(`Level ${levelOrder} nicht gefunden`);
} }
// Verwende die gefundenen Daten direkt, ohne Rekursion // 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 // WICHTIG: Nach dem Laden der Level-Daten, initialisiere das Level
this.initializeLevel(); await this.initializeLevel();
}); });
}); });
} }
// Verwende die gefundenen Daten direkt // 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 // 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 // WICHTIG: Verhindere mehrfache Level-Initialisierung
if (this.isInitializingLevel) { if (this.isInitializingLevel) {
return; return;
@@ -671,10 +671,10 @@ export default {
// Safety check: ensure currentLevelData is loaded // Safety check: ensure currentLevelData is loaded
if (!this.currentLevelData) { if (!this.currentLevelData) {
// KEINE REKURSION: Lade Kampagnendaten nur einmal // KEINE REKURSION: Lade Kampagnendaten nur einmal
this.loadCampaignData().then(() => { this.loadCampaignData().then(async () => {
// Nach dem Laden der Kampagne, initialisiere das Level direkt // Nach dem Laden der Kampagne, initialisiere das Level direkt
if (this.currentLevelData) { if (this.currentLevelData) {
this.initializeLevelInternal(); await this.initializeLevelInternal();
} else { } else {
// Level-Daten konnten nicht geladen werden // Level-Daten konnten nicht geladen werden
} }
@@ -686,11 +686,11 @@ export default {
this.isInitializingLevel = true; this.isInitializingLevel = true;
// Verwende die bereits geladenen Level-Daten direkt // Verwende die bereits geladenen Level-Daten direkt
this.initializeLevelInternal(); await this.initializeLevelInternal();
}, },
// Neue Hilfsmethode ohne Rekursion // Neue Hilfsmethode ohne Rekursion
initializeLevelInternal() { async initializeLevelInternal() {
const levelData = this.currentLevelData; const levelData = this.currentLevelData;
// Neue Level-Felder verwenden // Neue Level-Felder verwenden
@@ -784,6 +784,10 @@ export default {
console.log('🔧 Keine initialen Matches gefunden, Level ist bereit'); 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 // WICHTIG: Setze das Spiel als aktiv, aber prüfe NICHT sofort die Level-Objekte
this.gameActive = true; this.gameActive = true;
@@ -1706,19 +1710,32 @@ export default {
return; 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 // Tausche die Tiles
const temp = this.board[index1]; const temp = this.board[index1];
this.board[index1] = this.board[index2]; this.board[index1] = this.board[index2];
this.board[index2] = temp; 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 // Spiele Move-Sound
this.playSound('move'); 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) => { matches.forEach((match, matchIndex) => {
if (Array.isArray(match) && match.length >= 3) { if (Array.isArray(match) && match.length >= 3) {
// Normale Matches (3er, 4er, 5er) // Normale Matches (3er, 4er, 5er)
console.log(`🔧 ${match.length}er-Match ${matchIndex + 1}: [${match.join(', ')}]`); 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 => { match.forEach(tileIndex => {
// WICHTIG: Power-ups dürfen NIE entfernt werden // WICHTIG: Power-ups dürfen NIE entfernt werden
if (this.board[tileIndex] && this.isPowerUpTile(this.board[tileIndex].type)) { 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 // Debug: Zeige alle Tiles, die zur Entfernung hinzugefügt wurden
console.log('🔧 Debug: Alle Tiles, die zur Entfernung hinzugefügt wurden:'); console.log('🔧 Debug: Alle Tiles, die zur Entfernung hinzugefügt wurden:');
tilesToRemove.forEach(index => { tilesToRemove.forEach(index => {
@@ -1945,6 +1994,11 @@ 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(); this.$forceUpdate();
} }
// Kurze Pause zwischen den Iterationen // Kürzere Pause zwischen den Iterationen für bessere Performance
await this.wait(100); await this.wait(50);
} }
console.log(`🔧 Fall-Down abgeschlossen nach ${iteration} Iterationen`); console.log(`🔧 Fall-Down abgeschlossen nach ${iteration} Iterationen`);
@@ -2110,6 +2164,44 @@ export default {
} }
console.log(`🔧 ${newTilesAdded} neue Tiles hinzugefügt`); 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 // 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`); 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 { } else {
console.log('🔧 Alle gültigen Felder enthalten Tiles - Board ist vollständig'); 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) // Setze das Tile an seine ursprüngliche Position (oben)
element.style.transform = `translateY(0px)`; 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 // Füge CSS-Klasse für die Fall-Animation hinzu
element.classList.add('falling'); element.classList.add('falling');
@@ -2375,8 +2503,8 @@ export default {
// Spiele Fall-Sound ab // Spiele Fall-Sound ab
this.playSound('falling'); this.playSound('falling');
// Warte auf die Fall-Animation (0,5 Sekunden) // Warte auf die Fall-Animation (0,3 Sekunden)
await this.wait(500); await this.wait(300);
// Entferne die CSS-Klassen und transform-Eigenschaften // Entferne die CSS-Klassen und transform-Eigenschaften
tileElements.forEach(element => { tileElements.forEach(element => {
@@ -4792,7 +4920,18 @@ export default {
this.moves++; this.moves++;
this.movesLeft--; 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 // 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) // Neue Methode: Entferne ALLE Tiles vom Board (einschließlich Regenbögen)
async removeAllTilesFromBoardIncludingRainbows() { async removeAllTilesFromBoardIncludingRainbows() {
const allTileIndices = []; const allTileIndices = [];
@@ -4977,6 +5138,12 @@ export default {
this.score += points; this.score += points;
console.log(`🌈 Alle Tiles erfolgreich entfernt! +${points} Punkte`); 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();
}
} }
}, },