- 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
365 lines
8.2 KiB
Markdown
365 lines
8.2 KiB
Markdown
# 🎯 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`
|