FAZA 17: 2.5D Minecraft-Style Terrain + Y-Layer Stacking + Custom Sprites
COMPLETED FEATURES: Custom Sprite Integration: - Player, Zombie, Merchant sprites (0.2 scale) - 11 custom sprites + 5 asset packs loaded - Auto-transparency processing (white/brown removal) - Gravestone system with atlas extraction 2.5D Minecraft-Style Terrain: - Volumetric blocks with 25px thickness - Strong left/right side shading (30%/50% darker) - Minecraft-style texture patterns (grass, dirt, stone) - Crisp black outlines for definition Y-Layer Stacking System: - GRASS_FULL: All green (elevation > 0.7) - GRASS_TOP: Green top + brown sides (elevation 0.4-0.7) - DIRT: All brown (elevation < 0.4) - Dynamic terrain depth based on height Floating Island World Edge: - Stone cliff walls at map borders - 2-tile transition zone - Elevation flattening for cliff drop-off effect - 100x100 world with defined boundaries Performance & Polish: - Canvas renderer for pixel-perfect sharpness - CSS image-rendering: crisp-edges - willReadFrequently optimization - No Canvas2D warnings Technical: - 3D volumetric trees and rocks - Hybrid rendering (2.5D terrain + 2D characters) - Procedural texture generation - Y-layer aware terrain type selection
This commit is contained in:
198
src/systems/ParallaxSystem.js
Normal file
198
src/systems/ParallaxSystem.js
Normal file
@@ -0,0 +1,198 @@
|
||||
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)
|
||||
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 = [];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user