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:
364
docs/RESOURCE_COLLECTION_GUIDE.md
Normal file
364
docs/RESOURCE_COLLECTION_GUIDE.md
Normal 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`
|
||||
Reference in New Issue
Block a user