Big Update
This commit is contained in:
parent
53fe2280cb
commit
f409413e8d
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 2.1 MiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
358
src/GameScene.js
358
src/GameScene.js
|
|
@ -1,3 +1,5 @@
|
|||
import { LEVEL_CONFIG } from './config.js';
|
||||
|
||||
export class GameScene extends Phaser.Scene {
|
||||
constructor() {
|
||||
super({ key: 'GameScene' });
|
||||
|
|
@ -11,15 +13,29 @@ export class GameScene extends Phaser.Scene {
|
|||
jewelHeight: 100,
|
||||
};
|
||||
|
||||
this.numberOfJewels = 5;
|
||||
this.startRows = 5;
|
||||
// Stats
|
||||
this.numberOfJewels = 4;
|
||||
this.startRows = 3;
|
||||
this.level = 1;
|
||||
this.levelTime = 60;
|
||||
this.matchesNeeded = 10;
|
||||
this.score = 0;
|
||||
this.ally = 'goblin';
|
||||
|
||||
// Status Indication
|
||||
this.isDropping = false;
|
||||
this.isSwapping = false;
|
||||
this.isDestroying = false;
|
||||
this.isMovingUp = false;
|
||||
this.isPlayingVideo = false;
|
||||
|
||||
// Add selectedJewel property
|
||||
this.selectedJewel = null;
|
||||
this.swapWithJewel = null;
|
||||
|
||||
// Timer properties
|
||||
this.moveTimer = 0;
|
||||
this.moveInterval = 12000;
|
||||
this.timerText = null;
|
||||
}
|
||||
|
||||
preload() {
|
||||
|
|
@ -27,6 +43,13 @@ export class GameScene extends Phaser.Scene {
|
|||
frameWidth: 100,
|
||||
frameHeight: 100
|
||||
});
|
||||
this.load.font('cruiser', 'assets/NEUROPOL.ttf');
|
||||
this.load.font('code', 'assets/CodePredators-Regular.otf');
|
||||
|
||||
this.load.video('goblin-resting', 'assets/goblin-resting.mp4');
|
||||
this.load.video('goblin-excited', 'assets/goblin-excited.mp4');
|
||||
this.load.video('goblin-pleased', 'assets/goblin-pleased.mp4');
|
||||
this.load.video('goblin-match', 'assets/goblin-match.mp4');
|
||||
}
|
||||
|
||||
create() {
|
||||
|
|
@ -37,10 +60,79 @@ export class GameScene extends Phaser.Scene {
|
|||
});
|
||||
this.physics.add.collider(this.jewels, this.jewels);
|
||||
this.createStart();
|
||||
|
||||
// Create the score text
|
||||
this.scoreText = this.add.text(20, 50, 'Score: 0', {
|
||||
fontFamily: 'cruiser, arial',
|
||||
fontSize: '36px',
|
||||
fill: '#ffffff',
|
||||
padding: {
|
||||
left: 10,
|
||||
right: 10,
|
||||
top: 5,
|
||||
bottom: 5
|
||||
}
|
||||
}).setOrigin(0);
|
||||
|
||||
// Create the Level text
|
||||
this.LevelText = this.add.text(20, 116, `Level: ${this.level}`, {
|
||||
fontFamily: 'cruiser, arial',
|
||||
fontSize: '36px',
|
||||
fill: '#ffffff',
|
||||
padding: {
|
||||
left: 10,
|
||||
right: 10,
|
||||
top: 5,
|
||||
bottom: 5
|
||||
}
|
||||
}).setOrigin(0);
|
||||
|
||||
// Create the timer text
|
||||
this.timerText = this.add.text(20, 182, 'Next Row:', {
|
||||
fontFamily: 'cruiser, arial',
|
||||
fontSize: '36px',
|
||||
fill: '#ffffff',
|
||||
padding: {
|
||||
left: 10,
|
||||
right: 10,
|
||||
top: 5,
|
||||
bottom: 5
|
||||
}
|
||||
}).setOrigin(0);
|
||||
|
||||
// Create the Matches Needed text
|
||||
this.matchesText = this.add.text(20, 248, `Remaining Matches: ${this.matchesNeeded}`, {
|
||||
fontFamily: 'cruiser, arial',
|
||||
fontSize: '36px',
|
||||
fill: '#ffffff',
|
||||
padding: {
|
||||
left: 10,
|
||||
right: 10,
|
||||
top: 5,
|
||||
bottom: 5
|
||||
}
|
||||
}).setOrigin(0);
|
||||
|
||||
this.allyVideo = this.add.video(350, 610, `${this.ally}-resting`).setOrigin(0.5);
|
||||
this.allyVideo.play(true);
|
||||
}
|
||||
|
||||
update(time, delta) {
|
||||
|
||||
// Update the move timer
|
||||
this.moveTimer += delta;
|
||||
|
||||
// Check if it's time to move all jewels up
|
||||
if (this.moveTimer >= this.moveInterval && this.isDropping === false && this.isSwapping === false && this.isDestroying === false) {
|
||||
this.moveAllJewelsUp();
|
||||
this.moveTimer = 0; // Reset the timer
|
||||
}
|
||||
|
||||
// Update the timer display
|
||||
const timeRemaining = (this.moveInterval - this.moveTimer) / 1000;
|
||||
const displayTime = timeRemaining.toFixed(2);
|
||||
if (this.timerText) {
|
||||
this.timerText.setText(`Next Row: ${displayTime}`);
|
||||
}
|
||||
}
|
||||
|
||||
makeGrid() {
|
||||
|
|
@ -228,6 +320,12 @@ export class GameScene extends Phaser.Scene {
|
|||
|
||||
// Modified swap function to disable clicks during execution
|
||||
swapJewel() {
|
||||
if (this.isMovingUp === true) {
|
||||
this.time.delayedCall(300, ()=> {
|
||||
this.swapJewel();
|
||||
})
|
||||
return;
|
||||
}
|
||||
// Set swapping flag to prevent new clicks from being processed
|
||||
this.isSwapping = true;
|
||||
|
||||
|
|
@ -263,7 +361,7 @@ export class GameScene extends Phaser.Scene {
|
|||
|
||||
|
||||
// After swap completes, re-enable interactivity and reset flag
|
||||
this.time.delayedCall(500, () => { // Adjust delay as needed for animation duration
|
||||
this.time.delayedCall(300, () => { // Adjust delay as needed for animation duration
|
||||
this.jewels.children.iterate((jewel) => {
|
||||
if (jewel) {
|
||||
jewel.setInteractive();
|
||||
|
|
@ -274,6 +372,60 @@ export class GameScene extends Phaser.Scene {
|
|||
});
|
||||
}
|
||||
|
||||
reduceMatches(amount) {
|
||||
this.matchesNeeded -= amount;
|
||||
if (this.matchesNeeded <= 0) {
|
||||
this.levelUp();
|
||||
}
|
||||
this.matchesText.setText(`Matches Needed: ${this.matchesNeeded}`);
|
||||
}
|
||||
|
||||
levelUp() {
|
||||
this.level ++;
|
||||
const newLevel = LEVEL_CONFIG[this.level];
|
||||
this.numberOfJewels = newLevel.numberOfJewels;
|
||||
this.matchesNeeded = newLevel.matchesNeeded;
|
||||
this.moveInterval = newLevel.moveInterval;
|
||||
this.LevelText.setText(`Level: ${this.level}`);
|
||||
|
||||
// Create the New Level text
|
||||
const newLevelText = this.add.text(1150, 250, `Level ${this.level}`, {
|
||||
fontFamily: 'code, arial',
|
||||
fontSize: '100px',
|
||||
fill: '#ea00ffff',
|
||||
padding: {
|
||||
left: 10,
|
||||
right: 10,
|
||||
top: 5,
|
||||
bottom: 5
|
||||
}
|
||||
}).setOrigin(0.5);
|
||||
|
||||
// Add cool eye-catching effect
|
||||
this.tweens.add({
|
||||
targets: newLevelText,
|
||||
scale: { from: 0.5, to: 1.5 },
|
||||
alpha: { from: 0, to: 1 },
|
||||
duration: 1000,
|
||||
ease: 'Back.easeOut',
|
||||
yoyo: true
|
||||
});
|
||||
|
||||
// Fade out and destroy after 500ms
|
||||
this.time.delayedCall(1200, () => {
|
||||
this.tweens.add({
|
||||
targets: newLevelText,
|
||||
angle: 360,
|
||||
scale: 0,
|
||||
alpha: 0,
|
||||
duration: 500,
|
||||
onComplete: () => {
|
||||
newLevelText.destroy();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Function to check for matches and destroy them
|
||||
checkMatches() {
|
||||
const matchedJewels = new Set();
|
||||
|
|
@ -290,6 +442,7 @@ export class GameScene extends Phaser.Scene {
|
|||
count++;
|
||||
} else {
|
||||
if (count >= 3) {
|
||||
this.reduceMatches(1);
|
||||
// Add all jewels in this match to the matched set
|
||||
for (let i = col - count; i < col; i++) {
|
||||
const key = `${i},${row}`;
|
||||
|
|
@ -303,6 +456,7 @@ export class GameScene extends Phaser.Scene {
|
|||
|
||||
// Check for match at the end of row
|
||||
if (count >= 3) {
|
||||
this.reduceMatches(1);
|
||||
for (let i = this.gridConfig.cols - count + 1; i <= this.gridConfig.cols; i++) {
|
||||
const key = `${i},${row}`;
|
||||
matchedJewels.add(key);
|
||||
|
|
@ -322,6 +476,7 @@ export class GameScene extends Phaser.Scene {
|
|||
count++;
|
||||
} else {
|
||||
if (count >= 3) {
|
||||
this.reduceMatches(1);
|
||||
// Add all jewels in this match to the matched set
|
||||
for (let i = row - count; i < row; i++) {
|
||||
const key = `${col},${i}`;
|
||||
|
|
@ -335,6 +490,7 @@ export class GameScene extends Phaser.Scene {
|
|||
|
||||
// Check for match at the end of column
|
||||
if (count >= 3) {
|
||||
this.reduceMatches(1);
|
||||
for (let i = this.gridConfig.rows - count + 1; i <= this.gridConfig.rows; i++) {
|
||||
const key = `${col},${i}`;
|
||||
matchedJewels.add(key);
|
||||
|
|
@ -342,8 +498,14 @@ export class GameScene extends Phaser.Scene {
|
|||
}
|
||||
}
|
||||
|
||||
// If we found matches, destroy them
|
||||
// If we found matches, destroy them and play video
|
||||
if (matchedJewels.size > 0) {
|
||||
this.playVideo(matchedJewels.size);
|
||||
const scoreMatches = matchedJewels.size / 3;
|
||||
const scoreAdd = Math.ceil(scoreMatches ** 2) * 10;
|
||||
this.score += scoreAdd;
|
||||
this.scoreText.setText(`Score: ${this.score}`);
|
||||
// ADD SCORE
|
||||
this.destroyMatchedJewels(matchedJewels);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -351,8 +513,37 @@ export class GameScene extends Phaser.Scene {
|
|||
return false;
|
||||
}
|
||||
|
||||
playVideo(amount) {
|
||||
if (this.isPlayingVideo === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isPlayingVideo = true;
|
||||
let video = null;
|
||||
|
||||
if (amount >= 5) {
|
||||
video = `${this.ally}-excited`;
|
||||
} else if (amount >= 4) {
|
||||
video = `${this.ally}-pleased`;
|
||||
} else {
|
||||
video = `${this.ally}-match`;
|
||||
}
|
||||
const showVideo = this.add.video(350, 610, video).setOrigin(0.5).setDepth(100);
|
||||
showVideo.play(false);
|
||||
this.time.delayedCall(5000, () => {
|
||||
this.isPlayingVideo = false;
|
||||
showVideo.destroy();
|
||||
console.log('end video');
|
||||
});
|
||||
}
|
||||
|
||||
// Function to destroy matched jewels
|
||||
destroyMatchedJewels(matchedJewels) {
|
||||
if (this.isDestroying) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isDestroying = true;
|
||||
// Create an array of jewels to destroy
|
||||
const jewelsToDestroy = [];
|
||||
|
||||
|
|
@ -379,6 +570,7 @@ export class GameScene extends Phaser.Scene {
|
|||
onComplete: () => {
|
||||
jewel.destroy();
|
||||
this.time.delayedCall(100, () => {
|
||||
this.isDestroying = false;
|
||||
this.dropJewels();
|
||||
});
|
||||
}
|
||||
|
|
@ -392,7 +584,6 @@ export class GameScene extends Phaser.Scene {
|
|||
}
|
||||
|
||||
this.isDropping = true;
|
||||
console.log('drop');
|
||||
|
||||
// Create a grid representation to track jewel positions
|
||||
const grid = [];
|
||||
|
|
@ -481,4 +672,157 @@ export class GameScene extends Phaser.Scene {
|
|||
});
|
||||
}
|
||||
|
||||
// Function to move all jewels up one row
|
||||
moveAllJewelsUp() {
|
||||
this.isMovingUp = true;
|
||||
// Check if any jewel is at row 1 (topmost) that would go to row 0
|
||||
let gameOver = false;
|
||||
|
||||
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);
|
||||
|
||||
// If jewel is at row 1 and would move up to row 0, game over
|
||||
if (row === 1 && col >= 1 && col <= this.gridConfig.cols) {
|
||||
gameOver = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// If game over, end the game
|
||||
if (gameOver) {
|
||||
this.gameOver();
|
||||
return;
|
||||
}
|
||||
|
||||
// Move all jewels up one row
|
||||
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);
|
||||
|
||||
// Only move jewels that are not at the top row
|
||||
if (row > 1 && col >= 1 && col <= this.gridConfig.cols) {
|
||||
const targetRow = row - 1;
|
||||
const targetY = targetRow * this.gridConfig.jewelHeight;
|
||||
|
||||
// Animate the jewel moving up
|
||||
this.tweens.add({
|
||||
targets: jewel,
|
||||
y: targetY,
|
||||
duration: 300,
|
||||
ease: 'Linear'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Create new bottom row after moving all jewels up
|
||||
this.time.delayedCall(300, () => {
|
||||
this.isMovingUp = false;
|
||||
this.createBottomRow();
|
||||
});
|
||||
}
|
||||
|
||||
// Function to create a new row of jewels at the bottom
|
||||
createBottomRow() {
|
||||
const newRow = 8;
|
||||
let jewelDelay = 0;
|
||||
|
||||
for (let col = 1; col <= this.gridConfig.cols; col++) {
|
||||
let type = null;
|
||||
let match = false;
|
||||
|
||||
do {
|
||||
type = Phaser.Math.Between(0, this.numberOfJewels - 1);
|
||||
match = false;
|
||||
|
||||
// Check horizontal matches in the new row
|
||||
if (col >= 3) {
|
||||
// Check if this would create a horizontal match of 3 or more
|
||||
const leftType = this.getJewelAtPosition(col-1, newRow);
|
||||
const leftLeftType = this.getJewelAtPosition(col-2, newRow);
|
||||
|
||||
if (leftType === type && leftLeftType === type) {
|
||||
match = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check vertical matches in the columns above
|
||||
if (newRow <= this.gridConfig.rows) {
|
||||
const aboveType = this.getJewelAtPosition(col, newRow - 1);
|
||||
|
||||
if (aboveType === type) {
|
||||
// Check if there's a match of 3 or more by looking at additional positions
|
||||
let count = 1;
|
||||
|
||||
// Look up to see how many matching jewels we have in the column
|
||||
for (let row = newRow - 2; row < this.gridConfig.rows; row++) {
|
||||
const jewelType = this.getJewelAtPosition(col, row);
|
||||
if (jewelType === type) {
|
||||
count++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have 3 or more in a vertical line, it's a match
|
||||
if (count >= 3) {
|
||||
match = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Also check for matches with jewels above the new row (if they exist)
|
||||
if (newRow < this.gridConfig.rows && col <= this.gridConfig.cols) {
|
||||
const jewelAbove = this.getJewelAtPosition(col, newRow - 1);
|
||||
|
||||
if (jewelAbove !== null) {
|
||||
// Check horizontal match with jewels in the same row
|
||||
let count = 0;
|
||||
|
||||
// Look left to see how many matching jewels we have in that row
|
||||
for (let c = col - 1; c >= 1; c--) {
|
||||
const jewelType = this.getJewelAtPosition(c, newRow);
|
||||
if (jewelType === type) {
|
||||
count++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Look right to see how many matching jewels we have in that row
|
||||
for (let c = col + 1; c <= this.gridConfig.cols; c++) {
|
||||
const jewelType = this.getJewelAtPosition(c, newRow);
|
||||
if (jewelType === type) {
|
||||
count++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have at least 2 matching jewels in the row and one more above,
|
||||
// or any other match scenario that creates a 3-in-a-row
|
||||
if (count >= 2 && jewelAbove === type) {
|
||||
match = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} while (match === true);
|
||||
|
||||
// Create the jewel at the correct position
|
||||
this.createJewel(type, col, newRow);
|
||||
}
|
||||
}
|
||||
|
||||
// Game over function
|
||||
gameOver() {
|
||||
console.log('Game Over!');
|
||||
// Add game over logic here (e.g., show game over screen, reset game, etc.)
|
||||
|
||||
// For now, just restart the scene
|
||||
this.scene.restart();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,17 @@
|
|||
export const GRID_CONFIG = {
|
||||
rows: 8,
|
||||
cols: 8,
|
||||
jewelWidth: 100,
|
||||
jewelHeight: 100,
|
||||
export const LEVEL_CONFIG = {
|
||||
1: {
|
||||
numberOfJewels: 4,
|
||||
matchesNeeded: 12,
|
||||
moveInterval: 12000
|
||||
},
|
||||
2: {
|
||||
numberOfJewels: 5,
|
||||
matchesNeeded: 12,
|
||||
moveInterval: 12000
|
||||
},
|
||||
3: {
|
||||
numberOfJewels: 5,
|
||||
matchesNeeded: 12,
|
||||
moveInterval: 11000
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue