```git commit message
Add match detection and jewel dropping functionality This commit implements the core matching logic for the gem matching game: - Added isDropping flag to prevent concurrent drop operations - Implemented checkMatches() function to detect horizontal and vertical matches of 3+ jewels - Added destroyMatchedJewels() function to animate and remove matched jewels - Implemented dropJewels() function to handle jewel dropping after matches are cleared - Integrated match checking into the swap completion callback - Added proper animation sequences with tweens and delayed calls for smooth gameplay The changes enable the core gem matching mechanics where matched jewels are destroyed, remaining jewels fall down to fill gaps, and new matches are automatically detected and processed. ```
This commit is contained in:
parent
e9cb2a939d
commit
53fe2280cb
213
src/GameScene.js
213
src/GameScene.js
|
|
@ -15,6 +15,7 @@ export class GameScene extends Phaser.Scene {
|
|||
this.startRows = 5;
|
||||
this.level = 1;
|
||||
this.levelTime = 60;
|
||||
this.isDropping = false;
|
||||
|
||||
// Add selectedJewel property
|
||||
this.selectedJewel = null;
|
||||
|
|
@ -252,7 +253,10 @@ export class GameScene extends Phaser.Scene {
|
|||
targets: this.swapWithJewel,
|
||||
x: fromX,
|
||||
y: fromY,
|
||||
duration: 300
|
||||
duration: 300,
|
||||
onComplete: () => {
|
||||
this.checkMatches();
|
||||
}
|
||||
});
|
||||
this.selectedJewel = null;
|
||||
this.swapWithJewel = null;
|
||||
|
|
@ -268,8 +272,213 @@ export class GameScene extends Phaser.Scene {
|
|||
|
||||
this.isSwapping = false;
|
||||
});
|
||||
}
|
||||
|
||||
// Check for Matches
|
||||
// Function to check for matches and destroy them
|
||||
checkMatches() {
|
||||
const matchedJewels = new Set();
|
||||
|
||||
// Check horizontal matches
|
||||
for (let row = 1; row <= this.gridConfig.rows; row++) {
|
||||
let count = 1;
|
||||
let currentType = this.getJewelAtPosition(1, row);
|
||||
|
||||
for (let col = 2; col <= this.gridConfig.cols; col++) {
|
||||
const jewelType = this.getJewelAtPosition(col, row);
|
||||
|
||||
if (jewelType === currentType && jewelType !== null) {
|
||||
count++;
|
||||
} else {
|
||||
if (count >= 3) {
|
||||
// Add all jewels in this match to the matched set
|
||||
for (let i = col - count; i < col; i++) {
|
||||
const key = `${i},${row}`;
|
||||
matchedJewels.add(key);
|
||||
}
|
||||
}
|
||||
count = 1;
|
||||
currentType = jewelType;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for match at the end of row
|
||||
if (count >= 3) {
|
||||
for (let i = this.gridConfig.cols - count + 1; i <= this.gridConfig.cols; i++) {
|
||||
const key = `${i},${row}`;
|
||||
matchedJewels.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check vertical matches
|
||||
for (let col = 1; col <= this.gridConfig.cols; col++) {
|
||||
let count = 1;
|
||||
let currentType = this.getJewelAtPosition(col, 0);
|
||||
|
||||
for (let row = 1; row <= this.gridConfig.rows; row++) {
|
||||
const jewelType = this.getJewelAtPosition(col, row);
|
||||
|
||||
if (jewelType === currentType && jewelType !== null) {
|
||||
count++;
|
||||
} else {
|
||||
if (count >= 3) {
|
||||
// Add all jewels in this match to the matched set
|
||||
for (let i = row - count; i < row; i++) {
|
||||
const key = `${col},${i}`;
|
||||
matchedJewels.add(key);
|
||||
}
|
||||
}
|
||||
count = 1;
|
||||
currentType = jewelType;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for match at the end of column
|
||||
if (count >= 3) {
|
||||
for (let i = this.gridConfig.rows - count + 1; i <= this.gridConfig.rows; i++) {
|
||||
const key = `${col},${i}`;
|
||||
matchedJewels.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we found matches, destroy them
|
||||
if (matchedJewels.size > 0) {
|
||||
this.destroyMatchedJewels(matchedJewels);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Function to destroy matched jewels
|
||||
destroyMatchedJewels(matchedJewels) {
|
||||
// Create an array of jewels to destroy
|
||||
const jewelsToDestroy = [];
|
||||
|
||||
this.jewels.children.iterate((jewel) => {
|
||||
if (jewel) {
|
||||
const col = Math.floor((jewel.x - this.gridConfig.leftPadding) / this.gridConfig.jewelWidth);
|
||||
const row = Math.floor(jewel.y / this.gridConfig.jewelHeight);
|
||||
const key = `${col},${row}`;
|
||||
|
||||
if (matchedJewels.has(key)) {
|
||||
jewelsToDestroy.push(jewel);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Animate destruction
|
||||
jewelsToDestroy.forEach((jewel) => {
|
||||
this.tweens.add({
|
||||
targets: jewel,
|
||||
scaleX: 0,
|
||||
scaleY: 0,
|
||||
alpha: 0,
|
||||
duration: 200,
|
||||
onComplete: () => {
|
||||
jewel.destroy();
|
||||
this.time.delayedCall(100, () => {
|
||||
this.dropJewels();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
dropJewels() {
|
||||
if (this.isDropping) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isDropping = true;
|
||||
console.log('drop');
|
||||
|
||||
// Create a grid representation to track jewel positions
|
||||
const grid = [];
|
||||
for (let row = 1; row <= this.gridConfig.rows; row++) {
|
||||
grid[row] = [];
|
||||
for (let col = 1; col <= this.gridConfig.cols; col++) {
|
||||
grid[row][col] = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Populate the grid with jewel positions
|
||||
this.jewels.children.iterate((jewel) => {
|
||||
if (jewel) {
|
||||
const col = Math.floor((jewel.x - this.gridConfig.leftPadding) / this.gridConfig.jewelWidth);
|
||||
const row = Math.floor(jewel.y / this.gridConfig.jewelHeight);
|
||||
|
||||
// Ensure we're within grid bounds
|
||||
if (col >= 1 && col <= this.gridConfig.cols && row >= 1 && row <= this.gridConfig.rows) {
|
||||
grid[row][col] = jewel;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Find jewels that need to drop and their target positions
|
||||
const jewelsToDrop = [];
|
||||
|
||||
for (let col = 1; col <= this.gridConfig.cols; col++) {
|
||||
let emptySpaces = 0;
|
||||
|
||||
// Process from bottom to top
|
||||
for (let row = this.gridConfig.rows; row >= 1; row--) {
|
||||
if (grid[row][col] === null) {
|
||||
emptySpaces++;
|
||||
} else if (emptySpaces > 0) {
|
||||
// This jewel needs to drop
|
||||
const jewel = grid[row][col];
|
||||
const targetRow = row + emptySpaces;
|
||||
|
||||
jewelsToDrop.push({
|
||||
jewel: jewel,
|
||||
fromRow: row,
|
||||
toRow: targetRow
|
||||
});
|
||||
|
||||
// Update grid reference
|
||||
grid[row][col] = null;
|
||||
grid[targetRow][col] = jewel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If no jewels need to drop, we're done
|
||||
if (jewelsToDrop.length === 0) {
|
||||
this.isDropping = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Animate the dropping
|
||||
let droppedCount = 0;
|
||||
|
||||
jewelsToDrop.forEach((dropInfo) => {
|
||||
const { jewel, fromRow, toRow } = dropInfo;
|
||||
|
||||
// Calculate target y position
|
||||
const targetY = toRow * this.gridConfig.jewelHeight;
|
||||
|
||||
// Animate the jewel dropping
|
||||
this.tweens.add({
|
||||
targets: jewel,
|
||||
y: targetY,
|
||||
duration: 300,
|
||||
ease: 'Linear',
|
||||
onComplete: () => {
|
||||
droppedCount++;
|
||||
|
||||
// When all jewels have dropped, check for new matches
|
||||
if (droppedCount === jewelsToDrop.length) {
|
||||
this.time.delayedCall(100, () => {
|
||||
this.isDropping = false;
|
||||
// Check for new matches after dropping
|
||||
this.checkMatches();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue