200 lines
5.7 KiB
JavaScript
200 lines
5.7 KiB
JavaScript
class ParallaxSystem {
|
|
constructor(scene) {
|
|
this.scene = scene;
|
|
this.layers = [];
|
|
|
|
// Layer depths (Phaser depth sorting)
|
|
this.DEPTH = {
|
|
SKY: -1000,
|
|
DISTANT_HILLS: -500,
|
|
FAR_TREES: -100,
|
|
TERRAIN: 0,
|
|
GAME_OBJECTS: 1000,
|
|
FOREGROUND_GRASS: 5000,
|
|
FOREGROUND_LEAVES: 5500
|
|
};
|
|
|
|
this.init();
|
|
}
|
|
|
|
init() {
|
|
console.log('🌄 ParallaxSystem: Initialized');
|
|
|
|
// Layer 1: Sky/Hills (Distant background)
|
|
// Layer 1: Sky/Hills (Disabled by request)
|
|
// this.createSkyLayer();
|
|
// this.createDistantHills();
|
|
|
|
// Layer 4: Foreground overlay (High grass patches)
|
|
this.createForegroundGrass();
|
|
}
|
|
|
|
createSkyLayer() {
|
|
// Gradient sky rectangle
|
|
const width = 3000;
|
|
const height = 2000;
|
|
|
|
const skyBg = this.scene.add.rectangle(0, 0, width, height, 0x87CEEB); // Sky blue
|
|
skyBg.setOrigin(0, 0);
|
|
skyBg.setScrollFactor(0); // Fixed (no parallax)
|
|
skyBg.setDepth(this.DEPTH.SKY);
|
|
|
|
this.layers.push({
|
|
name: 'sky',
|
|
objects: [skyBg],
|
|
scrollFactor: 0
|
|
});
|
|
}
|
|
|
|
createDistantHills() {
|
|
// Create simple hill silhouettes in background
|
|
const hillCount = 5;
|
|
const hills = [];
|
|
|
|
for (let i = 0; i < hillCount; i++) {
|
|
const x = i * 800 - 1000;
|
|
const y = 600;
|
|
const width = Phaser.Math.Between(400, 800);
|
|
const height = Phaser.Math.Between(150, 300);
|
|
|
|
// Create hill as ellipse
|
|
const hill = this.scene.add.ellipse(x, y, width, height, 0x4a5f3a); // Dark green
|
|
hill.setAlpha(0.4);
|
|
hill.setDepth(this.DEPTH.DISTANT_HILLS);
|
|
hill.setScrollFactor(0.2, 0.2); // Slow parallax
|
|
|
|
hills.push(hill);
|
|
}
|
|
|
|
this.layers.push({
|
|
name: 'distant_hills',
|
|
objects: hills,
|
|
scrollFactor: 0.2
|
|
});
|
|
}
|
|
|
|
createForegroundGrass() {
|
|
// Create tall grass patches that appear in front of player
|
|
const grassPatches = [];
|
|
const patchCount = 30;
|
|
|
|
for (let i = 0; i < patchCount; i++) {
|
|
const x = Phaser.Math.Between(-500, 2500);
|
|
const y = Phaser.Math.Between(-500, 2500);
|
|
|
|
const grass = this.createGrassPatch(x, y);
|
|
grass.setDepth(this.DEPTH.FOREGROUND_GRASS);
|
|
grass.setScrollFactor(1.05, 1.05); // Slight forward parallax
|
|
grass.setAlpha(0.6);
|
|
|
|
grassPatches.push(grass);
|
|
}
|
|
|
|
this.layers.push({
|
|
name: 'foreground_grass',
|
|
objects: grassPatches,
|
|
scrollFactor: 1.05
|
|
});
|
|
}
|
|
|
|
createGrassPatch(x, y) {
|
|
// Create procedural grass patch
|
|
const graphics = this.scene.add.graphics();
|
|
|
|
// Draw several grass blades
|
|
for (let i = 0; i < 6; i++) {
|
|
const offsetX = Phaser.Math.Between(-10, 10);
|
|
const offsetY = Phaser.Math.Between(-5, 5);
|
|
const height = Phaser.Math.Between(20, 40);
|
|
|
|
graphics.fillStyle(0x3a5f2a, 0.8); // Dark grass green
|
|
|
|
// Draw grass blade (thin triangle)
|
|
graphics.beginPath();
|
|
graphics.moveTo(x + offsetX, y + offsetY);
|
|
graphics.lineTo(x + offsetX - 2, y + offsetY + height);
|
|
graphics.lineTo(x + offsetX + 2, y + offsetY + height);
|
|
graphics.closePath();
|
|
graphics.fillPath();
|
|
}
|
|
|
|
return graphics;
|
|
}
|
|
|
|
update(playerX, playerY) {
|
|
// Update foreground grass visibility based on player position
|
|
// Hide/show grass patches that are too close to player for better gameplay
|
|
|
|
const foregroundLayer = this.layers.find(l => l.name === 'foreground_grass');
|
|
if (!foregroundLayer) return;
|
|
|
|
for (const grass of foregroundLayer.objects) {
|
|
const distance = Phaser.Math.Distance.Between(
|
|
grass.x, grass.y,
|
|
playerX, playerY
|
|
);
|
|
|
|
// Fade out grass when player is very close
|
|
if (distance < 50) {
|
|
grass.setAlpha(0.2);
|
|
} else if (distance < 100) {
|
|
grass.setAlpha(0.4);
|
|
} else {
|
|
grass.setAlpha(0.6);
|
|
}
|
|
}
|
|
}
|
|
|
|
addFarTree(x, y) {
|
|
// Add a background tree (Layer 2)
|
|
if (!this.scene.textures.exists('tree')) return;
|
|
|
|
const tree = this.scene.add.sprite(x, y, 'tree');
|
|
tree.setDepth(this.DEPTH.FAR_TREES);
|
|
tree.setScrollFactor(0.7, 0.7); // Medium parallax
|
|
tree.setAlpha(0.7);
|
|
tree.setScale(1.5);
|
|
|
|
return tree;
|
|
}
|
|
|
|
addForegroundLeaves(x, y) {
|
|
// Add falling leaves or branch overlay (Layer 4)
|
|
const graphics = this.scene.add.graphics();
|
|
|
|
// Draw some leaves
|
|
for (let i = 0; i < 3; i++) {
|
|
const leafX = x + Phaser.Math.Between(-20, 20);
|
|
const leafY = y + Phaser.Math.Between(-10, 10);
|
|
|
|
graphics.fillStyle(0x2d4a1f, 0.5); // Dark green leaf
|
|
graphics.fillEllipse(leafX, leafY, 8, 12);
|
|
}
|
|
|
|
graphics.setDepth(this.DEPTH.FOREGROUND_LEAVES);
|
|
graphics.setScrollFactor(1.1, 1.1); // Fastest parallax (closest)
|
|
|
|
return graphics;
|
|
}
|
|
|
|
clearLayer(layerName) {
|
|
const layer = this.layers.find(l => l.name === layerName);
|
|
if (!layer) return;
|
|
|
|
for (const obj of layer.objects) {
|
|
obj.destroy();
|
|
}
|
|
|
|
layer.objects = [];
|
|
}
|
|
|
|
destroy() {
|
|
for (const layer of this.layers) {
|
|
for (const obj of layer.objects) {
|
|
obj.destroy();
|
|
}
|
|
}
|
|
this.layers = [];
|
|
}
|
|
}
|