Files
novafarma/docs/RESOURCE_COLLECTION_GUIDE.md
NovaFarma Dev 80bddf5d61 feat: Complete 2D Visual Overhaul - Isometric to Flat Top-Down
- NEW: Flat2DTerrainSystem.js (375 lines)
- NEW: map2d_data.js procedural map (221 lines)
- MODIFIED: GameScene async create, 2D terrain integration
- MODIFIED: Player.js flat 2D positioning
- MODIFIED: game.js disabled pixelArt for smooth rendering
- FIXED: 15+ bugs (updateCulling, isometric conversions, grid lines)
- ADDED: Phase 28 to TASKS.md
- DOCS: DNEVNIK.md session summary

Result: Working flat 2D game with Stardew Valley style!
Time: 5.5 hours
2025-12-14 17:12:40 +01:00

8.2 KiB

🎯 Resource Collection System Guide

Vodič za zbiranje recursos (drevesa, kamni) v KRVAVA ŽETEV igri.


📖 Pregled

Igra uporablja HYBRID sistem za zbiranje resources:

  • ⌨️ Keyboard kontrola - SPACE + proximity (traditional)
  • 🖱️ Mouse/Touch kontrola - Click-to-collect (modern)
  • 🎨 Visual feedback - Hover highlights, shake effects
  • 📏 Proximity check - Mora biti blizu (3 tiles)
  • 🛠️ Tool system - Potrebuj pravilno orodje

🎮 NAČIN 1: Keyboard Control (SPACE)

Kako deluje:

1. Hodi do drevesa/kamna (WASD)
2. Približaj se (< 3 tiles)  
3. Pritisni SPACE
4. Orodje se zamahne
5. Objekt prejme damage
6. Po 3 hitih → drop items

Prednosti:

  • Traditional gameplay
  • Balanciran (število hits)
  • Keyboard-friendly
  • No accidental clicks

🖱️ NAČIN 2: Click-to-Collect

Kako deluje:

1. Klikni na drevo/kamen (direktno)
2. Sistem preveri proximity (< 3 tiles)
3. Preveri orodje (axe, pickaxe)
4. Če OK → damage objekt
5. Če NE → floating text "Preblizu!"

Features:

  • Hover highlight - Yellow tint on mouseover
  • Hand cursor - Cursor changes to hand
  • Proximity check - Must be within 3 tiles
  • Tool check - Requires correct tool
  • Shake effect - Visual feedback if too far
  • Sound effects - Chop/mine sounds

🔧 Implementacija

TerrainSystem.js - Pointer Events

// V updateCulling() kjer se renderajo decorations
const sprite = this.decorationPool.get();

// ... position, texture, scale setup ...

// 🎯 HYBRID POINTER EVENTS
const isCollectible = decor.type.includes('tree') || 
                     decor.type.includes('rock') ||
                     decor.type.includes('bush') ||
                     decor.type.includes('flower');

if (isCollectible) {
    // Make interactive
    sprite.setInteractive({ useHandCursor: true });
    
    // Store metadata
    sprite.setData('gridX', x);
    sprite.setData('gridY', y);
    sprite.setData('decorType', decor.type);
    
    // HOVER EVENT - Yellow highlight
    sprite.on('pointerover', () => {
        sprite.setTint(0xffff00);
    });
    
    sprite.on('pointerout', () => {
        sprite.clearTint();
    });
    
    // CLICK EVENT - Collect
    sprite.on('pointerdown', () => {
        this.handleResourceClick(x, y, decor.type, sprite);
    });
}

handleResourceClick() - Click Handler

handleResourceClick(x, y, decorType, sprite) {
    // 1. Get player position
    const playerPos = this.scene.player.getPosition();
    
    // 2. PROXIMITY CHECK (< 3 tiles)
    const distance = Phaser.Math.Distance.Between(
        playerPos.x, playerPos.y, x, y
    );
    
    if (distance > 3) {
        // Shake sprite
        this.scene.tweens.add({
            targets: sprite,
            x: sprite.x + 5,
            duration: 50,
            yoyo: true,
            repeat: 2
        });
        
        // Show warning
        this.scene.events.emit('show-floating-text', {
            x: sprite.x,
            y: sprite.y - 50,
            text: 'Preblizu!',
            color: '#ff4444'
        });
        
        return;
    }
    
    // 3. TOOL CHECK
    const requiredTool = this.getRequiredTool(decorType);
    const hasTool = this.scene.player.hasToolEquipped(requiredTool);
    
    if (!hasTool && requiredTool) {
        this.scene.events.emit('show-floating-text', {
            x: sprite.x,
            y: sprite.y - 50,
            text: `Potrebuješ: ${requiredTool}`,
            color: '#ff4444'
        });
        return;
    }
    
    // 4. COLLECT - Damage decoration
    this.damageDecoration(x, y, 1); // 1 hit per click
    
    // Sound effect
    if (decorType.includes('tree')) {
        this.scene.soundManager.playChopSound();
    } else if (decorType.includes('rock')) {
        this.scene.soundManager.playMineSound();
    }
}

