diff --git a/assets/.DS_Store b/assets/.DS_Store index e65ce88ab..e49b28bfa 100644 Binary files a/assets/.DS_Store and b/assets/.DS_Store differ diff --git a/assets/DEMO_FAZA1/.DS_Store b/assets/DEMO_FAZA1/.DS_Store index 3bc6613ca..61d6972ac 100644 Binary files a/assets/DEMO_FAZA1/.DS_Store and b/assets/DEMO_FAZA1/.DS_Store differ diff --git a/assets/DEMO_FAZA1/Environment/dead_nature_0.png b/assets/DEMO_FAZA1/Environment/dead_nature_0.png new file mode 100644 index 000000000..3f7b57f38 Binary files /dev/null and b/assets/DEMO_FAZA1/Environment/dead_nature_0.png differ diff --git a/assets/DEMO_FAZA1/Environment/dead_nature_1.png b/assets/DEMO_FAZA1/Environment/dead_nature_1.png new file mode 100644 index 000000000..a5ffc204a Binary files /dev/null and b/assets/DEMO_FAZA1/Environment/dead_nature_1.png differ diff --git a/assets/DEMO_FAZA1/Environment/dead_nature_2.png b/assets/DEMO_FAZA1/Environment/dead_nature_2.png new file mode 100644 index 000000000..dd63b75ad Binary files /dev/null and b/assets/DEMO_FAZA1/Environment/dead_nature_2.png differ diff --git a/assets/DEMO_FAZA1/Environment/dead_nature_3.png b/assets/DEMO_FAZA1/Environment/dead_nature_3.png new file mode 100644 index 000000000..e49e7466c Binary files /dev/null and b/assets/DEMO_FAZA1/Environment/dead_nature_3.png differ diff --git a/assets/DEMO_FAZA1/Environment/dead_nature_4.png b/assets/DEMO_FAZA1/Environment/dead_nature_4.png new file mode 100644 index 000000000..7459ff6ed Binary files /dev/null and b/assets/DEMO_FAZA1/Environment/dead_nature_4.png differ diff --git a/assets/DEMO_FAZA1/Environment/dead_nature_5.png b/assets/DEMO_FAZA1/Environment/dead_nature_5.png new file mode 100644 index 000000000..c500c956a Binary files /dev/null and b/assets/DEMO_FAZA1/Environment/dead_nature_5.png differ diff --git a/assets/DEMO_FAZA1/Environment/dead_nature_6.png b/assets/DEMO_FAZA1/Environment/dead_nature_6.png new file mode 100644 index 000000000..e29dfd5bd Binary files /dev/null and b/assets/DEMO_FAZA1/Environment/dead_nature_6.png differ diff --git a/assets/DEMO_FAZA1/Environment/dead_nature_7.png b/assets/DEMO_FAZA1/Environment/dead_nature_7.png new file mode 100644 index 000000000..66ba5746b Binary files /dev/null and b/assets/DEMO_FAZA1/Environment/dead_nature_7.png differ diff --git a/assets/DEMO_FAZA1/Environment/dead_nature_8.png b/assets/DEMO_FAZA1/Environment/dead_nature_8.png new file mode 100644 index 000000000..31fa11e41 Binary files /dev/null and b/assets/DEMO_FAZA1/Environment/dead_nature_8.png differ diff --git a/assets/DEMO_FAZA1/Environment/fence_sign_0.png b/assets/DEMO_FAZA1/Environment/fence_sign_0.png new file mode 100644 index 000000000..0dfc666f1 Binary files /dev/null and b/assets/DEMO_FAZA1/Environment/fence_sign_0.png differ diff --git a/assets/DEMO_FAZA1/Environment/fence_sign_1.png b/assets/DEMO_FAZA1/Environment/fence_sign_1.png new file mode 100644 index 000000000..38054d454 Binary files /dev/null and b/assets/DEMO_FAZA1/Environment/fence_sign_1.png differ diff --git a/assets/DEMO_FAZA1/Environment/fence_sign_2.png b/assets/DEMO_FAZA1/Environment/fence_sign_2.png new file mode 100644 index 000000000..1fcc6e097 Binary files /dev/null and b/assets/DEMO_FAZA1/Environment/fence_sign_2.png differ diff --git a/assets/DEMO_FAZA1/Environment/stream_v5_graded.png b/assets/DEMO_FAZA1/Environment/stream_v5_graded.png deleted file mode 100644 index 392ce700c..000000000 Binary files a/assets/DEMO_FAZA1/Environment/stream_v5_graded.png and /dev/null differ diff --git a/assets/DEMO_FAZA1/Ground/path_mud_0.png b/assets/DEMO_FAZA1/Ground/path_mud_0.png new file mode 100644 index 000000000..78013736a Binary files /dev/null and b/assets/DEMO_FAZA1/Ground/path_mud_0.png differ diff --git a/assets/DEMO_FAZA1/Ground/path_tile_0.png b/assets/DEMO_FAZA1/Ground/path_tile_0.png new file mode 100644 index 000000000..b7e596b14 Binary files /dev/null and b/assets/DEMO_FAZA1/Ground/path_tile_0.png differ diff --git a/assets/DEMO_FAZA1/Ground/path_tile_1.png b/assets/DEMO_FAZA1/Ground/path_tile_1.png new file mode 100644 index 000000000..057f3689e Binary files /dev/null and b/assets/DEMO_FAZA1/Ground/path_tile_1.png differ diff --git a/assets/DEMO_FAZA1/Ground/path_tile_10.png b/assets/DEMO_FAZA1/Ground/path_tile_10.png new file mode 100644 index 000000000..d5fb2504c Binary files /dev/null and b/assets/DEMO_FAZA1/Ground/path_tile_10.png differ diff --git a/assets/DEMO_FAZA1/Ground/path_tile_11.png b/assets/DEMO_FAZA1/Ground/path_tile_11.png new file mode 100644 index 000000000..c55cc2e17 Binary files /dev/null and b/assets/DEMO_FAZA1/Ground/path_tile_11.png differ diff --git a/assets/DEMO_FAZA1/Ground/path_tile_12.png b/assets/DEMO_FAZA1/Ground/path_tile_12.png new file mode 100644 index 000000000..1ae197066 Binary files /dev/null and b/assets/DEMO_FAZA1/Ground/path_tile_12.png differ diff --git a/assets/DEMO_FAZA1/Ground/path_tile_13.png b/assets/DEMO_FAZA1/Ground/path_tile_13.png new file mode 100644 index 000000000..fba8798b6 Binary files /dev/null and b/assets/DEMO_FAZA1/Ground/path_tile_13.png differ diff --git a/assets/DEMO_FAZA1/Ground/path_tile_14.png b/assets/DEMO_FAZA1/Ground/path_tile_14.png new file mode 100644 index 000000000..3c69d43a8 Binary files /dev/null and b/assets/DEMO_FAZA1/Ground/path_tile_14.png differ diff --git a/assets/DEMO_FAZA1/Ground/path_tile_15.png b/assets/DEMO_FAZA1/Ground/path_tile_15.png new file mode 100644 index 000000000..e204c6fde Binary files /dev/null and b/assets/DEMO_FAZA1/Ground/path_tile_15.png differ diff --git a/assets/DEMO_FAZA1/Ground/path_tile_2.png b/assets/DEMO_FAZA1/Ground/path_tile_2.png new file mode 100644 index 000000000..3784f395a Binary files /dev/null and b/assets/DEMO_FAZA1/Ground/path_tile_2.png differ diff --git a/assets/DEMO_FAZA1/Ground/path_tile_3.png b/assets/DEMO_FAZA1/Ground/path_tile_3.png new file mode 100644 index 000000000..bbc6b304c Binary files /dev/null and b/assets/DEMO_FAZA1/Ground/path_tile_3.png differ diff --git a/assets/DEMO_FAZA1/Ground/path_tile_4.png b/assets/DEMO_FAZA1/Ground/path_tile_4.png new file mode 100644 index 000000000..b9bd252af Binary files /dev/null and b/assets/DEMO_FAZA1/Ground/path_tile_4.png differ diff --git a/assets/DEMO_FAZA1/Ground/path_tile_5.png b/assets/DEMO_FAZA1/Ground/path_tile_5.png new file mode 100644 index 000000000..dddf0b089 Binary files /dev/null and b/assets/DEMO_FAZA1/Ground/path_tile_5.png differ diff --git a/assets/DEMO_FAZA1/Ground/path_tile_6.png b/assets/DEMO_FAZA1/Ground/path_tile_6.png new file mode 100644 index 000000000..f85305421 Binary files /dev/null and b/assets/DEMO_FAZA1/Ground/path_tile_6.png differ diff --git a/assets/DEMO_FAZA1/Ground/path_tile_7.png b/assets/DEMO_FAZA1/Ground/path_tile_7.png new file mode 100644 index 000000000..78eb0b8f1 Binary files /dev/null and b/assets/DEMO_FAZA1/Ground/path_tile_7.png differ diff --git a/assets/DEMO_FAZA1/Ground/path_tile_8.png b/assets/DEMO_FAZA1/Ground/path_tile_8.png new file mode 100644 index 000000000..1472d9cf3 Binary files /dev/null and b/assets/DEMO_FAZA1/Ground/path_tile_8.png differ diff --git a/assets/DEMO_FAZA1/Ground/path_tile_9.png b/assets/DEMO_FAZA1/Ground/path_tile_9.png new file mode 100644 index 000000000..e68ccf24e Binary files /dev/null and b/assets/DEMO_FAZA1/Ground/path_tile_9.png differ diff --git a/assets/DEMO_FAZA1/Obstacles/trnje.png b/assets/DEMO_FAZA1/Obstacles/trnje.png new file mode 100644 index 000000000..0ee47dbdc Binary files /dev/null and b/assets/DEMO_FAZA1/Obstacles/trnje.png differ diff --git a/assets/DEMO_FAZA1/Trees/tree_adult_0.png b/assets/DEMO_FAZA1/Trees/tree_adult_0.png new file mode 100644 index 000000000..66e7b684b Binary files /dev/null and b/assets/DEMO_FAZA1/Trees/tree_adult_0.png differ diff --git a/assets/DEMO_FAZA1/Trees/tree_adult_1.png b/assets/DEMO_FAZA1/Trees/tree_adult_1.png new file mode 100644 index 000000000..22f661ca0 Binary files /dev/null and b/assets/DEMO_FAZA1/Trees/tree_adult_1.png differ diff --git a/assets/DEMO_FAZA1/Trees/tree_adult_2.png b/assets/DEMO_FAZA1/Trees/tree_adult_2.png new file mode 100644 index 000000000..34155fee3 Binary files /dev/null and b/assets/DEMO_FAZA1/Trees/tree_adult_2.png differ diff --git a/assets/DEMO_FAZA1/Trees/tree_adult_3.png b/assets/DEMO_FAZA1/Trees/tree_adult_3.png new file mode 100644 index 000000000..54e2be0c1 Binary files /dev/null and b/assets/DEMO_FAZA1/Trees/tree_adult_3.png differ diff --git a/assets/DEMO_FAZA1/Trees/tree_adult_4.png b/assets/DEMO_FAZA1/Trees/tree_adult_4.png new file mode 100644 index 000000000..c7157920b Binary files /dev/null and b/assets/DEMO_FAZA1/Trees/tree_adult_4.png differ diff --git a/assets/DEMO_FAZA1/Trees/tree_adult_5.png b/assets/DEMO_FAZA1/Trees/tree_adult_5.png new file mode 100644 index 000000000..7b651e1ec Binary files /dev/null and b/assets/DEMO_FAZA1/Trees/tree_adult_5.png differ diff --git a/scripts/slice_assets.py b/scripts/slice_assets.py new file mode 100644 index 000000000..24466564d --- /dev/null +++ b/scripts/slice_assets.py @@ -0,0 +1,142 @@ + +import cv2 +import numpy as np +import os +import glob + +# Configuration +# Input files (Generated images) +INPUT_FILES = [ + { + 'path': '/Users/davidkotnik/.gemini/antigravity/brain/8233d64e-0c17-43b1-b8b5-fbc41754e56b/trees_adult_noir_1769706733583.png', + 'prefix': 'tree_adult', + 'output_folder': 'assets/DEMO_FAZA1/Trees' + }, + { + 'path': '/Users/davidkotnik/.gemini/antigravity/brain/8233d64e-0c17-43b1-b8b5-fbc41754e56b/dead_nature_noir_1769706761105.png', + 'prefix': 'dead_nature', + 'output_folder': 'assets/DEMO_FAZA1/Environment' + }, + { + 'path': '/Users/davidkotnik/.gemini/antigravity/brain/8233d64e-0c17-43b1-b8b5-fbc41754e56b/fence_sign_noir_1769706790281.png', + 'prefix': 'fence_sign', + 'output_folder': 'assets/DEMO_FAZA1/Environment' + }, + { + 'path': '/Users/davidkotnik/.gemini/antigravity/brain/8233d64e-0c17-43b1-b8b5-fbc41754e56b/muddy_path_noir_v2_1769706866951.png', + 'prefix': 'path_tile', + 'output_folder': 'assets/DEMO_FAZA1/Ground', + 'mode': 'grid', + 'grid_size': 256 + } +] + +BASE_DIR = '/Users/davidkotnik/repos/novafarma' + +def process_and_slice(file_data): + full_path = file_data['path'] + prefix = file_data['prefix'] + out_dir_rel = file_data['output_folder'] + mode = file_data.get('mode', 'contour') # Default to contour + + out_dir = os.path.join(BASE_DIR, out_dir_rel) + + if not os.path.exists(out_dir): + os.makedirs(out_dir) + + print(f"Processing {prefix} from {full_path} in {mode} mode...") + + img = cv2.imread(full_path, cv2.IMREAD_COLOR) + if img is None: + print(f"Error loading {full_path}") + return + + h, w = img.shape[:2] + + if mode == 'grid': + # Split into fixed grid cells + tile_size = file_data.get('grid_size', 256) + rows = h // tile_size + cols = w // tile_size + + count = 0 + for r in range(rows): + for c in range(cols): + y = r * tile_size + x = c * tile_size + + roi = img[y:y+tile_size, x:x+tile_size] + + # Check if tile is empty (all white/uniform?) + # Calculate variance or average color. + if np.mean(roi) > 250: # Mostly white + continue + + # We can enable alpha here if needed, but for ground tiles usually we want Opaque? + # User wants "Tile Palette". Tiles usually have transparency if they are "Path on Grass". + # Let's clean white background using same threshold logic. + + roi_gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY) + _, roi_mask = cv2.threshold(roi_gray, 240, 255, cv2.THRESH_BINARY_INV) + + roi_bgra = cv2.cvtColor(roi, cv2.COLOR_BGR2BGRA) + roi_bgra[:, :, 3] = roi_mask + + # Save + filename = f"{prefix}_{count}.png" + out_path = os.path.join(out_dir, filename) + cv2.imwrite(out_path, roi_bgra) + print(f" Saved Grid Tile {filename}") + count += 1 + + else: # Contour mode (old logic) + # 1. Remove Background (White) -> Alpha + # Assuming white background. + # Convert to Gray for thresholding + gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + + # Threshold: Close to white (240+) is background + _, mask = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV) + # mask: White (255) is OBJECT, Black (0) is BACKGROUND + + # Clean mask (remove noise) + kernel = np.ones((3,3), np.uint8) + mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=1) + # Dilate slightly to include outlines? + # mask = cv2.dilate(mask, kernel, iterations=1) + + # 2. Find Contours (Separate Objects) + contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + + count = 0 + for i, c in enumerate(contours): + area = cv2.contourArea(c) + if area < 500: # Filter small noise + continue + + # Bounding box + x, y, w, h = cv2.boundingRect(c) + + # Crop + roi = img[y:y+h, x:x+w] + + # Create alpha channel for ROI + # We need a mask for this specific object in the ROI + roi_gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY) + # Re-threshold ROI to get clean alpha + _, roi_mask = cv2.threshold(roi_gray, 240, 255, cv2.THRESH_BINARY_INV) + + # Convert ROI to BGRA + roi_bgra = cv2.cvtColor(roi, cv2.COLOR_BGR2BGRA) + roi_bgra[:, :, 3] = roi_mask + + # Save + filename = f"{prefix}_{count}.png" + out_path = os.path.join(out_dir, filename) + cv2.imwrite(out_path, roi_bgra) + print(f" Saved {filename}") + count += 1 + +if __name__ == "__main__": + for f in INPUT_FILES: + process_and_slice(f) diff --git a/src/scenes/GrassScene_Clean.js b/src/scenes/GrassScene_Clean.js index 97fe8d08d..4cf11fc21 100644 --- a/src/scenes/GrassScene_Clean.js +++ b/src/scenes/GrassScene_Clean.js @@ -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;