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
This commit is contained in:
2025-12-14 17:12:40 +01:00
parent c3dd39e1a6
commit 80bddf5d61
37 changed files with 8164 additions and 1800 deletions

View File

@@ -0,0 +1,364 @@
# 🎯 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**
```javascript
// 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**
```javascript
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**
```javascript
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:**
```javascript
sprite.on('pointerover', () => {
sprite.setTint(0xffff00); // Yellow highlight
});
sprite.on('pointerout', () => {
sprite.clearTint(); // Remove highlight
});
```
### **Shake Effect (Too Far):**
```javascript
this.scene.tweens.add({
targets: sprite,
x: sprite.x + 5,
duration: 50,
yoyo: true,
repeat: 2
});
```
### **Floating Text:**
```javascript
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:**
```javascript
// Če želiš 1-click collect (brez HP sistema)
this.damageDecoration(x, y, 999); // Instant destroy
```
### **Auto-Walk to Resource:**
```javascript
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:**
```javascript
// 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**
```javascript
// Preveri če je interactive:
console.log(sprite.input); // Should exist
// Preveri event listener:
sprite.listenerCount('pointerdown'); // Should be > 0
```
### **Problem: Hover highlight ostane**
```javascript
// Vedno clear tint on pointerout:
sprite.on('pointerout', () => {
sprite.clearTint();
});
```
### **Problem: Klikanje deluje skozi zidove**
```javascript
// 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:
```javascript
// 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`