getRequiredTool(decorType) {
    if (decorType.includes('tree')) return 'axe';
    if (decorType.includes('rock')) return 'pickaxe';
    if (decorType.includes('bush')) return 'axe';
    return null; // No tool required
}

Player.js - Tool Check

hasToolEquipped(toolType) {
    if (!toolType) return true; // No tool required
    
    // Check inventory for tool
    if (this.scene.inventorySystem) {
        return this.scene.inventorySystem.hasItem(toolType, 1);
    }
    
    return false;
}

📊 Primerjava

Feature Keyboard (SPACE) Click-to-Collect
Platform PC (keyboard) PC + Mobile + Tablet
Precision Walk-to + SPACE Direct click
Learning Curve Easy Very Easy
Accidental Actions Low Medium
UX Traditional Modern
Touch Support NO YES

🎯 Tool System

Resource Required Tool Drop Items
🌳 Tree Axe Wood (5x)
🪨 Rock Pickaxe Stone (3x)
🌿 Bush Axe Berries (2x)
🌸 Flowers None Flower (1x)

🎨 Visual Feedback

Hover Effect:

sprite.on('pointerover', () => {
    sprite.setTint(0xffff00); // Yellow highlight
});

sprite.on('pointerout', () => {
    sprite.clearTint(); // Remove highlight
});

Shake Effect (Too Far):

this.scene.tweens.add({
    targets: sprite,
    x: sprite.x + 5,
    duration: 50,
    yoyo: true,
    repeat: 2
});

Floating Text:

this.scene.events.emit('show-floating-text', {
    x: sprite.x,
    y: sprite.y - 50,
    text: 'Preblizu!',
    color: '#ff4444'
});

💡 Best Practices

DO:

  • Uporabi hover highlights za visual feedback
  • Preveri proximity (< 3 tiles)
  • Preveri orodje pred akcijo
  • Dodaj sound effects
  • Uporabi consistent cursor (hand)

DON'T:

  • Ne dovoli instant collect brez proximity
  • Ne pozabi tool check
  • Ne dopusti klikanja skozi zidove
  • Ne pozabi clear tint on pointerout

🚀 Advanced Features

Instant Collect Mode:

// Če želiš 1-click collect (brez HP sistema)
this.damageDecoration(x, y, 999); // Instant destroy

Auto-Walk to Resource:

sprite.on('pointerdown', (pointer, localX, localY, event) => {
    const distance = Phaser.Math.Distance.Between(
        playerX, playerY, x, y
    );
    
    if (distance > 3) {
        // Auto-walk to resource
        this.scene.player.pathfindTo(x, y, () => {
            this.handleResourceClick(x, y, decorType, sprite);
        });
    } else {
        // Collect immediately
        this.handleResourceClick(x, y, decorType, sprite);
    }
});

Multi-Resource Selection:

// Hold SHIFT + click multiple resources
if (pointer.shiftKey) {
    this.selectedResources.push({ x, y, type: decorType });
} else {
    this.handleResourceClick(x, y, decorType, sprite);
}

🐛 Troubleshooting

Problem: Click ne deluje

// Preveri če je interactive:
console.log(sprite.input); // Should exist

// Preveri event listener:
sprite.listenerCount('pointerdown'); // Should be > 0

Problem: Hover highlight ostane

// Vedno clear tint on pointerout:
sprite.on('pointerout', () => {
    sprite.clearTint();
});

Problem: Klikanje deluje skozi zidove

// Dodaj raycast check:
const line = new Phaser.Geom.Line(
    playerX, playerY, x, y
);

const hasObstacle = this.checkLineCollision(line);
if (hasObstacle) {
    console.log('Path blocked!');
    return;
}

📱 Mobile Support

Pointer events avtomatično delujejo na touch devices:

  • pointerdown = tap
  • pointerover = ne deluje (no hover on touch)
  • pointerout = ne deluje

Priporočilo: Dodaj visual feedback brez hover efekta:

// Selected tint (ostane dokler ni zbran)
sprite.on('pointerdown', () => {
    sprite.setTint(0x00ff00); // Green selected
    
    // ... collect logic ...
    
    // Remove tint when destroyed
    sprite.clearTint();
});

Zadnja posodobitev: 14.12.2025
Avtor: KRVAVA ŽETEV Team
Status: Hybrid system implemented
Files: TerrainSystem.js, Player.js