feat: Implement multi-layer parallax backgrounds, font loading, and improved game flow
- Added multiple background layers (bg-layer2, bg-layer3) with parallax scrolling effect - Implemented proper background positioning and continuous scrolling logic - Integrated custom 'Space' font for UI elements and game over text - Updated menu scene integration and game flow with fade-out transition to menu - Enhanced visual assets including logo display and improved background layer management
|
After Width: | Height: | Size: 242 KiB |
|
After Width: | Height: | Size: 244 KiB |
|
After Width: | Height: | Size: 288 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
Before Width: | Height: | Size: 2.4 MiB After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 2.4 MiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 679 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 4.4 KiB |
|
|
@ -30,12 +30,6 @@
|
||||||
<script src="phaser.min.js"></script>
|
<script src="phaser.min.js"></script>
|
||||||
|
|
||||||
<!-- Import game modules using ES6 modules -->
|
<!-- Import game modules using ES6 modules -->
|
||||||
<script type="module">
|
<script type="module" src="./src/config.js"></script>
|
||||||
import { config } from './src/config.js';
|
|
||||||
import { GameScene } from './src/scenes/GameScene.js';
|
|
||||||
|
|
||||||
const game = new Phaser.Game(config);
|
|
||||||
game.scene.add('GameScene', GameScene, true);
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
import { MenuScene } from './scenes/MenuScene.js';
|
||||||
|
import { GameScene } from './scenes/GameScene.js';
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
type: Phaser.AUTO,
|
type: Phaser.AUTO,
|
||||||
width: 600,
|
width: 600,
|
||||||
|
|
@ -10,13 +13,14 @@ export const config = {
|
||||||
debug: false
|
debug: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
scene: {
|
scene: [
|
||||||
preload: function() {},
|
MenuScene,
|
||||||
create: function() {},
|
GameScene,
|
||||||
update: function() {}
|
],
|
||||||
},
|
|
||||||
scale: {
|
scale: {
|
||||||
mode: Phaser.Scale.FIT,
|
mode: Phaser.Scale.FIT,
|
||||||
autoCenter: Phaser.Scale.CENTER_BOTH
|
autoCenter: Phaser.Scale.CENTER_BOTH
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const game = new Phaser.Game(config);
|
||||||
|
|
@ -33,8 +33,9 @@ export class GameScene extends Phaser.Scene {
|
||||||
|
|
||||||
// Load background images
|
// Load background images
|
||||||
this.load.image('bg-layer1', 'assets/neon-city-bg.png');
|
this.load.image('bg-layer1', 'assets/neon-city-bg.png');
|
||||||
//this.load.image('bg-layer2', 'assets/bg-layer2.png');
|
this.load.image('bg-layer2', 'assets/neon-city-dark-clouds2.png');
|
||||||
//this.load.image('bg-layer3', 'assets/bg-layer3.png');
|
this.load.image('bg-layer3', 'assets/neon-city-dark-clouds.png');
|
||||||
|
this.load.image('logo', 'assets/logo.png');
|
||||||
|
|
||||||
// Load Sprites
|
// Load Sprites
|
||||||
this.load.spritesheet('player-sprite', 'assets/player-sprite.png', {
|
this.load.spritesheet('player-sprite', 'assets/player-sprite.png', {
|
||||||
|
|
@ -55,6 +56,9 @@ export class GameScene extends Phaser.Scene {
|
||||||
this.load.audio('enemy-shoot', 'assets/sounds/enemy-shoot.mp3');
|
this.load.audio('enemy-shoot', 'assets/sounds/enemy-shoot.mp3');
|
||||||
this.load.audio('next-wave', 'assets/sounds/next-wave.mp3');
|
this.load.audio('next-wave', 'assets/sounds/next-wave.mp3');
|
||||||
|
|
||||||
|
// Load Fonts
|
||||||
|
this.load.font('Space', 'assets/space-age.otf');
|
||||||
|
|
||||||
// Create simple placeholder graphics for now
|
// Create simple placeholder graphics for now
|
||||||
this.createPlaceholderGraphics();
|
this.createPlaceholderGraphics();
|
||||||
}
|
}
|
||||||
|
|
@ -102,13 +106,13 @@ export class GameScene extends Phaser.Scene {
|
||||||
createBackgrounds() {
|
createBackgrounds() {
|
||||||
// Create multiple background layers with different speeds
|
// Create multiple background layers with different speeds
|
||||||
this.bgLayer1 = this.add.image(280, 30, 'bg-layer1').setOrigin(0.5);
|
this.bgLayer1 = this.add.image(280, 30, 'bg-layer1').setOrigin(0.5);
|
||||||
//this.bgLayer2 = this.add.image(400, 300, 'bg-layer2').setOrigin(0.5);
|
this.bgLayer2 = this.add.image(280, 30, 'bg-layer2').setOrigin(0.5);
|
||||||
//this.bgLayer3 = this.add.image(400, 300, 'bg-layer3').setOrigin(0.5);
|
this.bgLayer3 = this.add.image(280, 30, 'bg-layer3').setOrigin(0.5);
|
||||||
|
|
||||||
// Set different speeds for parallax effect (smaller = slower)
|
// Set different speeds for parallax effect (smaller = slower)
|
||||||
this.bgSpeed1 = 0.2;
|
this.bgSpeed1 = 0.2;
|
||||||
//this.bgSpeed2 = 0.5;
|
this.bgSpeed2 = 0.5;
|
||||||
//this.bgSpeed3 = 0.8;
|
this.bgSpeed3 = 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
update(time, delta) {
|
update(time, delta) {
|
||||||
|
|
@ -141,19 +145,19 @@ export class GameScene extends Phaser.Scene {
|
||||||
updateBackgrounds() {
|
updateBackgrounds() {
|
||||||
// Move background layers at different speeds
|
// Move background layers at different speeds
|
||||||
this.bgLayer1.y += this.bgSpeed1;
|
this.bgLayer1.y += this.bgSpeed1;
|
||||||
//this.bgLayer2.x -= this.bgSpeed2;
|
this.bgLayer2.y += this.bgSpeed2;
|
||||||
//this.bgLayer3.x -= this.bgSpeed3;
|
this.bgLayer3.y += this.bgSpeed3;
|
||||||
|
|
||||||
// Reset positions to create continuous scrolling effect
|
// Reset positions to create continuous scrolling effect
|
||||||
if (this.bgLayer1.y > 736) {
|
if (this.bgLayer1.y > 736) {
|
||||||
this.bgLayer1.y = 30; // Width of game + layer width
|
this.bgLayer1.y = 0;
|
||||||
|
}
|
||||||
|
if (this.bgLayer2.y > 1536) {
|
||||||
|
this.bgLayer2.y = 0;
|
||||||
|
}
|
||||||
|
if (this.bgLayer3.y > 1536) {
|
||||||
|
this.bgLayer3.y = 0;
|
||||||
}
|
}
|
||||||
// if (this.bgLayer2.x < -400) {
|
|
||||||
// this.bgLayer2.x = 1200;
|
|
||||||
// }
|
|
||||||
// if (this.bgLayer3.x < -400) {
|
|
||||||
// this.bgLayer3.x = 1200;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setupMouseInput() {
|
setupMouseInput() {
|
||||||
|
|
@ -229,17 +233,18 @@ export class GameScene extends Phaser.Scene {
|
||||||
this.scoreText = this.add.text(16, 16, 'Score: 0', {
|
this.scoreText = this.add.text(16, 16, 'Score: 0', {
|
||||||
fontSize: '28px',
|
fontSize: '28px',
|
||||||
fill: '#ffffff',
|
fill: '#ffffff',
|
||||||
fontFamily: 'Arial'
|
fontFamily: 'Space, Arial'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create game title
|
// Create game title
|
||||||
this.titleText = this.add.text(300, 50, 'Zenith Vector', {
|
// this.titleText = this.add.text(300, 50, 'Zenith Vector', {
|
||||||
fontSize: '40px',
|
// fontSize: '40px',
|
||||||
fill: '#00ffcc',
|
// fill: '#00ffcc',
|
||||||
fontFamily: 'Arial',
|
// fontFamily: 'Arial',
|
||||||
align: 'center'
|
// align: 'center'
|
||||||
});
|
// });
|
||||||
this.titleText.setOrigin(0.5);
|
// this.titleText.setOrigin(0.5);
|
||||||
|
this.titleText = this.add.image(300, 50, 'logo').setScale(.1).setOrigin(0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
shoot(pointer) {
|
shoot(pointer) {
|
||||||
|
|
@ -365,14 +370,24 @@ export class GameScene extends Phaser.Scene {
|
||||||
const gameOverText = this.add.text(300, 400, 'GAME OVER', {
|
const gameOverText = this.add.text(300, 400, 'GAME OVER', {
|
||||||
fontSize: '54px',
|
fontSize: '54px',
|
||||||
fill: '#ff3366',
|
fill: '#ff3366',
|
||||||
fontFamily: 'Arial'
|
fontFamily: 'Space, Arial'
|
||||||
});
|
});
|
||||||
gameOverText.setOrigin(0.5);
|
gameOverText.setOrigin(0.5);
|
||||||
|
|
||||||
// Restart game after delay
|
// Return to menu after delay
|
||||||
// this.time.delayedCall(2000, () => {
|
this.time.delayedCall(5000, () => {
|
||||||
// this.scene.restart();
|
// Fade camera out before returning to menu
|
||||||
// });
|
this.tweens.add({
|
||||||
|
targets: this.cameras.main,
|
||||||
|
alpha: 0, // Fade to transparent
|
||||||
|
duration: 1000, // 1 second fade
|
||||||
|
ease: 'Linear',
|
||||||
|
onComplete: () => {
|
||||||
|
this.bgMusic.stop();
|
||||||
|
this.scene.start('MenuScene');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
startWave(waveNumber) {
|
startWave(waveNumber) {
|
||||||
|
|
@ -383,7 +398,7 @@ export class GameScene extends Phaser.Scene {
|
||||||
const waveText = this.add.text(300, 150, `WAVE ${waveNumber + 1}`, {
|
const waveText = this.add.text(300, 150, `WAVE ${waveNumber + 1}`, {
|
||||||
fontSize: '48px',
|
fontSize: '48px',
|
||||||
fill: '#ffff00',
|
fill: '#ffff00',
|
||||||
fontFamily: 'Arial'
|
fontFamily: 'Space, Arial'
|
||||||
});
|
});
|
||||||
waveText.setOrigin(0.5);
|
waveText.setOrigin(0.5);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,299 @@
|
||||||
|
export class MenuScene extends Phaser.Scene {
|
||||||
|
constructor() {
|
||||||
|
super('MenuScene');
|
||||||
|
}
|
||||||
|
|
||||||
|
preload() {
|
||||||
|
this.load.image('menu-logo','assets/logo.png');
|
||||||
|
this.load.image('menu-ship','assets/menu-ship.png');
|
||||||
|
this.load.image('menu-hunter','assets/menu-hunter.png');
|
||||||
|
this.load.image('menu-alien','assets/menu-alien.png');
|
||||||
|
this.load.image('reticle', 'assets/reticle.png');
|
||||||
|
this.load.audio('menu-bgMusic', 'assets/music/NeonVelocity.mp3');
|
||||||
|
|
||||||
|
// Load custom font
|
||||||
|
this.load.font('Space', 'assets/space-age.otf');
|
||||||
|
this.load.font('coder', 'assets/ClassCoder.ttf');
|
||||||
|
}
|
||||||
|
|
||||||
|
create() {
|
||||||
|
// Create menu background and title
|
||||||
|
this.add.rectangle(300, 400, 600, 800, 0x111111);
|
||||||
|
|
||||||
|
// Create starfield effect
|
||||||
|
this.createStarfield();
|
||||||
|
|
||||||
|
const logo = this.add.image(300, 250, 'menu-logo').setOrigin(0.5).setScale(0.5).setAlpha(0.7);
|
||||||
|
const menuHunter = this.add.image(450, 700, 'menu-hunter').setScale(0.6).setOrigin(0.5).setAlpha(0);
|
||||||
|
const menuShip = this.add.image(900, -300, 'menu-ship').setOrigin(0.5).setScale(.6);
|
||||||
|
const menuAlien = this.add.image(150, 700, 'menu-alien').setScale(0.6).setOrigin(0.5).setAlpha(0);
|
||||||
|
|
||||||
|
this.tweens.add({
|
||||||
|
targets: menuShip,
|
||||||
|
x: 500,
|
||||||
|
y: 100,
|
||||||
|
duration: 2000,
|
||||||
|
ease: 'Cubic',
|
||||||
|
delay: 3000
|
||||||
|
});
|
||||||
|
|
||||||
|
this.tweens.add({
|
||||||
|
targets: logo,
|
||||||
|
alpha: 1,
|
||||||
|
scale: 1,
|
||||||
|
duration: 5000,
|
||||||
|
ease: 'Bounce',
|
||||||
|
});
|
||||||
|
|
||||||
|
this.tweens.add({
|
||||||
|
targets: [menuHunter, menuAlien],
|
||||||
|
alpha: 1,
|
||||||
|
duration: 3000,
|
||||||
|
delay: 4000,
|
||||||
|
ease: 'Bounce'
|
||||||
|
})
|
||||||
|
|
||||||
|
// Controls display with typing animation
|
||||||
|
const controlsText = 'Controls: A and D to go Left and Right. Mouse to Aim and Fire';
|
||||||
|
this.controlsText = this.add.text(300, 500, '', {
|
||||||
|
fontFamily: 'Coder, Arial',
|
||||||
|
fontSize: '16px',
|
||||||
|
fill: '#00ff00'
|
||||||
|
}).setOrigin(0.5);
|
||||||
|
|
||||||
|
// Typing animation
|
||||||
|
this.time.delayedCall(1000, () => {
|
||||||
|
let i = 0;
|
||||||
|
const typingTimer = this.time.addEvent({
|
||||||
|
delay: 50, // Characters per second
|
||||||
|
callback: () => {
|
||||||
|
if (i < controlsText.length) {
|
||||||
|
this.controlsText.text += controlsText.charAt(i);
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
typingTimer.remove();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
callbackScope: this,
|
||||||
|
loop: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Menu button
|
||||||
|
this.startButton = this.add.text(300, 550, ' START GAME ', {
|
||||||
|
fontFamily: 'Space, Arial',
|
||||||
|
fontSize: '48px',
|
||||||
|
fill: '#fff'
|
||||||
|
}).setOrigin(0.5);
|
||||||
|
|
||||||
|
// Add color cycling effect for synthwave colors
|
||||||
|
const synthwaveColors = ['#ffffff', '#ff00ff', '#00ffff', '#ffff00', '#ff00cc'];
|
||||||
|
let colorIndex = 0;
|
||||||
|
|
||||||
|
this.time.addEvent({
|
||||||
|
delay: 1500,
|
||||||
|
callback: () => {
|
||||||
|
colorIndex = (colorIndex + 1) % synthwaveColors.length;
|
||||||
|
this.startButton.setFill(synthwaveColors[colorIndex]);
|
||||||
|
},
|
||||||
|
loop: true
|
||||||
|
});
|
||||||
|
|
||||||
|
this.tweens.add({
|
||||||
|
targets: this.startButton,
|
||||||
|
scale: 1.2,
|
||||||
|
duration: 1500,
|
||||||
|
repeat: -1,
|
||||||
|
ease: 'Sine',
|
||||||
|
yoyo: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.startButton.setInteractive();
|
||||||
|
this.startButton.on('pointerdown', () => {
|
||||||
|
// Start the actual game scene
|
||||||
|
this.bgMusic.stop();
|
||||||
|
this.scene.start('GameScene');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Play background music
|
||||||
|
this.bgMusic = this.sound.add('menu-bgMusic', { loop: true });
|
||||||
|
this.bgMusic.play();
|
||||||
|
|
||||||
|
// Setup mouse input for shooting and reticle
|
||||||
|
this.setupMouseInput();
|
||||||
|
|
||||||
|
// Add scanline effect (narrow and moving)
|
||||||
|
this.scanlines = this.add.graphics({ x: 0, y: 0 });
|
||||||
|
this.scanlines.fillStyle(0x00ff00, 0.15); // Green scanlines with moderate opacity
|
||||||
|
// Create narrow horizontal lines that move vertically
|
||||||
|
for (let i = 0; i < 20; i++) {
|
||||||
|
const y = (i * 40) % 800;
|
||||||
|
this.scanlines.fillRect(0, y, 600, 2); // Narrow lines (2px height)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add VHS artifacts
|
||||||
|
this.vhsArtifacts = this.add.graphics({ x: 0, y: 0 });
|
||||||
|
this.vhsArtifacts.fillStyle(0xff00ff, 0.1); // Magenta artifacts
|
||||||
|
this.vhsArtifacts.fillRect(0, 0, 600, 800);
|
||||||
|
|
||||||
|
// Add VHS artifacts 2
|
||||||
|
this.vhsArtifacts2 = this.add.graphics({ x: 0, y: 0 });
|
||||||
|
this.vhsArtifacts2.fillStyle(0xff00ff, 0.1); // Magenta artifacts
|
||||||
|
this.vhsArtifacts2.fillRect(0, 0, 600, 800);
|
||||||
|
|
||||||
|
this.tweens.add({
|
||||||
|
targets: this.vhsArtifacts2,
|
||||||
|
alpha: 0.1,
|
||||||
|
duration: 10000,
|
||||||
|
yoyo: true,
|
||||||
|
repeat: -1
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start artifact effects
|
||||||
|
this.artifactTimer = this.time.addEvent({
|
||||||
|
delay: 200,
|
||||||
|
callback: this.updateVHSArtifacts,
|
||||||
|
callbackScope: this,
|
||||||
|
loop: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createStarfield() {
|
||||||
|
// Create a graphics object for the starfield
|
||||||
|
this.starfield = this.add.graphics({ x: 0, y: 0 });
|
||||||
|
|
||||||
|
// Star configuration
|
||||||
|
this.stars = [];
|
||||||
|
const starCount = 200;
|
||||||
|
|
||||||
|
// Initialize stars with random positions and z-depths
|
||||||
|
for (let i = 0; i < starCount; i++) {
|
||||||
|
const star = {
|
||||||
|
x: Math.random() * 600,
|
||||||
|
y: Math.random() * 800,
|
||||||
|
z: Math.random() * 10 + 1, // Depth from 1 to 11
|
||||||
|
size: Math.random() * 2 + 1,
|
||||||
|
speed: Math.random() * 0.5 + 0.2 // Significantly reduced speed
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set color based on depth (closer stars are brighter)
|
||||||
|
const brightness = Math.max(0.5, 1 - star.z / 15); // Closer stars brighter
|
||||||
|
const grayValue = Math.floor(150 + brightness * 105);
|
||||||
|
star.color = (grayValue << 16) | (grayValue << 8) | grayValue;
|
||||||
|
|
||||||
|
this.stars.push(star);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change direction timer - increased to make it more subtle
|
||||||
|
this.directionChangeTimer = this.time.addEvent({
|
||||||
|
delay: 5000, // Increase delay to 5 seconds
|
||||||
|
callback: this.changeStarDirection,
|
||||||
|
callbackScope: this,
|
||||||
|
loop: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
// Update star positions
|
||||||
|
if (this.starfield && this.stars) {
|
||||||
|
this.starfield.clear();
|
||||||
|
|
||||||
|
for (let i = 0; i < this.stars.length; i++) {
|
||||||
|
const star = this.stars[i];
|
||||||
|
|
||||||
|
// Move stars toward camera (decrease z) - greatly reduced speed
|
||||||
|
star.z -= star.speed * 0.02;
|
||||||
|
|
||||||
|
// Reset stars that move too close to camera
|
||||||
|
if (star.z <= 0) {
|
||||||
|
star.z = Math.random() * 10 + 1; // Reset with new depth
|
||||||
|
star.x = Math.random() * 600; // Random x position
|
||||||
|
star.y = Math.random() * 800; // Random y position
|
||||||
|
|
||||||
|
// Recalculate color based on new depth
|
||||||
|
const brightness = Math.max(0.5, 1 - star.z / 15);
|
||||||
|
const grayValue = Math.floor(150 + brightness * 105);
|
||||||
|
star.color = (grayValue << 16) | (grayValue << 8) | grayValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply perspective projection to create parallax effect
|
||||||
|
const scale = 20 / (star.z + 20); // Scale based on depth
|
||||||
|
const screenX = star.x * scale;
|
||||||
|
const screenY = star.y * scale;
|
||||||
|
|
||||||
|
// Draw the star with its color and scaled size
|
||||||
|
this.starfield.fillStyle(star.color);
|
||||||
|
this.starfield.fillCircle(screenX, screenY, star.size * scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update scanline position
|
||||||
|
if (this.scanlines) {
|
||||||
|
this.scanlines.y = (this.scanlines.y + 0.5) % 800;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateVHSArtifacts() {
|
||||||
|
// Randomly update VHS artifacts
|
||||||
|
if (this.vhsArtifacts && Math.random() > 0.7) {
|
||||||
|
// Clear previous artifacts but keep some for flickering effect
|
||||||
|
this.vhsArtifacts.clear();
|
||||||
|
|
||||||
|
// Add random color shifts and distortions
|
||||||
|
for (let i = 0; i < 5; i++) {
|
||||||
|
const x = Math.random() * 600;
|
||||||
|
const y = Math.random() * 800;
|
||||||
|
const width = Math.random() * 10 + 1;
|
||||||
|
const height = Math.random() * 20 + 5;
|
||||||
|
|
||||||
|
// Random color (neon colors for synthwave)
|
||||||
|
const colors = [0xff00ff, 0x00ffff, 0xffff00];
|
||||||
|
const color = Phaser.Display.Color.GetColor32(
|
||||||
|
...colors[Math.floor(Math.random() * colors.length)].toString(16).split('').map(c => parseInt(c, 16) * 17)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Use higher opacity for flickering effect (instead of very low opacity)
|
||||||
|
this.vhsArtifacts.fillStyle(color, Math.random() * 0.3 + 0.1); // Increased from 0.05 to 0.3-0.1 range
|
||||||
|
this.vhsArtifacts.fillRect(x, y, width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changeStarDirection() {
|
||||||
|
// Change direction of all stars (they'll move toward camera)
|
||||||
|
for (let i = 0; i < this.stars.length; i++) {
|
||||||
|
const star = this.stars[i];
|
||||||
|
|
||||||
|
// Randomly adjust speed and depth - much slower changes
|
||||||
|
star.speed = Math.random() * 1 + 0.5; // Reduced speed range
|
||||||
|
star.z += (Math.random() * 0.5 - 0.25); // Very subtle z position change
|
||||||
|
|
||||||
|
// Keep stars within reasonable bounds
|
||||||
|
if (star.z < 0.5) {
|
||||||
|
star.z = 0.5;
|
||||||
|
} else if (star.z > 15) {
|
||||||
|
star.z = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recalculate color based on new depth and speed
|
||||||
|
const brightness = Math.max(0.5, 1 - star.z / 15);
|
||||||
|
const grayValue = Math.floor(150 + brightness * 105);
|
||||||
|
star.color = (grayValue << 16) | (grayValue << 8) | grayValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setupMouseInput() {
|
||||||
|
// Create mouse reticle as sprite (replacing the circle)
|
||||||
|
this.reticle = this.add.sprite(0, 0, 'reticle');
|
||||||
|
this.reticle.setOrigin(0.5);
|
||||||
|
this.reticle.preFX.addGlow(0x00ffcc, .7);
|
||||||
|
|
||||||
|
// Update reticle position with mouse
|
||||||
|
this.input.on('pointermove', (pointer) => {
|
||||||
|
if (this.gameOver) return;
|
||||||
|
|
||||||
|
this.reticle.x = pointer.x;
|
||||||
|
this.reticle.y = pointer.y;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||