- 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
8.2 KiB
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= tappointerover= 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