Two Levels and polish
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 228 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 2.1 MiB |
|
Before Width: | Height: | Size: 348 KiB After Width: | Height: | Size: 715 KiB |
|
After Width: | Height: | Size: 384 KiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 1.9 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 937 B |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 15 KiB |
134
src/GameScene.js
|
|
@ -3,6 +3,16 @@ import { LEVEL_CONFIG } from './config.js';
|
|||
export class GameScene extends Phaser.Scene {
|
||||
constructor() {
|
||||
super({ key: 'GameScene' });
|
||||
}
|
||||
|
||||
init(data) {
|
||||
this.level = 1;
|
||||
|
||||
// Receive data passed from MenuScene
|
||||
if (data && data.level !== undefined) {
|
||||
this.level = data.level;
|
||||
console.log('Current level received:', this.currentLevel);
|
||||
}
|
||||
|
||||
this.gridConfig = {
|
||||
allPadding: 50,
|
||||
|
|
@ -16,7 +26,6 @@ export class GameScene extends Phaser.Scene {
|
|||
// Stats
|
||||
this.numberOfJewels = 4;
|
||||
this.startRows = 5;
|
||||
this.level = 1;
|
||||
this.matchesNeeded = 8;
|
||||
this.score = 0;
|
||||
this.ally = 'goblin';
|
||||
|
|
@ -65,7 +74,7 @@ export class GameScene extends Phaser.Scene {
|
|||
this.load.audio('alarm', 'assets/alarm.mp3');
|
||||
|
||||
// Ally Assets
|
||||
const allys = ['goblin', 'surfer', 'bear', 'wizard'];
|
||||
const allys = ['goblin', 'surfer', 'bear', 'wizard', 'steam', 'shark'];
|
||||
allys.forEach((ally) => {
|
||||
this.load.video(`${ally}-resting`, `assets/${ally}-resting.mp4`);
|
||||
this.load.video(`${ally}-excited`, `assets/${ally}-excited.mp4`);
|
||||
|
|
@ -344,7 +353,7 @@ export class GameScene extends Phaser.Scene {
|
|||
// Modified swap function to disable clicks during execution
|
||||
moveJewel(x ,y) {
|
||||
if (this.isMovingUp === true) {
|
||||
this.time.delayedCall(1000, ()=> {
|
||||
this.time.delayedCall(1200, ()=> {
|
||||
this.moveJewel(x, y);
|
||||
})
|
||||
return;
|
||||
|
|
@ -536,7 +545,7 @@ export class GameScene extends Phaser.Scene {
|
|||
|
||||
|
||||
// After swap completes, re-enable interactivity and reset flag
|
||||
this.time.delayedCall(300, () => { // Adjust delay as needed for animation duration
|
||||
this.time.delayedCall(400, () => { // Adjust delay as needed for animation duration
|
||||
this.jewels.children.iterate((jewel) => {
|
||||
if (jewel) {
|
||||
jewel.setInteractive();
|
||||
|
|
@ -874,7 +883,7 @@ export class GameScene extends Phaser.Scene {
|
|||
});
|
||||
|
||||
// Create new bottom row after moving all jewels up
|
||||
this.time.delayedCall(300, () => {
|
||||
this.time.delayedCall(500, () => {
|
||||
this.isMovingUp = false;
|
||||
this.createBottomRow();
|
||||
this.checkWarning();
|
||||
|
|
@ -1065,6 +1074,11 @@ export class GameScene extends Phaser.Scene {
|
|||
|
||||
levelUp() {
|
||||
this.level ++;
|
||||
if (this.level === 25) {
|
||||
this.gameStatus === false
|
||||
this.gameEnd();
|
||||
return;
|
||||
}
|
||||
const newLevel = LEVEL_CONFIG[this.level];
|
||||
this.numberOfJewels = newLevel.numberOfJewels;
|
||||
this.matchesNeeded = newLevel.matchesNeeded;
|
||||
|
|
@ -1148,7 +1162,6 @@ export class GameScene extends Phaser.Scene {
|
|||
|
||||
// Game over function
|
||||
gameOver() {
|
||||
console.log('Game Over!');
|
||||
this.gameStatus = false;
|
||||
this.sound.play('game-over');
|
||||
this.rowOne = false;
|
||||
|
|
@ -1231,4 +1244,113 @@ export class GameScene extends Phaser.Scene {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Game over function
|
||||
gameEnd() {
|
||||
this.gameStatus = false;
|
||||
this.sound.play('game-over');
|
||||
this.rowOne = false;
|
||||
this.grid.setFillStyle(this.gridColor).setAlpha(0.5);
|
||||
|
||||
// Make all jewels bounce off screen
|
||||
this.jewels.children.iterate((jewel) => {
|
||||
if (jewel) {
|
||||
// Enable physics for the jewel if not already enabled
|
||||
if (!jewel.body) {
|
||||
this.physics.add.existing(jewel);
|
||||
}
|
||||
|
||||
// Remove world bounds collision
|
||||
jewel.body.setCollideWorldBounds(false);
|
||||
|
||||
// Set random velocity for bouncing effect
|
||||
const angle = Phaser.Math.Between(0, 360);
|
||||
const speed = Phaser.Math.Between(100, 300);
|
||||
|
||||
jewel.body.setVelocity(
|
||||
Math.cos(angle) * speed,
|
||||
Math.sin(angle) * speed
|
||||
);
|
||||
|
||||
// Add some rotation for visual effect
|
||||
jewel.body.angularVelocity = Phaser.Math.Between(-200, 200);
|
||||
|
||||
// Get some points!
|
||||
const delay = Phaser.Math.Between(100,6000);
|
||||
this.time.delayedCall(delay, () => {
|
||||
this.score += 100;
|
||||
this.scoreText.setText(`Score: ${this.score}`);
|
||||
this.sound.play('clear');
|
||||
|
||||
this.tweens.add({
|
||||
targets: jewel,
|
||||
scaleX: 0,
|
||||
scaleY: 0,
|
||||
alpha: 0,
|
||||
duration: 200,
|
||||
onComplete: () => {
|
||||
jewel.destroy();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (this.alarm) {
|
||||
this.alarm.stop();
|
||||
}
|
||||
if (this.alarmFlash) {
|
||||
this.alarmFlash.remove();
|
||||
this.alarmFlash = null;
|
||||
}
|
||||
|
||||
// Create the New Level text
|
||||
const gameOverText = this.add.text(1150, 250, `YOU WIN!!!`, {
|
||||
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: gameOverText,
|
||||
scale: { from: 0.5, to: 1.5 },
|
||||
alpha: { from: 0, to: 1 },
|
||||
duration: 1000,
|
||||
ease: 'Back.easeOut',
|
||||
});
|
||||
|
||||
// Fade out and destroy after 2000ms
|
||||
this.time.delayedCall(10200, () => {
|
||||
this.tweens.add({
|
||||
targets: gameOverText,
|
||||
angle: 360,
|
||||
scale: 0,
|
||||
alpha: 0,
|
||||
duration: 500,
|
||||
onComplete: () => {
|
||||
gameOverText.destroy();
|
||||
this.time.delayedCall(3000, () => {
|
||||
// Fade out camera
|
||||
this.tweens.add({
|
||||
targets: this.cameras.main,
|
||||
opacity: 0,
|
||||
duration: 1500,
|
||||
ease: 'Linear',
|
||||
onComplete: () => {
|
||||
this.sound.stopAll();
|
||||
this.scene.start('MenuScene');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
132
src/MenuScene.js
|
|
@ -2,6 +2,49 @@ export class MenuScene extends Phaser.Scene {
|
|||
|
||||
constructor() {
|
||||
super({ key: 'MenuScene' });
|
||||
|
||||
this.allies = {
|
||||
'goblin': {
|
||||
'level': 1,
|
||||
'spriteFrom': 0,
|
||||
'spriteTo': 4
|
||||
},
|
||||
'surfer': {
|
||||
'level': 5,
|
||||
'spriteFrom': 5,
|
||||
'spriteTo': 10
|
||||
},
|
||||
'bear': {
|
||||
'level': 9,
|
||||
'spriteFrom': 11,
|
||||
'spriteTo': 17
|
||||
},
|
||||
'wizard': {
|
||||
'level': 13,
|
||||
'spriteFrom': 18,
|
||||
'spriteTo': 27
|
||||
},
|
||||
'steam': {
|
||||
'level': 17,
|
||||
'spriteFrom': 28,
|
||||
'spriteTo': 39
|
||||
},
|
||||
'shark': {
|
||||
'level': 21,
|
||||
'spriteFrom': 40,
|
||||
'spriteTo': 54
|
||||
},
|
||||
};
|
||||
this.allyNames = [];
|
||||
for (let ally in this.allies) {
|
||||
this.allyNames.push(ally);
|
||||
}
|
||||
}
|
||||
|
||||
init(data) {
|
||||
this.currentAlly = 0;
|
||||
this.currentLevel = 1;
|
||||
this.currentDifficulty = 'Easy';
|
||||
}
|
||||
|
||||
preload() {
|
||||
|
|
@ -13,8 +56,12 @@ export class MenuScene extends Phaser.Scene {
|
|||
this.load.image('menuBackground', 'assets/menuBackground.png');
|
||||
this.load.image('menuLogo', 'assets/menuLogo.png');
|
||||
this.load.image('menuPlate', 'assets/menuPlate.png');
|
||||
this.load.image('menuFrame', 'assets/menuFrame.png');
|
||||
this.load.audio('menuMusic', 'assets/menuMusic.mp3');
|
||||
this.load.font('royalAcid', 'assets/Royalacid.ttf');
|
||||
for (let ally in this.allies) {
|
||||
this.load.image(`${ally}-pic`, `assets/${ally}.png`);
|
||||
}
|
||||
}
|
||||
|
||||
create() {
|
||||
|
|
@ -69,7 +116,9 @@ export class MenuScene extends Phaser.Scene {
|
|||
this.bgMusic.destroy();
|
||||
|
||||
// Start the game scene
|
||||
this.scene.start('GameScene');
|
||||
this.scene.start('GameScene', {
|
||||
level: this.currentLevel
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -89,6 +138,63 @@ export class MenuScene extends Phaser.Scene {
|
|||
}
|
||||
}).setAlpha(0);
|
||||
|
||||
// Setup Ally Selector
|
||||
|
||||
this.allyImage = this.add.image(1350, 550, `${this.allyNames[this.currentAlly]}-pic`).setScale(0.17).setAlpha(0);
|
||||
this.allyMenu = this.add.image(1350, 550, 'menuFrame').setOrigin(0.5).setScale(0);
|
||||
this.allyMenu.preFX.addShadow(-5, -5, .005);
|
||||
|
||||
this.allyMenuBG = this.add.rectangle(1075, 750, 550, 150, 0xf9eec7, .6).setOrigin(0,0).setAlpha(0);
|
||||
|
||||
this.allyMenuText = this.add.text(1100, 775, 'Starting Ally: Level 1', {
|
||||
fontFamily: 'royalAcid, arial',
|
||||
fontSize: '48px',
|
||||
fill: '#40faf6', // Primary color for the text
|
||||
stroke: '#00b43cff', // Secondary color for stroke (creates gradient effect)
|
||||
strokeThickness: 2,
|
||||
shadow: {
|
||||
offsetX: 3,
|
||||
offsetY: 3,
|
||||
color: '#1b426e',
|
||||
blur: 5,
|
||||
fill: true
|
||||
}
|
||||
}).setAlpha(0).setOrigin(0,0);
|
||||
|
||||
this.allyMenuDifficulty = this.add.text(1100, 825, 'Easy', {
|
||||
fontFamily: 'royalAcid, arial',
|
||||
fontSize: '48px',
|
||||
fill: '#40faf6', // Primary color for the text
|
||||
stroke: '#00b43cff', // Secondary color for stroke (creates gradient effect)
|
||||
strokeThickness: 2,
|
||||
shadow: {
|
||||
offsetX: 3,
|
||||
offsetY: 3,
|
||||
color: '#1b426e',
|
||||
blur: 5,
|
||||
fill: true
|
||||
}
|
||||
}).setAlpha(0).setOrigin(0,0);
|
||||
|
||||
this.allyMenu.setInteractive();
|
||||
this.allyMenu.on('pointerdown', () => {
|
||||
this.currentAlly++;
|
||||
if (this.currentAlly > this.allyNames.length-1) {
|
||||
this.currentAlly = 0;
|
||||
}
|
||||
this.currentLevel = this.allies[this.allyNames[this.currentAlly]].level;
|
||||
if (this.currentLevel < 9) {
|
||||
this.currentDifficulty = 'Easy';
|
||||
} else if (this.currentLevel < 17) {
|
||||
this.currentDifficulty = 'Medium';
|
||||
} else if (this.currentLevel < 25) {
|
||||
this.currentDifficulty = 'Hard';
|
||||
}
|
||||
this.allyImage.setTexture(`${this.allyNames[this.currentAlly]}-pic`);
|
||||
this.allyMenuText.setText('Starting Ally: Level ' + this.currentLevel);
|
||||
this.allyMenuDifficulty.setText(`${this.currentDifficulty}`);
|
||||
});
|
||||
|
||||
// Create and animate menu logo
|
||||
this.menuLogo = this.add.image(-300, -300, 'menuLogo');
|
||||
this.menuLogo.setOrigin(0.5, 0.5);
|
||||
|
|
@ -101,7 +207,7 @@ export class MenuScene extends Phaser.Scene {
|
|||
scale: .9,
|
||||
duration: 4000,
|
||||
ease: 'Back.out',
|
||||
delay: 500,
|
||||
delay: 1000,
|
||||
onComplete: () => {
|
||||
// Pulse Menu
|
||||
this.tweens.add({
|
||||
|
|
@ -121,12 +227,27 @@ export class MenuScene extends Phaser.Scene {
|
|||
ease: 'Quart.out',
|
||||
onComplete: () => {
|
||||
this.tweens.add({
|
||||
targets: this.startMenuText,
|
||||
targets: [
|
||||
this.startMenuText,
|
||||
this.allyMenuText,
|
||||
this.allyMenuDifficulty,
|
||||
this.allyImage,
|
||||
this.allyMenuBG
|
||||
],
|
||||
duration: 1000,
|
||||
alpha: 1
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Start Button
|
||||
this.tweens.add({
|
||||
targets: this.allyMenu,
|
||||
angle: -1080,
|
||||
duration: 1000,
|
||||
scale: 0.7,
|
||||
ease: 'Quart.out'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -156,7 +277,10 @@ export class MenuScene extends Phaser.Scene {
|
|||
spawnJewel() {
|
||||
// Create a new jewel at random position at bottom of screen
|
||||
const x = Phaser.Math.Between(50, this.game.config.width - 50);
|
||||
const frame = Phaser.Math.Between(0, 4);
|
||||
const frame = Phaser.Math.Between(
|
||||
this.allies[this.allyNames[this.currentAlly]].spriteFrom,
|
||||
this.allies[this.allyNames[this.currentAlly]].spriteTo
|
||||
);
|
||||
|
||||
// Create jewel sprite
|
||||
const jewel = this.add.sprite(x, this.game.config.height + 50, 'jewels', frame);
|
||||
|
|
|
|||
|
|
@ -97,19 +97,19 @@ export const LEVEL_CONFIG = {
|
|||
},
|
||||
13: {
|
||||
numberOfJewels: 7,
|
||||
matchesNeeded: 8,
|
||||
matchesNeeded: 6,
|
||||
moveInterval: 8000,
|
||||
ally: 'wizard',
|
||||
spritePlus: 18,
|
||||
gridColor: 0xFFFFFF
|
||||
gridColor: 0xffef6a
|
||||
},
|
||||
14: {
|
||||
numberOfJewels: 8,
|
||||
matchesNeeded: 8,
|
||||
matchesNeeded: 7,
|
||||
moveInterval: 9000,
|
||||
ally: 'wizard',
|
||||
spritePlus: 18,
|
||||
gridColor: 0xFFFFFF
|
||||
gridColor: 0xffc000
|
||||
},
|
||||
15: {
|
||||
numberOfJewels: 9,
|
||||
|
|
@ -117,7 +117,7 @@ export const LEVEL_CONFIG = {
|
|||
moveInterval: 10000,
|
||||
ally: 'wizard',
|
||||
spritePlus: 18,
|
||||
gridColor: 0xFFFFFF
|
||||
gridColor: 0xff9000
|
||||
},
|
||||
16: {
|
||||
numberOfJewels: 10,
|
||||
|
|
@ -125,6 +125,70 @@ export const LEVEL_CONFIG = {
|
|||
moveInterval: 11000,
|
||||
ally: 'wizard',
|
||||
spritePlus: 18,
|
||||
gridColor: 0xFFFFFF
|
||||
gridColor: 0x583200
|
||||
},
|
||||
17: {
|
||||
numberOfJewels: 10,
|
||||
matchesNeeded: 8,
|
||||
moveInterval: 11000,
|
||||
ally: 'steam',
|
||||
spritePlus: 28,
|
||||
gridColor: 0x8c4c00
|
||||
},
|
||||
18: {
|
||||
numberOfJewels: 11,
|
||||
matchesNeeded: 8,
|
||||
moveInterval: 11000,
|
||||
ally: 'steam',
|
||||
spritePlus: 28,
|
||||
gridColor: 0xffb24e
|
||||
},
|
||||
19: {
|
||||
numberOfJewels: 12,
|
||||
matchesNeeded: 8,
|
||||
moveInterval: 11500,
|
||||
ally: 'steam',
|
||||
spritePlus: 28,
|
||||
gridColor: 0x4ef9ff
|
||||
},
|
||||
20: {
|
||||
numberOfJewels: 12,
|
||||
matchesNeeded: 8,
|
||||
moveInterval: 11000,
|
||||
ally: 'steam',
|
||||
spritePlus: 28,
|
||||
gridColor: 0x00999f
|
||||
},
|
||||
21: {
|
||||
numberOfJewels: 12,
|
||||
matchesNeeded: 8,
|
||||
moveInterval: 11000,
|
||||
ally: 'shark',
|
||||
spritePlus: 40,
|
||||
gridColor: 0x83ffbd
|
||||
},
|
||||
22: {
|
||||
numberOfJewels: 13,
|
||||
matchesNeeded: 8,
|
||||
moveInterval: 11500,
|
||||
ally: 'shark',
|
||||
spritePlus: 40,
|
||||
gridColor: 0x83fff8
|
||||
},
|
||||
23: {
|
||||
numberOfJewels: 14,
|
||||
matchesNeeded: 8,
|
||||
moveInterval: 12000,
|
||||
ally: 'shark',
|
||||
spritePlus: 40,
|
||||
gridColor: 0x00ffba
|
||||
},
|
||||
24: {
|
||||
numberOfJewels: 15,
|
||||
matchesNeeded: 8,
|
||||
moveInterval: 11500,
|
||||
ally: 'shark',
|
||||
spritePlus: 40,
|
||||
gridColor: 0x00fff0
|
||||
}
|
||||
};
|
||||
|
|
|
|||