farma orodje in dnevnik

This commit is contained in:
2025-12-08 01:55:39 +01:00
parent e49f567831
commit 860a10a5c3
2 changed files with 222 additions and 126 deletions

75
DNEVNIK.md Normal file
View File

@@ -0,0 +1,75 @@
# 📔 DNEVNIK RAZVOJA: KRVAVA ŽETEV (NOVA FARMA)
## 📅 Začetek Projekta
**Datum začetka:** 5. December 2025
**Lokacija:** Nova Farma (c:\novafarma)
**Engine:** Phaser 3 + Custom Antigravity Engine
**Stil:** 2.5D Izometrični Pixel Art / Voxel
---
## 🧟‍♂️ Koncept Igre & Zgodba
### Naslov: Krvava Žetev (Zombie Roots)
**Zgodba:**
Svet, kakršnega smo poznali, je propadel. Nisi vojak, nisi heroj – si kmet. Tvoja naloga ni zgolj preživeti, ampak ponovno pognati korenine civilizacije. Prebudiš se na zapuščeni kmetiji sredi opustošene dežele. Čez dan je svet varljiv: sonce sije na ruševine, trava raste in narava si jemlje nazaj, kar je njeno.
A ko pade noč, pridejo oni. **Prekleti.**
Tvoj cilj je obnoviti kmetijo, pridelati hrano (ki je zdaj najvrednejša valuta) in zgraditi obrambo. Trgovali boste z redkimi preživelimi trgovci, ki si upajo potovati med naselbinami.
**Ključne Mehanike:**
* **Farming (Kmetovanje):** Realistična rast pridelkov (koruza, pšenica, itd.). Vsaka rastlina ima svoj cikel.
* **Survival (Preživetje):** Lakota, žeja in spanje.
* **Combat (Boj):** Brani svojo letino pred nočnimi napadi zombijev.
* **Economy (Ekonomija):** Prodajaj pridelke za zlato, kupuj boljša orodja in semena.
---
## 🛠️ Dosedanji Napredek (Feature Log)
### Faza 1: Temelji (5. - 6. Dec 2025)
- [x] Vzpostavitev projekta (Node.js, Electron).
- [x] Implementacija **Antigravity Engine** (modularni sistem).
- [x] **Proceduralno Generiranje Sveta:** Uporaba Perlin Noise za ustvarjanje neskončnega, razgibanega terena (trava, voda, pesek).
- [x] Izometrična kamera in gibanje igralca.
### Faza 2: Sistemi Igre (6. - 7. Dec 2025)
- [x] **Farming System:**
- Oranje zemlje z motiko.
- Sajenje semen.
- Faze rasti (seme -> kalček -> rastlina -> zrelo).
- Žetev pridelkov.
- [x] **Inventory System:**
- Delujoč inventar z zlaganjem (stacking).
- Drag & Drop (še v delu) / Slot selection.
- [x] **Time & Weather System:**
- Cikel dan/noč z vizualno zatemnitvijo.
- Dež (zvočni in vizualni efekti), ki namaka zemljo.
### Faza 3: Poliranje in Realizem (8. Dec 2025 - Danes)
- [x] **Statistika in XP:**
- Dodan sistem izkušenj (XP). Igralec dobiva XP za sekanje dreves, rudarjenje in pobiranje pridelkov.
- Prikaz Levela in XP vrstice v HUD-u.
- [x] **Novi Pridelki:**
- **Pšenica:** Standardni pridelek, raste srednje hitro.
- **Koruza:** Visoka rast, počasnejša, a večji donos.
- Unikatne teksture za vsako fazo rasti.
- [x] **3D Voxel Orodja:**
- Proceduralno generirana orodja v 3D "Minecraft" stilu.
- Sekira, Kramp, Motika, Meč, Zalivalka - vsa imajo volumen in senčenje.
- [x] **Zvok:**
- Proceduralno generirani zvočni effekti (kopanje, sekanje, koraki).
- Popravek manjkajočih zvokov (`playDig`).
---
## 🔮 Vizija za Naprej (TODO)
1. **Napredni NPC-ji:** Trgovci, ki pridejo le ob določenih dnevih.
2. **Gradnja Baze:** Postavljanje ograj in stolpov za obrambo.
3. **Razširitev Sveta:** Dodajanje novih biomov (gozd, puščava).
4. **Save System:** Shranjevanje napredka v datoteko.
---
*Zadnja posodobitev: 8. December 2025 ob 01:55*

