diff --git a/frontend/src/views/minigames/Match3Game.vue b/frontend/src/views/minigames/Match3Game.vue
index dd0610a..e2e5697 100644
--- a/frontend/src/views/minigames/Match3Game.vue
+++ b/frontend/src/views/minigames/Match3Game.vue
@@ -143,6 +143,20 @@
+
+
+
+
+
+
+
+
@@ -326,6 +340,10 @@ export default {
rainbowCenter: { x: 0, y: 0 },
showBombEffect: false,
bombCenter: { x: 0, y: 0 },
+ showRocketEffect: false,
+ rocketCenter: { x: 0, y: 0 },
+ rocketTarget: { x: -1, y: -1 },
+ showFlyingRocket: false,
// Sound-Effekte
sounds: {
@@ -2058,6 +2076,18 @@ export default {
return false;
}
+ // PrĂĽfe ob ein Tile eine Rakete ist
+ if (this.isRocketTile(this.board[fromIndex].type) || this.isRocketTile(this.board[toIndex].type)) {
+ console.log('🚀 Rakete wird aktiviert!');
+ return await this.activateRocket(fromIndex, toIndex);
+ }
+
+ // PrĂĽfe ob das Ziel ein leeres Feld ist
+ if (!this.board[toIndex]) {
+ console.log('⚠️ Verschieben auf leeres Feld nicht erlaubt');
+ return false;
+ }
+
// FĂĽhre den Tausch durch
const tempTile = { ...this.board[fromIndex] };
this.board[fromIndex] = { ...this.board[toIndex] };
@@ -2088,6 +2118,187 @@ export default {
}
},
+ // Aktiviere eine Rakete (durch Verschieben oder Doppelklick)
+ async activateRocket(rocketIndex, targetIndex) {
+ console.log(`🚀 Aktiviere Rakete an Position ${rocketIndex}`);
+
+ // Bestimme das Zentrum der Raketen-Explosion
+ let explosionCenter;
+ let tilesToRemove = new Set();
+
+ if (this.isRocketTile(this.board[rocketIndex].type)) {
+ // Rakete wird auf ein Nachbarfeld verschoben
+ explosionCenter = targetIndex;
+ tilesToRemove = this.getRocketExplosionTiles(targetIndex);
+ } else {
+ // Ein Tile wird auf die Rakete verschoben
+ explosionCenter = rocketIndex;
+ tilesToRemove = this.getRocketExplosionTiles(rocketIndex);
+ }
+
+ // Entferne die Tiles um das Explosionszentrum
+ if (tilesToRemove.size > 0) {
+ console.log(`🚀 Entferne ${tilesToRemove.size} Tiles um Position ${explosionCenter}`);
+
+ // Starte Schrumpf-Animation fĂĽr alle zu entfernenden Tiles
+ await this.animateTileRemoval(Array.from(tilesToRemove));
+
+ // Entferne alle Tiles nach der Animation
+ tilesToRemove.forEach(index => {
+ if (this.board[index]) {
+ console.log(`🚀 Entferne Tile ${this.board[index].type} an Position ${index}`);
+ this.board[index] = null;
+ }
+ });
+
+ // Entferne auch die Rakete selbst
+ if (this.isRocketTile(this.board[rocketIndex].type)) {
+ console.log(`🚀 Entferne Rakete an Position ${rocketIndex}`);
+ this.board[rocketIndex] = null;
+ }
+
+ // Aktualisiere die Anzeige
+ this.$forceUpdate();
+
+ // Zeige Raketen-Explosions-Animation
+ await this.showRocketExplosionAnimation(explosionCenter);
+
+ // 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--;
+
+ return true;
+ }
+
+ return false;
+ },
+
+ // Hole alle Tiles, die von der Raketen-Explosion betroffen sind
+ getRocketExplosionTiles(centerIndex) {
+ const tilesToRemove = new Set();
+ const centerPos = this.indexToCoords(centerIndex);
+
+ // PrĂĽfe alle 4 Richtungen: oben, unten, links, rechts
+ const directions = [
+ { row: -1, col: 0 }, // oben
+ { row: 1, col: 0 }, // unten
+ { row: 0, col: -1 }, // links
+ { row: 0, col: 1 } // rechts
+ ];
+
+ directions.forEach(dir => {
+ const newRow = centerPos.row + dir.row;
+ const newCol = centerPos.col + dir.col;
+
+ if (this.isValidPosition(newRow, newCol)) {
+ const newIndex = this.coordsToIndex(newRow, newCol);
+ if (newIndex !== null && this.board[newIndex] && !this.isRocketTile(this.board[newIndex].type)) {
+ tilesToRemove.add(newIndex);
+ }
+ }
+ });
+
+ return tilesToRemove;
+ },
+
+ // Zeige Raketen-Explosions-Animation
+ async showRocketExplosionAnimation(centerIndex) {
+ const centerPos = this.indexToCoords(centerIndex);
+ const tileElement = document.querySelector(`[data-index="${centerIndex}"]`);
+
+ if (tileElement) {
+ const rect = tileElement.getBoundingClientRect();
+ this.rocketCenter = { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
+ }
+
+ // Zeige Explosions-Animation
+ this.showRocketEffect = true;
+ this.playSound('rocket');
+
+ // Warte auf Animation
+ await this.wait(1000);
+
+ // Verstecke Animation
+ this.showRocketEffect = false;
+
+ // Rakete fliegt zu einem zufälligen belegten Feld
+ await this.rocketFlightToRandomTile();
+ },
+
+ // Rakete fliegt zu einem zufälligen belegten Feld
+ async rocketFlightToRandomTile() {
+ // Finde alle belegten Felder
+ const occupiedTiles = [];
+ for (let i = 0; i < this.board.length; i++) {
+ if (this.board[i] && !this.isRocketTile(this.board[i].type)) {
+ occupiedTiles.push(i);
+ }
+ }
+
+ if (occupiedTiles.length > 0) {
+ // Wähle ein zufälliges belegtes Feld
+ const randomTargetIndex = occupiedTiles[Math.floor(Math.random() * occupiedTiles.length)];
+ const targetPos = this.indexToCoords(randomTargetIndex);
+
+ console.log(`🚀 Rakete fliegt zu Position [${targetPos.row}, ${targetPos.col}]`);
+
+ // Zeige Flug-Animation
+ await this.showRocketFlightAnimation(randomTargetIndex);
+
+ // Entferne das Ziel-Tile nach der Animation
+ this.board[randomTargetIndex] = null;
+ console.log(`🚀 Ziel-Tile an Position ${randomTargetIndex} entfernt`);
+
+ // Aktualisiere die Anzeige
+ this.$forceUpdate();
+ }
+ },
+
+ // Zeige Raketen-Flug-Animation
+ async showRocketFlightAnimation(targetIndex) {
+ const targetPos = this.indexToCoords(targetIndex);
+ const targetElement = document.querySelector(`[data-index="${targetIndex}"]`);
+
+ if (targetElement) {
+ const rect = targetElement.getBoundingClientRect();
+ this.rocketTarget = { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
+ }
+
+ // Zeige Flug-Animation
+ console.log(`🚀 Rakete fliegt zu Ziel...`);
+
+ // Zeige die fliegende Rakete
+ this.showFlyingRocket = true;
+
+ // Berechne die Flug-Distanz
+ const flyX = this.rocketTarget.x - this.rocketCenter.x;
+ const flyY = this.rocketTarget.y - this.rocketCenter.y;
+
+ // Setze CSS-Variablen fĂĽr die Flug-Animation
+ const flyingRocketElement = document.querySelector('.flying-rocket');
+ if (flyingRocketElement) {
+ flyingRocketElement.style.setProperty('--fly-x', `${flyX}px`);
+ flyingRocketElement.style.setProperty('--fly-y', `${flyY}px`);
+ }
+
+ // Warte auf Flug-Animation (1 Sekunde)
+ await this.wait(1000);
+
+ // Verstecke die fliegende Rakete
+ this.showFlyingRocket = false;
+
+ console.log(`🚀 Rakete erreicht Ziel und zerstört es`);
+
+ // Aktualisiere die Anzeige
+ this.$forceUpdate();
+ },
+
// Hilfsmethode: Warte fĂĽr eine bestimmte Zeit
wait(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
@@ -3530,13 +3741,21 @@ export default {
},
// Neue Methode: Behandle Doppelklick auf Power-Up Tiles
- handleDoubleClick(index, event) {
+ async handleDoubleClick(index, event) {
event.preventDefault();
event.stopPropagation();
const tile = this.board[index];
if (!tile) return;
+ // PrĂĽfe auf Raketen-Tiles (neue Power-ups)
+ if (this.isRocketTile(tile.type)) {
+ console.log(`🚀 Doppelklick auf Rakete ${tile.type} an Position ${index}`);
+ // Rakete durch Doppelklick aktivieren
+ await this.activateRocketByDoubleClick(index);
+ return;
+ }
+
if (tile.isSpecial) {
// Power-Up als Zug zählen
this.countPowerUpMove();
@@ -3556,8 +3775,51 @@ export default {
this.handleRocketDoubleClick(index);
}
}
+ },
+
+ // Aktiviere Rakete durch Doppelklick
+ async activateRocketByDoubleClick(rocketIndex) {
+ console.log(`🚀 Aktiviere Rakete durch Doppelklick an Position ${rocketIndex}`);
+
+ // Hole alle Tiles um die Rakete herum
+ const tilesToRemove = this.getRocketExplosionTiles(rocketIndex);
+
+ if (tilesToRemove.size > 0) {
+ console.log(`🚀 Entferne ${tilesToRemove.size} Tiles um Rakete herum`);
+
+ // Starte Schrumpf-Animation fĂĽr alle zu entfernenden Tiles
+ await this.animateTileRemoval(Array.from(tilesToRemove));
+
+ // Entferne alle Tiles nach der Animation
+ tilesToRemove.forEach(index => {
+ if (this.board[index]) {
+ console.log(`🚀 Entferne Tile ${this.board[index].type} an Position ${index}`);
+ this.board[index] = null;
+ }
+ });
+
+ // Entferne auch die Rakete selbst
+ console.log(`🚀 Entferne Rakete an Position ${rocketIndex}`);
+ this.board[rocketIndex] = null;
+
+ // Aktualisiere die Anzeige
+ this.$forceUpdate();
+
+ // Zeige Raketen-Explosions-Animation
+ await this.showRocketExplosionAnimation(rocketIndex);
+
+ // 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 = [];
@@ -5116,6 +5378,100 @@ export default {
font-weight: bold;
}
+/* Raketen-Explosions-Effekt */
+.rocket-explosion {
+ width: 80px;
+ height: 80px;
+ background: radial-gradient(circle, #ff6b6b, #ffd93d, #ff6b6b);
+ border-radius: 50%;
+ animation: rocketExplosion 1s ease-out forwards;
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 24px;
+}
+
+@keyframes rocketExplosion {
+ 0% {
+ transform: scale(0.1);
+ opacity: 0;
+ }
+ 50% {
+ transform: scale(1.2);
+ opacity: 1;
+ }
+ 100% {
+ transform: scale(1);
+ opacity: 0;
+ }
+}
+
+/* Raketen-Flug-Animation */
+.rocket-flight-animation {
+ position: fixed;
+ z-index: 2000;
+ pointer-events: none;
+}
+
+.rocket-flight {
+ width: 40px;
+ height: 40px;
+ background: white;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 20px;
+ animation: rocketFlight 1s ease-in-out forwards;
+}
+
+@keyframes rocketFlight {
+ 0% {
+ transform: scale(0.5);
+ opacity: 0;
+ }
+ 50% {
+ transform: scale(1);
+ opacity: 1;
+ }
+ 100% {
+ transform: scale(0.8);
+ opacity: 0;
+ }
+}
+
+/* Fliegende Rakete */
+.flying-rocket {
+ position: fixed;
+ z-index: 2000;
+ pointer-events: none;
+ animation: rocketFly 1s ease-in-out forwards;
+}
+
+.rocket-icon {
+ width: 40px;
+ height: 40px;
+ background: white;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 20px;
+ box-shadow: 0 0 10px rgba(255, 107, 107, 0.8);
+}
+
+@keyframes rocketFly {
+ 0% {
+ transform: translate(0, 0) scale(1);
+ opacity: 1;
+ }
+ 100% {
+ transform: translate(var(--fly-x), var(--fly-y)) scale(0.8);
+ opacity: 0;
+ }
+}
+
@keyframes newTileAppear {
0% {
transform: scale(0.1);