feat: Add Editor Mode (Palette, Eraser, Path Tiles), generate assets, enable WASD
This commit is contained in:
@@ -20,6 +20,19 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
|
||||
// 4. Items & Charts
|
||||
this.load.image('hay', 'DEMO_FAZA1/Items/hay_drop_0.png');
|
||||
this.load.image('trnje', 'DEMO_FAZA1/Obstacles/trnje.png');
|
||||
|
||||
// Generated Assets (Slices)
|
||||
this.load.image('tree_adult_0', 'DEMO_FAZA1/Trees/tree_adult_0.png');
|
||||
this.load.image('tree_adult_1', 'DEMO_FAZA1/Trees/tree_adult_1.png');
|
||||
this.load.image('dead_nature_0', 'DEMO_FAZA1/Environment/dead_nature_0.png'); // Stump
|
||||
this.load.image('fence_sign_0', 'DEMO_FAZA1/Environment/fence_sign_0.png'); // Fence
|
||||
// this.load.image('path_mud_0', 'DEMO_FAZA1/Ground/path_mud_0.png'); // Old single slice
|
||||
|
||||
// Tileset (Grid Slices)
|
||||
for (let i = 0; i < 16; i++) {
|
||||
this.load.image(`path_tile_${i}`, `DEMO_FAZA1/Ground/path_tile_${i}.png`);
|
||||
}
|
||||
// REPLACED STATIC KAI WITH SPRITE SHEET
|
||||
// Frame size 256x256 based on 1024x1024 sheet
|
||||
this.load.spritesheet('kai', 'DEMO_FAZA1/Characters/kai_walk_sheet.png', {
|
||||
@@ -73,6 +86,7 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
this.stream = this.physics.add.staticImage(startX, startY, 'stream_final_v7');
|
||||
this.stream.setOrigin(0.5, 0.5);
|
||||
this.stream.setDepth(-50);
|
||||
this.stream.setInteractive({ draggable: true }); // Enable Dragging
|
||||
|
||||
// Physics Body for Main
|
||||
this.stream.body.setSize(this.stream.width * 0.8, this.stream.height * 0.2);
|
||||
@@ -86,8 +100,154 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
// --- 3. FOLIAGE (Trava - Šopi) ---
|
||||
// Removed as requested
|
||||
|
||||
// --- 4. ITEMS (Seno) ---
|
||||
// Removed as requested
|
||||
// --- 4. ITEMS & OBSTACLES ---
|
||||
// Trnje (Thorns) - Draggable
|
||||
this.trnje = this.add.image(startX - 200, startY + 100, 'trnje');
|
||||
this.trnje.setScale(0.5); // Adjust scale if needed
|
||||
this.trnje.setInteractive({ draggable: true });
|
||||
|
||||
// General Drag Event
|
||||
this.input.on('drag', function (pointer, gameObject, dragX, dragY) {
|
||||
gameObject.x = dragX;
|
||||
gameObject.y = dragY;
|
||||
});
|
||||
|
||||
// --- EDITOR MODE SYSTEM ---
|
||||
this.editorEnabled = false;
|
||||
this.selectedTile = 'path_tile_0';
|
||||
this.editorGroup = this.add.group(); // Saved tiles
|
||||
|
||||
// Toggle Key
|
||||
this.input.keyboard.on('keydown-E', () => {
|
||||
this.editorEnabled = !this.editorEnabled;
|
||||
this.paletteContainer.setVisible(this.editorEnabled);
|
||||
console.log("Editor Mode:", this.editorEnabled);
|
||||
});
|
||||
|
||||
// UI Palette (Hidden by default)
|
||||
// FIX: Use viewport dimensions for UI
|
||||
const VIEW_W = this.scale.width;
|
||||
const VIEW_H = this.scale.height;
|
||||
|
||||
this.paletteContainer = this.add.container(0, 0).setScrollFactor(0).setVisible(false).setDepth(1000);
|
||||
|
||||
// Background for Palette (TOP OF SCREEN)
|
||||
// Moved to y=100 so it covers top 0-200px
|
||||
let bg = this.add.rectangle(VIEW_W / 2, 100, VIEW_W, 200, 0x000000, 0.7);
|
||||
this.paletteContainer.add(bg);
|
||||
|
||||
// Generate Eraser Texture
|
||||
let g = this.make.graphics().fillStyle(0xFF0000).fillRect(0, 0, 64, 64);
|
||||
g.generateTexture('eraser_icon', 64, 64);
|
||||
g.destroy();
|
||||
|
||||
// Populate Palette
|
||||
// 16 Path Tiles + Fence + Stump + Eraser
|
||||
const paletteItems = [];
|
||||
for (let i = 0; i < 16; i++) paletteItems.push(`path_tile_${i}`);
|
||||
paletteItems.push('fence_sign_0');
|
||||
paletteItems.push('eraser_icon');
|
||||
|
||||
let px = 100;
|
||||
let py = 100; // TOP
|
||||
|
||||
const icons = []; // Store references for tinting
|
||||
console.log("Palette View:", VIEW_W, VIEW_H); // Debug
|
||||
paletteItems.forEach((key) => {
|
||||
let icon = this.add.image(px, py, key).setScale(0.3).setInteractive({ useHandCursor: true });
|
||||
icons.push(icon); // Track it
|
||||
|
||||
icon.on('pointerover', () => {
|
||||
if (this.selectedTile !== key) icon.setTint(0xFFFF00); // Yellow on hover
|
||||
});
|
||||
icon.on('pointerout', () => {
|
||||
if (this.selectedTile !== key) icon.clearTint(); // Clear if not selected
|
||||
else icon.setTint(0x00FF00); // Keep Green if selected
|
||||
});
|
||||
icon.on('pointerdown', () => {
|
||||
this.selectedTile = key;
|
||||
console.log("Selected Brush:", key);
|
||||
// Visual feedback: Tint selected Green, clear others
|
||||
icons.forEach(i => i.clearTint());
|
||||
icon.setTint(0x00FF00);
|
||||
});
|
||||
this.paletteContainer.add(icon);
|
||||
px += 80;
|
||||
if (px > VIEW_W - 100) { px = 100; py += 80; } // wrap
|
||||
});
|
||||
|
||||
// Painting Logic
|
||||
this.input.on('pointerdown', (pointer) => {
|
||||
if (!this.editorEnabled) return;
|
||||
// Ignore clicks on UI (Check Y < 200)
|
||||
if (pointer.y < 200) return;
|
||||
|
||||
// ERASER MODE: Handled via object clicks
|
||||
if (this.selectedTile === 'eraser_icon') return;
|
||||
|
||||
// Snap to Grid (128px for finer control, or 256px for full tiles)
|
||||
const SNAP = 128;
|
||||
const wx = pointer.worldX;
|
||||
const wy = pointer.worldY;
|
||||
const sx = Math.floor(wx / SNAP) * SNAP + (SNAP / 2);
|
||||
const sy = Math.floor(wy / SNAP) * SNAP + (SNAP / 2);
|
||||
|
||||
let placedStub = this.add.image(sx, sy, this.selectedTile);
|
||||
placedStub.setInteractive(); // Enable erase interaction
|
||||
|
||||
// Delete if clicked with eraser
|
||||
placedStub.on('pointerdown', () => {
|
||||
if (this.editorEnabled && this.selectedTile === 'eraser_icon') {
|
||||
placedStub.destroy();
|
||||
// Prevent click propagation?
|
||||
}
|
||||
});
|
||||
|
||||
if (this.selectedTile.includes('path')) {
|
||||
placedStub.setDepth(-40); // Above ground
|
||||
placedStub.setScale(0.5);
|
||||
} else {
|
||||
placedStub.setDepth(sy); // Y-sort
|
||||
// placedStub.setInteractive({ draggable: true }); // Draggable requires careful event handling vs eraser
|
||||
// Let's enable drag ONLY if not eraser?
|
||||
// For now, prioritize Eraser. Dragging might conflict with 'pointerdown' erase.
|
||||
// Or better: enable Drag, but if Eraser selected, destroy on click.
|
||||
}
|
||||
this.editorGroup.add(placedStub);
|
||||
});
|
||||
|
||||
// --- PREVIOUSLY GENERATED PROPS (Draggable Example) ---
|
||||
// Commented out per request "samo blatno potko"
|
||||
/*
|
||||
const propAssets = ['tree_adult_0', 'tree_adult_1', 'dead_nature_0'];
|
||||
for (let i = 0; i < propAssets.length; i++) {
|
||||
let item = this.add.image(startX + 200 + (i * 100), startY + 200, propAssets[i]);
|
||||
item.setInteractive({ draggable: true });
|
||||
}
|
||||
*/
|
||||
|
||||
// --- RECONSTRUCT PATH (4x4 GRID) ---
|
||||
// Image was 1024x1024, sliced into 256x256 (4 cols, 4 rows)
|
||||
// Indices 0..15
|
||||
let pIndex = 0;
|
||||
const GRID_SZ = 256;
|
||||
for (let r = 0; r < 4; r++) {
|
||||
for (let c = 0; c < 4; c++) {
|
||||
// Determine Tile Key
|
||||
let key = `path_tile_${pIndex}`;
|
||||
// Place it
|
||||
// Center offset: -1.5 * size to center the 4x4 block
|
||||
let px = startX + (c * GRID_SZ) + 200;
|
||||
let py = startY + (r * GRID_SZ) + 200;
|
||||
|
||||
let tile = this.add.image(px, py, key);
|
||||
tile.setDepth(-40); // Ground level
|
||||
// Optional: make draggable? User said "naredi", maybe fixed?
|
||||
// tile.setInteractive({ draggable: true });
|
||||
|
||||
pIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// --- 5. CHAR (Kai) ---
|
||||
this.kai = this.physics.add.sprite(WORLD_W / 2, WORLD_H / 2, 'kai');
|
||||
@@ -138,6 +298,13 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
// Camera setup logic
|
||||
this.cameras.main.startFollow(this.kai, true, 0.1, 0.1);
|
||||
this.cursors = this.input.keyboard.createCursorKeys();
|
||||
// Add WASD keys
|
||||
this.keys = this.input.keyboard.addKeys({
|
||||
up: Phaser.Input.Keyboard.KeyCodes.W,
|
||||
down: Phaser.Input.Keyboard.KeyCodes.S,
|
||||
left: Phaser.Input.Keyboard.KeyCodes.A,
|
||||
right: Phaser.Input.Keyboard.KeyCodes.D
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -196,25 +363,31 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
|
||||
let moving = false;
|
||||
|
||||
if (this.cursors.left.isDown) {
|
||||
// Input helpers
|
||||
const left = this.cursors.left.isDown || this.keys.left.isDown;
|
||||
const right = this.cursors.right.isDown || this.keys.right.isDown;
|
||||
const up = this.cursors.up.isDown || this.keys.up.isDown;
|
||||
const down = this.cursors.down.isDown || this.keys.down.isDown;
|
||||
|
||||
if (left) {
|
||||
this.kai.setVelocityX(-speed);
|
||||
this.kai.play('walk-left', true);
|
||||
moving = true;
|
||||
} else if (this.cursors.right.isDown) {
|
||||
} else if (right) {
|
||||
this.kai.setVelocityX(speed);
|
||||
this.kai.play('walk-right', true);
|
||||
moving = true;
|
||||
}
|
||||
|
||||
if (this.cursors.up.isDown) {
|
||||
if (up) {
|
||||
this.kai.setVelocityY(-speed);
|
||||
if (!this.cursors.left.isDown && !this.cursors.right.isDown) {
|
||||
if (!left && !right) {
|
||||
this.kai.play('walk-up', true);
|
||||
}
|
||||
moving = true;
|
||||
} else if (this.cursors.down.isDown) {
|
||||
} else if (down) {
|
||||
this.kai.setVelocityY(speed);
|
||||
if (!this.cursors.left.isDown && !this.cursors.right.isDown) {
|
||||
if (!left && !right) {
|
||||
this.kai.play('walk-down', true);
|
||||
}
|
||||
moving = true;
|
||||
|
||||
Reference in New Issue
Block a user