View File

@@ -136,23 +136,41 @@ class TextureGenerator {
}
static createCropSprite(scene, key, stage = 4) {
if (scene.textures.exists(key)) return;
if (scene.textures.exists(key)) scene.textures.remove(key); // FORCE REFRESH to see updates
const canvas = scene.textures.createCanvas(key, 32, 32);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 32, 32);
ctx.fillStyle = '#228B22'; // Stem
const h = stage * 5;
ctx.fillRect(14, 32 - h, 4, h);
// Improved Wheat Visuals
const startY = 32;
// 1. Stems (Green -> Yellowish)
ctx.fillStyle = (stage < 3) ? '#32CD32' : '#DAA520';
const h = stage * 6;
// Draw distinct stalks
ctx.fillRect(10, startY - h, 2, h); // Left stalk
ctx.fillRect(16, startY - h, 2, h); // Center stalk
ctx.fillRect(22, startY - h, 2, h); // Right stalk
// 2. Heads (Wheat ears) - Stage 3 & 4
if (stage >= 3) {
ctx.fillStyle = '#FFD700'; // Wheat head
ctx.beginPath(); ctx.arc(16, 32 - h, 6, 0, Math.PI * 2); ctx.fill();
ctx.fillStyle = '#FFD700'; // Gold
// Left head
ctx.beginPath(); ctx.ellipse(11, startY - h, 3, 5, -0.2, 0, Math.PI * 2); ctx.fill();
// Center head
ctx.beginPath(); ctx.ellipse(17, startY - h - 2, 3, 6, 0, 0, Math.PI * 2); ctx.fill();
// Right head
ctx.beginPath(); ctx.ellipse(23, startY - h, 3, 5, 0.2, 0, Math.PI * 2); ctx.fill();
}
if (stage === 5) { // Withered
// 3. Withered
if (stage === 5) {
ctx.fillStyle = '#8B4513';
ctx.fillRect(14, 20, 4, 12);
ctx.fillRect(10, 24, 14, 8); // Dead pile
}
canvas.refresh();
}
@@ -384,138 +402,104 @@ class TextureGenerator {
}
static createToolSprites(scene) {
// --- REALISTIC TOOLS (Procedural Generation) ---
// --- 3D VOXEL TOOLS ---
// 1. AXE (Sekira)
if (!scene.textures.exists('item_axe')) {
const c = scene.textures.createCanvas('item_axe', 32, 32);
const refresh = (key) => {
if (scene.textures.exists(key)) scene.textures.remove(key);
const c = scene.textures.createCanvas(key, 32, 32);
const ctx = c.getContext();
ctx.clearRect(0, 0, 32, 32);
return { c, ctx };
};
// Handle (Wood)
ctx.fillStyle = '#8B4513';
ctx.fillRect(14, 12, 4, 18);
// Head (Metal)
ctx.fillStyle = '#708090'; // SlateGray
ctx.beginPath();
ctx.moveTo(16, 12);
ctx.lineTo(24, 6); // Top edge
ctx.lineTo(24, 18); // Bottom edge
ctx.lineTo(16, 14); // Back to handle
ctx.fill();
// Edge (Sharp)
ctx.fillStyle = '#C0C0C0'; // Silver
ctx.fillRect(23, 6, 2, 12);
c.refresh();
}
// 2. PICKAXE (Kramp)
if (!scene.textures.exists('item_pickaxe')) {
const c = scene.textures.createCanvas('item_pickaxe', 32, 32);
const ctx = c.getContext();
ctx.clearRect(0, 0, 32, 32);
// Helper: Draw 3D Pixel/Block
const drawBlock = (ctx, x, y, color) => {
ctx.fillStyle = color;
ctx.fillRect(x, y, 2, 2); // Front
ctx.fillStyle = 'rgba(0,0,0,0.3)'; // Side shadow
ctx.fillRect(x + 2, y, 1, 2);
ctx.fillRect(x, y + 2, 3, 1);
};
// 1. AXE (3D)
{
const { c, ctx } = refresh('item_axe');
// Handle
ctx.fillStyle = '#8B4513';
ctx.fillRect(14, 10, 4, 20);
// Head (Curved Metal)
ctx.fillStyle = '#696969'; // DimGray
ctx.beginPath();
ctx.moveTo(6, 14); // Left tip
ctx.quadraticCurveTo(16, 4, 26, 14); // Curve over handle
ctx.lineTo(26, 16);
ctx.quadraticCurveTo(16, 8, 6, 16);
ctx.fill();
// Tips
ctx.fillStyle = '#DCDCDC';
ctx.fillRect(5, 14, 2, 2);
ctx.fillRect(25, 14, 2, 2);
c.refresh();
}
// 3. HOE (Motika)
if (!scene.textures.exists('item_hoe')) {
const c = scene.textures.createCanvas('item_hoe', 32, 32);
const ctx = c.getContext();
ctx.clearRect(0, 0, 32, 32);
// Handle
ctx.fillStyle = '#8B4513';
ctx.fillRect(14, 6, 4, 24);
for (let i = 0; i < 8; i++) drawBlock(ctx, 12 + i, 20 - i * 2, '#8B4513');
// Head
ctx.fillStyle = '#778899'; // LightSlateGray
ctx.fillRect(12, 6, 10, 4); // Top bar
ctx.fillRect(12, 6, 4, 8); // Blade down
// Blade Edge
ctx.fillStyle = '#C0C0C0';
ctx.fillRect(12, 12, 4, 2);
for (let x = 0; x < 3; x++) {
for (let y = 0; y < 4; y++) {
drawBlock(ctx, 18 + x * 2, 6 + y * 2, '#708090'); // Gray Metal
}
}
drawBlock(ctx, 24, 8, '#C0C0C0'); // Edge
drawBlock(ctx, 24, 10, '#C0C0C0');
c.refresh();
}
// 4. SWORD (Meč)
if (!scene.textures.exists('item_sword')) {
const c = scene.textures.createCanvas('item_sword', 32, 32);
const ctx = c.getContext();
ctx.clearRect(0, 0, 32, 32);
// 2. PICKAXE (3D)
{
const { c, ctx } = refresh('item_pickaxe');
// Handle
ctx.fillStyle = '#8B4513';
ctx.fillRect(15, 24, 2, 6);
// Pommel
ctx.fillStyle = '#FFD700'; // Gold
ctx.fillRect(14, 29, 4, 2);
for (let i = 0; i < 8; i++) drawBlock(ctx, 14, 8 + i * 2, '#8B4513');
// Head (Arc)
drawBlock(ctx, 6, 10, '#696969');
drawBlock(ctx, 8, 8, '#696969');
drawBlock(ctx, 10, 6, '#696969');
drawBlock(ctx, 12, 6, '#696969');
drawBlock(ctx, 14, 6, '#696969'); // Center
drawBlock(ctx, 16, 6, '#696969');
drawBlock(ctx, 18, 6, '#696969');
drawBlock(ctx, 20, 8, '#696969');
drawBlock(ctx, 22, 10, '#696969');
c.refresh();
}
// 3. HOE (3D)
{
const { c, ctx } = refresh('item_hoe');
// Handle
for (let i = 0; i < 9; i++) drawBlock(ctx, 14 + i, 4 + i * 2, '#8B4513');
// Head
drawBlock(ctx, 12, 4, '#778899');
drawBlock(ctx, 14, 4, '#778899');
drawBlock(ctx, 16, 6, '#778899');
drawBlock(ctx, 16, 8, '#778899'); // Blade
c.refresh();
}
// 4. SWORD (3D)
{
const { c, ctx } = refresh('item_sword');
// Handle
drawBlock(ctx, 14, 24, '#8B4513');
drawBlock(ctx, 14, 26, '#8B4513');
// Guard
ctx.fillStyle = '#FFD700';
ctx.fillRect(11, 22, 10, 2);
drawBlock(ctx, 10, 22, '#FFD700');
drawBlock(ctx, 12, 22, '#FFD700');
drawBlock(ctx, 14, 22, '#FFD700');
drawBlock(ctx, 16, 22, '#FFD700');
drawBlock(ctx, 18, 22, '#FFD700');
// Blade
ctx.fillStyle = '#C0C0C0'; // Silver
ctx.fillRect(14, 4, 4, 18);
// Blood Groove / Shine
ctx.fillStyle = '#F0F8FF'; // AliceBlue
ctx.fillRect(15, 4, 2, 18);
for (let i = 0; i < 8; i++) drawBlock(ctx, 14, 6 + i * 2, '#C0C0C0');
c.refresh();
}
// 5. WATERING CAN (Zalivalka)
if (!scene.textures.exists('item_watering_can')) {
const c = scene.textures.createCanvas('item_watering_can', 32, 32);
const ctx = c.getContext();
ctx.clearRect(0, 0, 32, 32);
// Body
ctx.fillStyle = '#A9A9A9'; // DarkGray
ctx.fillRect(8, 12, 16, 14);
// Handle
ctx.strokeStyle = '#696969';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(8, 14);
ctx.quadraticCurveTo(4, 10, 8, 6);
ctx.lineTo(20, 6);
ctx.stroke();
// 5. WATERING CAN (3D)
{
const { c, ctx } = refresh('item_watering_can');
// Body 3x3 blocks
for (let x = 0; x < 4; x++)
for (let y = 0; y < 3; y++)
drawBlock(ctx, 10 + x * 2, 14 + y * 2, '#A9A9A9');
// Spout
ctx.fillStyle = '#A9A9A9';
ctx.beginPath();
ctx.moveTo(24, 16);
ctx.lineTo(30, 10);
ctx.lineTo(28, 20);
ctx.fill();
drawBlock(ctx, 18, 12, '#A9A9A9');
drawBlock(ctx, 20, 10, '#A9A9A9');
// Handle
drawBlock(ctx, 8, 12, '#696969');
drawBlock(ctx, 8, 10, '#696969');
drawBlock(ctx, 10, 8, '#696969');
c.refresh();
}
}
@@ -537,14 +521,51 @@ class TextureGenerator {
const it = typeof item === 'string' ? item : item.name;
const color = typeof item === 'string' ? 'gold' : item.color;
const k = (it.startsWith('item_')) ? it : 'item_' + it;
if (!scene.textures.exists(k)) {
const c = scene.textures.createCanvas(k, 32, 32);
const x = c.getContext();
x.clearRect(0, 0, 32, 32);
if (scene.textures.exists(k)) scene.textures.remove(k); // FORCE REFRESH
const c = scene.textures.createCanvas(k, 32, 32);
const x = c.getContext();
x.clearRect(0, 0, 32, 32);
// SPECIAL ICONS
if (it === 'corn') {
// Corn Cob
x.fillStyle = '#228B22'; // Husk
x.beginPath(); x.ellipse(16, 16, 6, 12, 0, 0, Math.PI * 2); x.fill();
x.fillStyle = '#FFD700'; // Kernels
x.beginPath(); x.ellipse(16, 16, 3, 8, 0, 0, Math.PI * 2); x.fill();
}
else if (it === 'wheat') {
// Wheat Sheaf
x.strokeStyle = '#FFD700';
x.lineWidth = 2;
x.beginPath();
x.moveTo(12, 28); x.lineTo(20, 4); // Stalk 1
x.moveTo(16, 28); x.lineTo(16, 4); // Stalk 2
x.moveTo(20, 28); x.lineTo(12, 4); // Stalk 3
x.stroke();
// Tie
x.fillStyle = '#DAA520';
x.fillRect(13, 22, 6, 3);
}
else if (it.includes('seeds')) {
// Seed Bag
x.fillStyle = '#DEB887'; // Burlywood bag
x.beginPath();
x.moveTo(10, 8); x.lineTo(22, 8); // Top
x.lineTo(26, 26); x.lineTo(6, 26); // Bottom
x.fill();
// Label/Dots
x.fillStyle = color;
x.beginPath(); x.arc(16, 18, 4, 0, Math.PI * 2); x.fill();
}
else {
// Default Circle
x.fillStyle = color;
x.beginPath(); x.arc(16, 16, 10, 0, Math.PI * 2); x.fill();
c.refresh();
}
c.refresh();
});
}