feat(match3): Erweiterung der Power-Up-Mechanik mit Bomben und L-Form-Matches

- Hinzufügen von Bomben als neues Power-Up, das durch Doppelklick aktiviert werden kann.
- Implementierung der Logik zur Erkennung und Verarbeitung von L-Form-Matches.
- Anpassungen an der Spielmechanik zur Verhinderung von Matches mit Power-Ups.
- Verbesserung der Benutzeroberfläche zur Anzeige von Bomben und deren Effekten.
- Erweiterung der Debug-Ausgaben zur besseren Nachverfolgbarkeit von Power-Ups und Matches.
This commit is contained in:
Torsten Schulz (local)
2025-08-27 13:03:46 +02:00
parent b5f4e72de2
commit 9293ee31f7

View File

@@ -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)">
<span v-if="tile && !isRocketTile(tile.type)" class="tile-symbol">{{ getTileSymbol(tile.type) }}</span>
<span v-if="tile && !isPowerUpTile(tile.type)" class="tile-symbol">{{ getTileSymbol(tile.type) }}</span>
<span v-else-if="tile && isRocketTile(tile.type)" class="rocket-symbol">
🚀
</span>
<span v-else-if="tile && tile.type === 'bomb'" class="bomb-symbol">
💣
</span>
</div>
</template>
</div>
@@ -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;