diff --git a/frontend/src/views/minigames/Match3Game.vue b/frontend/src/views/minigames/Match3Game.vue index e2e5697..2864611 100644 --- a/frontend/src/views/minigames/Match3Game.vue +++ b/frontend/src/views/minigames/Match3Game.vue @@ -92,8 +92,9 @@ 'empty': !tile, 'dragging': draggedTileIndex === index, 'drag-hover': isDragging && adjacentTilesForHover.includes(index), - 'rocket-horizontal': tile && tile.type === 'rocket-horizontal', - 'rocket-vertical': tile && tile.type === 'rocket-vertical' + 'rocket-horizontal': tile && tile.type === 'rocket-horizontal', + 'rocket-vertical': tile && tile.type === 'rocket-vertical', + 'bomb': tile && tile.type === 'bomb' }]" :data-index="index" :data-type="tile ? tile.type : null" @@ -105,10 +106,13 @@ @touchstart="onTileMouseDown($event, index)" @touchend="onTileMouseUp($event, index)" @dblclick="handleDoubleClick(index, $event)"> - {{ getTileSymbol(tile.type) }} + {{ getTileSymbol(tile.type) }} 🚀 + + 💣 + @@ -1040,16 +1044,139 @@ export default { findMatchesOnBoard(board, showDebug = true) { const matches = []; - // Horizontale Matches finden (3er, 4er, 5er) + // L-Form Matches finden (alle 4 Richtungen) - PRIORITÄT vor regulären Matches + for (let row = 0; row < this.boardHeight - 2; row++) { + for (let col = 0; col < this.boardWidth - 2; col++) { + // L-Form nach rechts unten (┌) + if (row + 2 < this.boardHeight && col + 2 < this.boardWidth) { + const verticalIndices = [ + this.coordsToIndex(row, col), + this.coordsToIndex(row + 1, col), + this.coordsToIndex(row + 2, col) + ]; + const horizontalIndices = [ + this.coordsToIndex(row, col), + this.coordsToIndex(row, col + 1), + this.coordsToIndex(row, col + 2) + ]; + + // Prüfe ob alle Indizes gültig sind und Tiles existieren + if (verticalIndices.every(idx => idx !== null && board[idx]) && + horizontalIndices.every(idx => idx !== null && board[idx]) && + this.isValidMatchForLShape(verticalIndices[0], verticalIndices[1], verticalIndices[2], board) && + this.isValidMatchForLShape(horizontalIndices[0], horizontalIndices[1], horizontalIndices[2], board)) { + + const cornerIndex = this.coordsToIndex(row, col); + const lShapeIndices = [...new Set([...verticalIndices, ...horizontalIndices])]; + matches.push({ type: 'l-shape', indices: lShapeIndices, corner: cornerIndex, direction: 'bottom-right' }); + if (showDebug) console.log(`🔍 L-Form Match (┌): [${row},${col}] mit 3er vertikal und 3er horizontal`); + } + } + + // L-Form nach links unten (┐) + if (row + 2 < this.boardHeight && col >= 2) { + const verticalIndices = [ + this.coordsToIndex(row, col), + this.coordsToIndex(row + 1, col), + this.coordsToIndex(row + 2, col) + ]; + const horizontalIndices = [ + this.coordsToIndex(row, col), + this.coordsToIndex(row, col - 1), + this.coordsToIndex(row, col - 2) + ]; + + if (verticalIndices.every(idx => idx !== null && board[idx]) && + horizontalIndices.every(idx => idx !== null && board[idx]) && + this.isValidMatchForLShape(verticalIndices[0], verticalIndices[1], verticalIndices[2], board) && + this.isValidMatchForLShape(horizontalIndices[0], horizontalIndices[1], horizontalIndices[2], board)) { + + const cornerIndex = this.coordsToIndex(row, col); + const lShapeIndices = [...new Set([...verticalIndices, ...horizontalIndices])]; + matches.push({ type: 'l-shape', indices: lShapeIndices, corner: cornerIndex, direction: 'bottom-left' }); + if (showDebug) console.log(`🔍 L-Form Match (┐): [${row},${col}] mit 3er vertikal und 3er horizontal`); + } + } + + // L-Form nach rechts oben (└) + if (row >= 2 && col + 2 < this.boardWidth) { + const verticalIndices = [ + this.coordsToIndex(row, col), + this.coordsToIndex(row - 1, col), + this.coordsToIndex(row - 2, col) + ]; + const horizontalIndices = [ + this.coordsToIndex(row, col), + this.coordsToIndex(row, col + 1), + this.coordsToIndex(row, col + 2) + ]; + + if (verticalIndices.every(idx => idx !== null && board[idx]) && + horizontalIndices.every(idx => idx !== null && board[idx]) && + this.isValidMatchForLShape(verticalIndices[0], verticalIndices[1], verticalIndices[2], board) && + this.isValidMatchForLShape(horizontalIndices[0], horizontalIndices[1], horizontalIndices[2], board)) { + + const cornerIndex = this.coordsToIndex(row, col); + const lShapeIndices = [...new Set([...verticalIndices, ...horizontalIndices])]; + matches.push({ type: 'l-shape', indices: lShapeIndices, corner: cornerIndex, direction: 'top-right' }); + if (showDebug) console.log(`🔍 L-Form Match (└): [${row},${col}] mit 3er vertikal und 3er horizontal`); + } + } + + // L-Form nach links oben (┘) + if (row >= 2 && col >= 2) { + const verticalIndices = [ + this.coordsToIndex(row, col), + this.coordsToIndex(row - 1, col), + this.coordsToIndex(row - 2, col) + ]; + const horizontalIndices = [ + this.coordsToIndex(row, col), + this.coordsToIndex(row, col - 1), + this.coordsToIndex(row, col - 2) + ]; + + if (verticalIndices.every(idx => idx !== null && board[idx]) && + horizontalIndices.every(idx => idx !== null && board[idx]) && + this.isValidMatchForLShape(verticalIndices[0], verticalIndices[1], verticalIndices[2], board) && + this.isValidMatchForLShape(horizontalIndices[0], horizontalIndices[1], horizontalIndices[2], board)) { + + const cornerIndex = this.coordsToIndex(row, col); + const lShapeIndices = [...new Set([...verticalIndices, ...horizontalIndices])]; + matches.push({ type: 'l-shape', indices: lShapeIndices, corner: cornerIndex, direction: 'top-left' }); + if (showDebug) console.log(`🔍 L-Form Match (┘): [${row},${col}] mit 3er vertikal und 3er horizontal`); + } + } + } + } + + // Sammle alle Indizes, die bereits Teil einer L-Form sind + const lShapeIndices = new Set(); + matches.forEach(match => { + if (match.type === 'l-shape') { + match.indices.forEach(index => lShapeIndices.add(index)); + } + }); + + // Horizontale Matches finden (3er, 4er, 5er) - NACH L-Form Matches for (let row = 0; row < this.boardHeight; row++) { for (let col = 0; col < this.boardWidth - 2; col++) { + // Prüfe ob diese Position bereits Teil einer L-Form ist + const currentIndex = this.coordsToIndex(row, col); + if (lShapeIndices.has(currentIndex)) { + if (showDebug) console.log(`🔍 Überspringe Position [${row},${col}] - bereits Teil einer L-Form`); + continue; + } + // Prüfe auf 3er-Match if (col + 2 < this.boardWidth) { const index1 = this.coordsToIndex(row, col); const index2 = this.coordsToIndex(row, col + 1); const index3 = this.coordsToIndex(row, col + 2); - if (this.isValidMatch(index1, index2, index3, board)) { + // Prüfe ob alle drei Positionen bereits Teil einer L-Form sind + if (!lShapeIndices.has(index1) && !lShapeIndices.has(index2) && !lShapeIndices.has(index3) && + this.isValidMatch(index1, index2, index3, board)) { matches.push([index1, index2, index3]); if (showDebug) console.log(`🔍 3er-Match horizontal: [${row},${col}] bis [${row},${col+2}]`); } @@ -1062,7 +1189,9 @@ export default { const index3 = this.coordsToIndex(row, col + 2); const index4 = this.coordsToIndex(row, col + 3); - if (this.isValidMatch(index1, index2, index3, board) && + // Prüfe ob alle vier Positionen bereits Teil einer L-Form sind + if (!lShapeIndices.has(index1) && !lShapeIndices.has(index2) && !lShapeIndices.has(index3) && !lShapeIndices.has(index4) && + this.isValidMatch(index1, index2, index3, board) && this.isValidMatch(index2, index3, index4, board)) { matches.push([index1, index2, index3, index4]); if (showDebug) console.log(`🔍 4er-Match horizontal: [${row},${col}] bis [${row},${col+3}]`); @@ -1077,7 +1206,9 @@ export default { const index4 = this.coordsToIndex(row, col + 3); const index5 = this.coordsToIndex(row, col + 4); - if (this.isValidMatch(index1, index2, index3, board) && + // Prüfe ob alle fünf Positionen bereits Teil einer L-Form sind + if (!lShapeIndices.has(index1) && !lShapeIndices.has(index2) && !lShapeIndices.has(index3) && !lShapeIndices.has(index4) && !lShapeIndices.has(index5) && + this.isValidMatch(index1, index2, index3, board) && this.isValidMatch(index2, index3, index4, board) && this.isValidMatch(index3, index4, index5, board)) { matches.push([index1, index2, index3, index4, index5]); @@ -1087,16 +1218,25 @@ export default { } } - // Vertikale Matches finden (3er, 4er, 5er) + // Vertikale Matches finden (3er, 4er, 5er) - NACH L-Form Matches for (let row = 0; row < this.boardHeight - 2; row++) { for (let col = 0; col < this.boardWidth; col++) { + // Prüfe ob diese Position bereits Teil einer L-Form ist + const currentIndex = this.coordsToIndex(row, col); + if (lShapeIndices.has(currentIndex)) { + if (showDebug) console.log(`🔍 Überspringe Position [${row},${col}] - bereits Teil einer L-Form`); + continue; + } + // Prüfe auf 3er-Match if (row + 2 < this.boardHeight) { const index1 = this.coordsToIndex(row, col); const index2 = this.coordsToIndex(row + 1, col); const index3 = this.coordsToIndex(row + 2, col); - if (this.isValidMatch(index1, index2, index3, board)) { + // Prüfe ob alle drei Positionen bereits Teil einer L-Form sind + if (!lShapeIndices.has(index1) && !lShapeIndices.has(index2) && !lShapeIndices.has(index3) && + this.isValidMatch(index1, index2, index3, board)) { matches.push([index1, index2, index3]); if (showDebug) console.log(`🔍 3er-Match vertikal: [${row},${col}] bis [${row+2},${col}]`); } @@ -1109,7 +1249,9 @@ export default { const index3 = this.coordsToIndex(row + 2, col); const index4 = this.coordsToIndex(row + 3, col); - if (this.isValidMatch(index1, index2, index3, board) && + // Prüfe ob alle vier Positionen bereits Teil einer L-Form sind + if (!lShapeIndices.has(index1) && !lShapeIndices.has(index2) && !lShapeIndices.has(index3) && !lShapeIndices.has(index4) && + this.isValidMatch(index1, index2, index3, board) && this.isValidMatch(index2, index3, index4, board)) { matches.push([index1, index2, index3, index4]); if (showDebug) console.log(`🔍 4er-Match vertikal: [${row},${col}] bis [${row+3},${col}]`); @@ -1124,7 +1266,9 @@ export default { const index4 = this.coordsToIndex(row + 3, col); const index5 = this.coordsToIndex(row + 4, col); - if (this.isValidMatch(index1, index2, index3, board) && + // Prüfe ob alle fünf Positionen bereits Teil einer L-Form sind + if (!lShapeIndices.has(index1) && !lShapeIndices.has(index2) && !lShapeIndices.has(index3) && !lShapeIndices.has(index4) && !lShapeIndices.has(index5) && + this.isValidMatch(index1, index2, index3, board) && this.isValidMatch(index2, index3, index4, board) && this.isValidMatch(index3, index4, index5, board)) { matches.push([index1, index2, index3, index4, index5]); @@ -1134,32 +1278,7 @@ export default { } } - // L-Form Matches finden (3 Tiles senkrecht + 3 Tiles waagrecht) - for (let row = 0; row < this.boardHeight - 2; row++) { - for (let col = 0; col < this.boardWidth - 2; col++) { - // L-Form nach rechts unten - if (row + 2 < this.boardHeight && col + 2 < this.boardWidth) { - const verticalIndices = [ - this.coordsToIndex(row, col), - this.coordsToIndex(row + 1, col), - this.coordsToIndex(row + 2, col) - ]; - const horizontalIndices = [ - this.coordsToIndex(row, col), - this.coordsToIndex(row, col + 1), - this.coordsToIndex(row, col + 2) - ]; - - if (this.isValidMatch(verticalIndices[0], verticalIndices[1], verticalIndices[2], board) && - this.isValidMatch(horizontalIndices[0], horizontalIndices[1], horizontalIndices[2], board)) { - // Kombiniere alle Indizes (ohne Duplikate) - const lShapeIndices = [...new Set([...verticalIndices, ...horizontalIndices])]; - matches.push(lShapeIndices); - if (showDebug) console.log(`🔍 L-Form Match: [${row},${col}] mit 3er vertikal und 3er horizontal`); - } - } - } - } + if (showDebug) { console.log(`🔍 Gefundene Matches: ${matches.length}`, matches); @@ -1170,7 +1289,22 @@ export default { // Hilfsmethode: Prüfe ob ein Tile ein Raketen-Power-up ist isRocketTile(tileType) { - return tileType === 'rocket-horizontal' || tileType === 'rocket-vertical'; + return tileType === 'rocket' || tileType === 'rocket-horizontal' || tileType === 'rocket-vertical'; + }, + + // Hilfsmethode: Prüfe ob ein Tile ein Power-up ist + isPowerUpTile(tileType) { + return this.isRocketTile(tileType) || tileType === 'bomb' || tileType === 'rocket-horizontal' || tileType === 'rocket-vertical'; + }, + + // Hilfsmethode: Debug-Ausgabe für Power-ups + debugPowerUps() { + console.log('🔍 Debug: Alle Power-ups auf dem Board:'); + for (let i = 0; i < this.board.length; i++) { + if (this.board[i] && this.isPowerUpTile(this.board[i].type)) { + console.log(`🔍 Power-up ${this.board[i].type} an Position ${i}`); + } + } }, // Hilfsmethode: Prüfe ob 3 Tiles einen gültigen Match bilden @@ -1202,7 +1336,43 @@ export default { const type3 = board[index3].type; // Power-ups können nicht gematcht werden - if (this.isRocketTile(type1) || this.isRocketTile(type2) || this.isRocketTile(type3)) { + if (this.isPowerUpTile(type1) || this.isPowerUpTile(type2) || this.isPowerUpTile(type3)) { + return false; + } + + return type1 === type2 && type2 === type3; + }, + + // Hilfsmethode: Prüfe ob 3 Tiles einen gültigen Match bilden (für L-Form) + isValidMatchForLShape(index1, index2, index3, board) { + // Prüfe ob alle Indizes gültig sind + if (index1 === null || index2 === null || index3 === null) { + return false; + } + + // Prüfe ob alle Positionen gültig sind + const pos1 = this.indexToCoords(index1); + const pos2 = this.indexToCoords(index2); + const pos3 = this.indexToCoords(index3); + + if (!this.isValidPosition(pos1.row, pos1.col) || + !this.isValidPosition(pos2.row, pos2.col) || + !this.isValidPosition(pos3.row, pos3.col)) { + return false; + } + + // Prüfe ob alle Tiles existieren + if (!board[index1] || !board[index2] || !board[index3]) { + return false; + } + + // Prüfe ob alle Tiles den gleichen Typ haben + const type1 = board[index1].type; + const type2 = board[index2].type; + const type3 = board[index3].type; + + // Power-ups können nicht gematcht werden + if (this.isPowerUpTile(type1) || this.isPowerUpTile(type2) || this.isPowerUpTile(type3)) { return false; } @@ -1394,27 +1564,68 @@ export default { console.log(`🔧 Verarbeite ${matches.length} Matches...`); - // Erstelle Power-ups für 4er-Matches (BEVOR die Tiles entfernt werden) - await this.createPowerUpsForMatches(matches); + // Debug: Zeige alle gefundenen Matches + console.log('🔧 Debug: Alle gefundenen Matches:'); + matches.forEach((match, index) => { + if (match.type === 'l-shape') { + console.log(` Match ${index + 1}: L-Form ${match.direction} an Ecke ${match.corner}`); + } else if (Array.isArray(match)) { + console.log(` Match ${index + 1}: ${match.length}er-Match [${match.join(', ')}]`); + } + }); // Sammle alle zu entfernenden Tile-Indizes (aus 3er-Matches UND 4er-Matches) const tilesToRemove = new Set(); - matches.forEach((match, index) => { - if (match.length >= 3) { - console.log(`🔧 ${match.length}er-Match ${index + 1}: [${match.join(', ')}]`); + // Sammle alle Power-up-Positionen, die NICHT entfernt werden dürfen + const powerUpPositions = new Set(); + + // Verarbeite zuerst L-Form-Matches (Bomben) + matches.forEach((match, matchIndex) => { + if (match.type === 'l-shape') { + // L-Form Match: Erstelle Bombe an der Ecke + console.log(`🔧 L-Form Match ${matchIndex + 1}: ${match.direction} an Ecke ${match.corner}`); + + // Alle Tiles der L-Form entfernen (außer der Ecke, wo die Bombe ist) + match.indices.forEach(tileIndex => { + if (tileIndex !== match.corner) { + tilesToRemove.add(tileIndex); + } + }); + + // Bombe wird später in createPowerUpsForMatches erstellt + console.log(`💣 Bombe wird später an Position ${match.corner} erstellt`); + } + }); + + // Verarbeite dann normale Matches (3er, 4er, 5er) + 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(', ')}]`); + match.forEach(tileIndex => { - // Raketen-Power-ups nicht entfernen - if (this.board[tileIndex] && this.board[tileIndex].type && - (this.board[tileIndex].type === 'rocket-horizontal' || this.board[tileIndex].type === 'rocket-vertical')) { - console.log(`🔧 Rakete ${this.board[tileIndex].type} an Position ${tileIndex} wird NICHT entfernt`); + // WICHTIG: Power-ups dürfen NIE entfernt werden + if (this.board[tileIndex] && this.isPowerUpTile(this.board[tileIndex].type)) { + console.log(`🔧 Power-up ${this.board[tileIndex].type} an Position ${tileIndex} wird NICHT entfernt (Typ-Prüfung)`); return; // Überspringe dieses Tile } + + // Nur normale Tiles zur Entfernung hinzufügen + console.log(`🔧 Füge Tile ${this.board[tileIndex].type} an Position ${tileIndex} zur Entfernung hinzu`); tilesToRemove.add(tileIndex); }); } }); + // Debug: Zeige alle Tiles, die zur Entfernung hinzugefügt wurden + console.log('🔧 Debug: Alle Tiles, die zur Entfernung hinzugefügt wurden:'); + tilesToRemove.forEach(index => { + if (this.board[index]) { + console.log(` - Position ${index}: ${this.board[index].type}`); + } + }); + if (tilesToRemove.size === 0) { console.log('🔧 Keine Tiles zum Entfernen gefunden'); return; @@ -1422,6 +1633,14 @@ export default { console.log(`🔧 ${tilesToRemove.size} Tiles zum Entfernen gefunden`); + // Debug: Zeige alle Tiles, die entfernt werden sollen + console.log('🔧 Debug: Tiles die entfernt werden sollen:'); + tilesToRemove.forEach(index => { + if (this.board[index]) { + console.log(` - Position ${index}: ${this.board[index].type}`); + } + }); + // Starte Schrumpf-Animation für alle zu entfernenden Tiles console.log(`🔧 Starte Schrumpf-Animation für ${tilesToRemove.size} Tiles...`); await this.animateTileRemoval(Array.from(tilesToRemove)); @@ -1434,16 +1653,85 @@ export default { } }); + // Debug: Zeige alle Power-ups nach der Tile-Entfernung + console.log('🔧 Debug: Alle Power-ups nach Tile-Entfernung:'); + this.debugPowerUps(); + // Aktualisiere die Anzeige this.$forceUpdate(); console.log(`🔧 ${tilesToRemove.size} einzigartige Tiles aus 3er-Matches entfernt`); + // JETZT erst Power-ups erstellen, nachdem die Tiles entfernt wurden + console.log('🔧 Erstelle Power-ups nach der Tile-Entfernung...'); + const powerUpsCreated = await this.createPowerUpsForMatches(matches); + + // Debug: Zeige alle Power-ups nach der Erstellung + console.log('🔧 Debug: Alle Power-ups nach createPowerUpsForMatches:'); + this.debugPowerUps(); + + // Debug: Zeige alle Power-ups im Board nach der Erstellung + console.log('🔧 Debug: Board nach Power-up-Erstellung:'); + for (let i = 0; i < this.board.length; i++) { + if (this.board[i] && this.isPowerUpTile(this.board[i].type)) { + console.log(`🔧 Position ${i}: Power-up ${this.board[i].type}`); + console.log(`🔧 Board[${i}] = ${JSON.stringify(this.board[i])}`); + } + } + + // Debug: Zeige alle Power-ups im Template + console.log('🔧 Debug: Power-ups im Template:'); + for (let i = 0; i < this.board.length; i++) { + if (this.board[i]) { + console.log(`🔧 Position ${i}: Tile ${this.board[i].type}, isPowerUpTile: ${this.isPowerUpTile(this.board[i].type)}, isRocketTile: ${this.isRocketTile(this.board[i].type)}`); + if (this.isPowerUpTile(this.board[i].type)) { + console.log(`🔧 ✅ Power-up erkannt: ${this.board[i].type} an Position ${i}`); + } + } + } + + // Debug: Zeige alle Power-ups vor dem Fall-Down + console.log('🔧 Debug: Alle Power-ups vor dem Fall-Down:'); + this.debugPowerUps(); + + // Debug: Zeige alle Power-ups nach dem Fall-Down + console.log('🔧 Debug: Alle Power-ups nach dem Fall-Down:'); + this.debugPowerUps(); + // Führe Fall-Down-Logik aus await this.fallTilesDown(); + // Debug: Zeige alle Power-ups nach dem Fall-Down + console.log('🔧 Debug: Alle Power-ups nach dem Fall-Down:'); + this.debugPowerUps(); + // Fülle leere Positionen mit neuen Tiles auf await this.fillEmptyPositions(); + + // Debug: Zeige alle Power-ups nach dem Füllen + console.log('🔧 Debug: Alle Power-ups nach dem Füllen:'); + this.debugPowerUps(); + + // Prüfe ob Power-ups erstellt wurden - wenn ja, keine Cascade-Matches prüfen + // Verwende den Rückgabewert von createPowerUpsForMatches + if (!powerUpsCreated) { + // Nur Cascade-Matches prüfen, wenn keine Power-ups erstellt wurden + await this.checkForCascadeMatches(); + } else { + console.log(`🔧 ${powerUpsCreated} Power-ups erstellt - überspringe Cascade-Match-Prüfung`); + + // Debug: Zeige alle Power-ups nach der Verarbeitung + console.log('🔧 Debug: Alle Power-ups nach Power-up-Verarbeitung:'); + this.debugPowerUps(); + + // Debug: Zeige alle Power-ups im Template nach der Verarbeitung + console.log('🔧 Debug: Power-ups im Template nach Verarbeitung:'); + for (let i = 0; i < this.board.length; i++) { + if (this.board[i] && this.isPowerUpTile(this.board[i].type)) { + console.log(`🔧 ✅ Power-up im Template: ${this.board[i].type} an Position ${i}`); + } + } + } }, // Fall-Down-Logik: Bewege Tiles nach unten in leere Positionen @@ -1470,7 +1758,7 @@ export default { const belowIndex = this.coordsToIndex(row + 1, col); // Wenn aktuelles Tile existiert und das darunter leer ist - if (this.board[currentIndex] && !this.board[belowIndex]) { + if (this.board[currentIndex] && !this.board[belowIndex] && !this.isPowerUpTile(this.board[currentIndex].type)) { // Prüfe, ob das Zielfeld im board_layout gültig ist (nicht 'o') const targetRow = row + 1; const targetCol = col; @@ -1609,27 +1897,48 @@ export default { console.log(`🔧 ${newTilesAdded} neue Tiles hinzugefügt`); }, - // Erstelle Power-ups für 4er-Matches + // Erstelle Power-ups für 4er-Matches und L-Form-Matches async createPowerUpsForMatches(matches) { console.log('🔧 Prüfe auf Power-up-Erstellung...'); + let powerUpsCreated = 0; + matches.forEach(match => { - if (match.length === 4) { + // Prüfe auf L-Form-Matches (Bomben) + if (match.type === 'l-shape') { + console.log(`🔧 L-Form-Match gefunden: ${match.direction} an Ecke ${match.corner} - erstelle Bombe`); + + // Bombe an der Ecke erstellen + this.board[match.corner] = { type: 'bomb' }; + + console.log(`💣 Bombe an Position ${match.corner} erstellt`); + console.log(`🔧 Board[${match.corner}] = ${JSON.stringify(this.board[match.corner])}`); + powerUpsCreated++; + } + // Prüfe auf normale 4er-Matches (Arrays) + else if (Array.isArray(match) && match.length === 4) { console.log(`🔧 4er-Match gefunden: ${match.join(', ')} - erstelle Rakete`); // Rakete erscheint an der Position des zweiten Tiles const rocketIndex = match[1]; - const rocketTile = this.board[rocketIndex]; - if (rocketTile) { - // Erstelle Rakete basierend auf der Richtung des Matches - const rocketType = this.determineRocketType(match); - this.board[rocketIndex] = { type: rocketType }; - - console.log(`🚀 Rakete ${rocketType} an Position ${rocketIndex} erstellt`); - } + // Erstelle Rakete basierend auf der Richtung des Matches + const rocketType = this.determineRocketType(match); + this.board[rocketIndex] = { type: rocketType }; + + console.log(`🚀 Rakete ${rocketType} an Position ${rocketIndex} erstellt`); + console.log(`🔧 Board[${rocketIndex}] = ${JSON.stringify(this.board[rocketIndex])}`); + powerUpsCreated++; } }); + + // Aktualisiere die Anzeige nach der Power-up-Erstellung + if (powerUpsCreated > 0) { + this.$forceUpdate(); + console.log(`🔧 ${powerUpsCreated} Power-ups erstellt und Board aktualisiert`); + } + + return powerUpsCreated; }, // Bestimme den Raketen-Typ basierend auf der Match-Richtung @@ -1677,6 +1986,9 @@ export default { } } } + } else if (this.board[index] && this.isPowerUpTile(this.board[index].type)) { + // Position enthält bereits ein Power-up - nicht überschreiben + console.log(`🔧 Position [${row}, ${col}] enthält bereits Power-up ${this.board[index].type} - wird nicht überschrieben`); } } } @@ -2048,9 +2360,22 @@ export default { // Prüfe ob neue Matches entstanden sind const newMatches = this.findMatchesOnBoard(this.board, false); - if (newMatches.length > 0) { - console.log(`🔧 ${newMatches.length} neue Cascade-Matches gefunden`); - await this.handleMatches(newMatches, false); + // Filtere Power-up-Matches heraus (diese sollen nicht als Cascade-Matches behandelt werden) + const filteredMatches = newMatches.filter(match => { + if (match.type === 'l-shape') { + console.log('🔧 L-Form Match in Cascade gefunden - überspringe'); + return false; + } + if (Array.isArray(match) && match.length === 4) { + console.log('🔧 4er-Match in Cascade gefunden - überspringe'); + return false; + } + return true; + }); + + if (filteredMatches.length > 0) { + console.log(`🔧 ${filteredMatches.length} neue Cascade-Matches gefunden`); + await this.handleMatches(filteredMatches, false); } else { console.log('🔧 Keine neuen Cascade-Matches gefunden'); } @@ -2099,9 +2424,12 @@ export default { // Warte auf Animation (0,75 Sekunden) await this.wait(750); - // Prüfe ob der Move einen 3er-Match oder 4er-Match erzeugt hat - const matches = this.findMatchesOnBoard(this.board, false); - const hasValidMatch = matches.some(match => match.length >= 3); + // Prüfe ob der Move einen gültigen Match erzeugt hat + const matches = this.findMatchesOnBoard(this.board, false); + const hasValidMatch = matches.some(match => + (Array.isArray(match) && match.length >= 3) || + match.type === 'l-shape' + ); if (hasValidMatch) { console.log(`✅ Move erfolgreich - ${matches.length} Match(es) gefunden!`); @@ -3271,6 +3599,8 @@ export default { rainbow: '🌈', // Spezielle Items rocket: '🚀', + 'rocket-horizontal': '🚀', + 'rocket-vertical': '🚀', bomb: '💣' }; return symbols[type] || '❓'; @@ -3756,6 +4086,14 @@ export default { return; } + // Prüfe auf Bomben-Tiles (neue Power-ups) + if (tile.type === 'bomb') { + console.log(`💣 Doppelklick auf Bombe an Position ${index}`); + // Bombe durch Doppelklick aktivieren + await this.activateBombByDoubleClick(index); + return; + } + if (tile.isSpecial) { // Power-Up als Zug zählen this.countPowerUpMove(); @@ -3820,6 +4158,37 @@ export default { } }, + // Aktiviere Bombe durch Doppelklick + async activateBombByDoubleClick(bombIndex) { + console.log(`💣 Aktiviere Bombe durch Doppelklick an Position ${bombIndex}`); + + // Spiele Bomben-Sound + this.playSound('bomb'); + + // Zeige Bomben-Explosions-Animation + await this.showBombEffectAnimation(bombIndex); + + // Aktiviere die Bombe (3x3 Bereich) + this.explodeBomb(bombIndex, 1); + + // Entferne die Bombe selbst + console.log(`💣 Entferne Bombe an Position ${bombIndex}`); + this.board[bombIndex] = null; + + // Aktualisiere die Anzeige + this.$forceUpdate(); + + // Führe Fall-Down-Logik aus + await this.fallTilesDown(); + + // Fülle leere Positionen mit neuen Tiles auf + await this.fillEmptyPositions(); + + // Erhöhe den Zug-Zähler + this.moves++; + this.movesLeft--; + }, + // Neue Methode: Entferne alle Tiles eines bestimmten Typs removeAllTilesOfType(tileType) { const tilesToRemove = []; @@ -5378,6 +5747,20 @@ export default { font-weight: bold; } +/* Bomben-Power-ups */ +.game-tile.bomb { + background: linear-gradient(45deg, #ff6b6b, #ff8e53) !important; + position: relative; +} + +/* Bomben-Symbol */ +.bomb-symbol { + font-size: 24px; + color: white; + text-shadow: 2px 2px 4px rgba(0,0,0,0.5); + font-weight: bold; +} + /* Raketen-Explosions-Effekt */ .rocket-explosion { width: 80px;