🔥 FAZE SPRINT 1-3 COMPLETION: DayNight, Inventory, Core Farming System, Mrtvi Zombiji (ShamblerAI & Alfa Moć Taming), Sredili assets & daily UI
This commit is contained in:
660
nova farma TRAE/src/systems/FarmingSystem.js
Normal file
660
nova farma TRAE/src/systems/FarmingSystem.js
Normal file
@@ -0,0 +1,660 @@
|
||||
/**
|
||||
* ============================================================
|
||||
* FarmingSystem.js — Nova Farma
|
||||
* ============================================================
|
||||
* Farming logika:
|
||||
* - [E] blizu tal → Ore (Hoe) → tilled_soil tile
|
||||
* - [E] blizu tilled tile (z semenom v roki) → Posadi
|
||||
* - [E] blizu rastline (z zalivalko v roki) → Zalij
|
||||
* - Rast po N dnevih (tick ob sleep/new day)
|
||||
* - [E] blizu zrele rastline → Harvest → item v inventar
|
||||
* - Brez zalivanja 1 dan → rastlina uvene → izguba
|
||||
* ============================================================
|
||||
*
|
||||
* CROP DEFINITIONS:
|
||||
* wheat: 4 stopnje, 3 dni, 30g semena, 3×30g harvest
|
||||
* carrot: 5 stopenj, 4 dni, 15g semena, 2×40g harvest
|
||||
* cannabis: 6 stopenj, 7 dni, 50g semena, 4×200g harvest (Faza 1)
|
||||
*/
|
||||
|
||||
export default class FarmingSystem {
|
||||
|
||||
/**
|
||||
* @param {Phaser.Scene} scene — GrassSceneClean instanca
|
||||
* @param {object} options — { islandX, islandY, tileSize }
|
||||
*/
|
||||
constructor(scene, options = {}) {
|
||||
this.scene = scene;
|
||||
this.islandX = options.islandX || 2000;
|
||||
this.islandY = options.islandY || 2000;
|
||||
this.tileSize = options.tileSize || 128;
|
||||
|
||||
// Crop definicije
|
||||
this.CROPS = {
|
||||
wheat: {
|
||||
key: 'wheat',
|
||||
stages: 4, // 0=sprout,1=small,2=medium,3=ripe
|
||||
daysToGrow: 3, // Dan od saditve do žetve
|
||||
seedCost: 10,
|
||||
harvestItem: 'wheat',
|
||||
harvestCount: [1, 3], // min,max
|
||||
harvestValue: 30,
|
||||
stageKeys: [
|
||||
'crop_wheat_stage0',
|
||||
'crop_wheat_stage1',
|
||||
'crop_wheat_stage2',
|
||||
'crop_wheat_stage3',
|
||||
],
|
||||
},
|
||||
carrot: {
|
||||
key: 'carrot',
|
||||
stages: 5,
|
||||
daysToGrow: 4,
|
||||
seedCost: 15,
|
||||
harvestItem: 'carrot',
|
||||
harvestCount: [1, 2],
|
||||
harvestValue: 40,
|
||||
stageKeys: [
|
||||
'crop_carrot_stage0',
|
||||
'crop_carrot_stage1',
|
||||
'crop_carrot_stage2',
|
||||
'crop_carrot_stage3',
|
||||
'crop_carrot_stage4',
|
||||
],
|
||||
},
|
||||
cannabis: {
|
||||
key: 'cannabis',
|
||||
stages: 6,
|
||||
daysToGrow: 7,
|
||||
seedCost: 50,
|
||||
harvestItem: 'cannabis_bud',
|
||||
harvestCount: [3, 5],
|
||||
harvestValue: 200,
|
||||
stageKeys: [
|
||||
'crop_cannabis_stage0',
|
||||
'crop_cannabis_stage1',
|
||||
'crop_cannabis_stage2',
|
||||
'crop_cannabis_stage3',
|
||||
'crop_cannabis_stage4',
|
||||
'crop_cannabis_stage5',
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
// Stanje
|
||||
this.tilledPlots = []; // { x, y, tileSprite, crop, dayPlanted, dayWatered, stage, sprite, wilted }
|
||||
this.currentDay = 1;
|
||||
this.interactRange = 60; // px — razdalja za interakcijo
|
||||
this.TILE_DISPLAY = 40; // Vizualna velikost tilled tile — majhna kocka!
|
||||
|
||||
// Aktiven tool v roki (set from InventorySystem)
|
||||
this.activeTool = 'hoe'; // 'hoe' | 'watering_can' | null
|
||||
this.activeSeed = 'wheat'; // 'wheat' | 'carrot' | 'cannabis'
|
||||
|
||||
// Physics group za tilled tile colliderje
|
||||
this.plotGroup = scene.physics.add.staticGroup();
|
||||
|
||||
// Graphics za highlight (Kai blizu)
|
||||
this.highlightGfx = scene.add.graphics().setDepth(9000);
|
||||
|
||||
// Input — E tipka
|
||||
this.keyE = scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.E);
|
||||
|
||||
// Debounce
|
||||
this._lastInteract = 0;
|
||||
|
||||
console.log('🌱 FarmingSystem initialized');
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// PRELOAD — Assets (kliči iz scene.preload PRED new FarmingSystem)
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
static preload(scene) {
|
||||
// Tilled soil
|
||||
scene.load.image('tilled_soil', 'DEMO_FAZA1/Crops/tilled_soil.png');
|
||||
|
||||
// Wheat (4 stopnje)
|
||||
for (let i = 0; i < 4; i++) {
|
||||
scene.load.image(`crop_wheat_stage${i}`, `DEMO_FAZA1/Crops/crop_wheat_stage${i}.png`);
|
||||
}
|
||||
// Carrot (5 stopenj)
|
||||
for (let i = 0; i < 5; i++) {
|
||||
scene.load.image(`crop_carrot_stage${i}`, `DEMO_FAZA1/Crops/crop_carrot_stage${i}.png`);
|
||||
}
|
||||
// Cannabis (6 stopenj)
|
||||
for (let i = 0; i < 6; i++) {
|
||||
scene.load.image(`crop_cannabis_stage${i}`, `DEMO_FAZA1/Crops/crop_cannabis_stage${i}.png`);
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// UPDATE — Kliči iz scene.update()
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
update(kai, time) {
|
||||
this.highlightGfx.clear();
|
||||
|
||||
const nearPlot = this._getPlotNear(kai);
|
||||
const nearEmpty = this._getEmptyGroundNear(kai);
|
||||
|
||||
// ── Highlight najbližji plot ──
|
||||
const W = 48, H = 24; // Velikost tilled plot kocke
|
||||
if (nearPlot) {
|
||||
this.highlightGfx.lineStyle(2, 0x44ffcc, 0.9);
|
||||
this.highlightGfx.strokeRect(
|
||||
nearPlot.x - W / 2,
|
||||
nearPlot.y - H / 2,
|
||||
W, H
|
||||
);
|
||||
// Tooltip nad plotom
|
||||
this._drawTooltip(nearPlot);
|
||||
} else if (nearEmpty && this.activeTool === 'hoe') {
|
||||
// Pregled oranja
|
||||
this.highlightGfx.lineStyle(2, 0xaabb88, 0.5);
|
||||
this.highlightGfx.strokeRect(
|
||||
nearEmpty.x - W / 2,
|
||||
nearEmpty.y - H / 2,
|
||||
W, H
|
||||
);
|
||||
}
|
||||
|
||||
// ── E tipka — interakcija ──
|
||||
if (Phaser.Input.Keyboard.JustDown(this.keyE)) {
|
||||
if (nearPlot) {
|
||||
this._interactWithPlot(nearPlot, kai);
|
||||
} else if (nearEmpty && this.activeTool === 'hoe') {
|
||||
this._tillGround(nearEmpty.x, nearEmpty.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// ORE (TILL) — Ustvari nov tilled plot
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
_tillGround(x, y) {
|
||||
// Snap na grid — center tile-a
|
||||
const ts = this.tileSize;
|
||||
const snappedX = Math.floor(x / ts) * ts + ts / 2;
|
||||
const snappedY = Math.floor(y / ts) * ts + ts / 2;
|
||||
|
||||
// Ali plot že obstaja?
|
||||
if (this.tilledPlots.some(p => Math.abs(p.x - snappedX) < 4 && Math.abs(p.y - snappedY) < 4)) return;
|
||||
|
||||
// === Nariši tilled soil z Graphics — točna velikost, brez skaliranja slik ===
|
||||
const W = 48; // širina kocke (world px)
|
||||
const H = 24; // višina kocke (world px)
|
||||
const gfx = this.scene.add.graphics();
|
||||
gfx.setDepth(snappedY - 50);
|
||||
|
||||
// Ozadje — temna rjava zemlja
|
||||
gfx.fillStyle(0x3a2010, 1);
|
||||
gfx.fillRect(snappedX - W / 2, snappedY - H / 2, W, H);
|
||||
|
||||
// Brazde (bela linija × 3, horizontalne)
|
||||
gfx.lineStyle(1, 0x6b4020, 0.7);
|
||||
const lines = 3;
|
||||
for (let i = 1; i <= lines; i++) {
|
||||
const ly = snappedY - H / 2 + (H / (lines + 1)) * i;
|
||||
gfx.beginPath();
|
||||
gfx.moveTo(snappedX - W / 2 + 3, ly);
|
||||
gfx.lineTo(snappedX + W / 2 - 3, ly);
|
||||
gfx.strokePath();
|
||||
}
|
||||
|
||||
// Tanka okvirna linija
|
||||
gfx.lineStyle(1, 0x8b5a2b, 0.5);
|
||||
gfx.strokeRect(snappedX - W / 2, snappedY - H / 2, W, H);
|
||||
|
||||
// Pop-in animacija — skali iz 0
|
||||
gfx.setScale(0.1);
|
||||
this.scene.tweens.add({
|
||||
targets: gfx,
|
||||
scaleX: 1.0,
|
||||
scaleY: 1.0,
|
||||
duration: 250,
|
||||
ease: 'Back.out',
|
||||
});
|
||||
|
||||
// Shrani referenčni objekt (tile = gfx)
|
||||
const tile = gfx;
|
||||
|
||||
// Physics static body za collider
|
||||
const body = this.plotGroup.create(snappedX, snappedY);
|
||||
body.setDisplaySize(this.tileSize - 4, this.tileSize - 4);
|
||||
body.setAlpha(0);
|
||||
body.refreshBody();
|
||||
|
||||
// Shrani plot
|
||||
const plot = {
|
||||
x: snappedX,
|
||||
y: snappedY,
|
||||
tileSprite: tile,
|
||||
bodyRef: body,
|
||||
crop: null,
|
||||
dayPlanted: null,
|
||||
dayWatered: null,
|
||||
stage: 0,
|
||||
sprite: null,
|
||||
wilted: false,
|
||||
};
|
||||
this.tilledPlots.push(plot);
|
||||
|
||||
// Animacija: "Pop" ob oranju
|
||||
this.scene.tweens.add({
|
||||
targets: tile,
|
||||
scaleX: { from: 1.1, to: 1.0 },
|
||||
scaleY: { from: 0.8, to: 1.0 },
|
||||
duration: 200,
|
||||
ease: 'Bounce.out',
|
||||
});
|
||||
|
||||
this._showFloatingText(snappedX, snappedY, '🪱 Poorano!', '#aabb88');
|
||||
console.log(`🌱 Poorano: ${snappedX}, ${snappedY}`);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// INTERAKCIJA Z PLOTOM (posadi / zalij / poženi)
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
_interactWithPlot(plot, kai) {
|
||||
if (plot.wilted) {
|
||||
// Uvela rastlina — odstrani in reciklira plot
|
||||
this._removeCrop(plot);
|
||||
this._showFloatingText(plot.x, plot.y, '🍂 Odstranjeno', '#cc6666');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!plot.crop) {
|
||||
// 1. Prazno poorano → Posadi
|
||||
if (this.activeTool === 'hoe' || this.activeSeed) {
|
||||
this._plantCrop(plot, this.activeSeed);
|
||||
}
|
||||
} else if (plot.crop && plot.stage < this._getCropDef(plot.crop).stages - 1) {
|
||||
// 2. Rastlina raste → Zalij (samo z zalivalko)
|
||||
if (this.activeTool === 'watering_can') {
|
||||
this._waterCrop(plot);
|
||||
} else {
|
||||
this._showFloatingText(plot.x, plot.y - 30, '💧 Vzemi zalivalko!', '#aaaaff');
|
||||
}
|
||||
} else if (plot.stage >= this._getCropDef(plot.crop).stages - 1 && !plot.wilted) {
|
||||
// 3. Zrela → Poženi
|
||||
this._harvestCrop(plot);
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// POSADI
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
_plantCrop(plot, cropKey) {
|
||||
const def = this._getCropDef(cropKey);
|
||||
if (!def) {
|
||||
console.warn('Unknown crop:', cropKey);
|
||||
return;
|
||||
}
|
||||
|
||||
plot.crop = cropKey;
|
||||
plot.dayPlanted = this.currentDay;
|
||||
plot.dayWatered = this.currentDay; // Zaliješ takoj ob sajenju
|
||||
plot.stage = 0;
|
||||
plot.wilted = false;
|
||||
|
||||
// Ustvari sprite za rastlino (stage 0)
|
||||
// Stage 0 = 20px visoka (klica), max stage = 70px (zrela rastlina)
|
||||
const stageKey = def.stageKeys[0];
|
||||
const cropH = 20;
|
||||
const texture = this.scene.textures.get(stageKey);
|
||||
const srcH = texture?.getSourceImage()?.height || 100;
|
||||
const scale = cropH / srcH;
|
||||
|
||||
// Posadi na center tilled tile-a z offset za vizualni izgled
|
||||
plot.sprite = this.scene.add.image(plot.x, plot.y, stageKey)
|
||||
.setScale(scale)
|
||||
.setOrigin(0.5, 1.0)
|
||||
.setDepth(plot.y + 1)
|
||||
.setAlpha(0);
|
||||
|
||||
// Pop-in animacija
|
||||
this.scene.tweens.add({
|
||||
targets: plot.sprite,
|
||||
alpha: 1,
|
||||
scaleX: { from: scale * 1.4, to: scale },
|
||||
scaleY: { from: scale * 0.5, to: scale },
|
||||
duration: 350,
|
||||
ease: 'Back.out',
|
||||
});
|
||||
|
||||
this._showFloatingText(plot.x, plot.y - 30, `🌱 ${cropKey}!`, '#88ff88', 18);
|
||||
console.log(`🌱 Posajeno: ${cropKey} @ day ${this.currentDay}`);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// ZALIJ
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
_waterCrop(plot) {
|
||||
if (!plot.crop) return;
|
||||
if (plot.dayWatered === this.currentDay) {
|
||||
this._showFloatingText(plot.x, plot.y - 30, '✅ Že zalivano!', '#44ffcc');
|
||||
return;
|
||||
}
|
||||
|
||||
// === PREVERI VODO v vedru ===
|
||||
if (this.waterSystem) {
|
||||
if (!this.waterSystem.hasWater(1)) {
|
||||
this._showFloatingText(plot.x, plot.y - 30,
|
||||
'❌ Vedro prazno! [F] pri RC', '#ff6666', 16);
|
||||
return;
|
||||
}
|
||||
this.waterSystem.useWater(1); // Porabi 1L
|
||||
}
|
||||
|
||||
plot.dayWatered = this.currentDay;
|
||||
plot.wilted = false;
|
||||
|
||||
// Ripple efekt — modri krogci
|
||||
this._waterRipple(plot.x, plot.y);
|
||||
this._showFloatingText(plot.x, plot.y - 20, '💧 Zalivano!', '#44aaff');
|
||||
|
||||
// Tla (Graphics) - prebarva temnejše ko so mokra
|
||||
if (plot.tileSprite) {
|
||||
plot.tileSprite.clear();
|
||||
const W = 48, H = 24;
|
||||
const snappedX = plot.x, snappedY = plot.y;
|
||||
// Mokra zemlja = temnejša
|
||||
plot.tileSprite.fillStyle(0x25140a, 1);
|
||||
plot.tileSprite.fillRect(snappedX - W / 2, snappedY - H / 2, W, H);
|
||||
plot.tileSprite.lineStyle(1, 0x4a2c10, 0.7);
|
||||
for (let i = 1; i <= 3; i++) {
|
||||
const ly = snappedY - H / 2 + (H / 4) * i;
|
||||
plot.tileSprite.beginPath();
|
||||
plot.tileSprite.moveTo(snappedX - W / 2 + 3, ly);
|
||||
plot.tileSprite.lineTo(snappedX + W / 2 - 3, ly);
|
||||
plot.tileSprite.strokePath();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// ŽETEV
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
_harvestCrop(plot) {
|
||||
const def = this._getCropDef(plot.crop);
|
||||
const count = Phaser.Math.Between(def.harvestCount[0], def.harvestCount[1]);
|
||||
const value = count * def.harvestValue;
|
||||
|
||||
// Notify scene (UIScene bo prikazal)
|
||||
this.scene.events.emit('harvest', {
|
||||
item: def.harvestItem,
|
||||
count,
|
||||
value,
|
||||
x: plot.x,
|
||||
y: plot.y,
|
||||
});
|
||||
|
||||
// Floating nagrade tekst
|
||||
this._showFloatingText(plot.x, plot.y - 20,
|
||||
`🌾 ×${count} (+${value}g)`, '#ffd700', 28);
|
||||
|
||||
// Bounce animacija preden izgine
|
||||
if (plot.sprite) {
|
||||
this.scene.tweens.add({
|
||||
targets: plot.sprite,
|
||||
scaleX: plot.sprite.scaleX * 1.3,
|
||||
scaleY: plot.sprite.scaleY * 1.3,
|
||||
alpha: 0,
|
||||
duration: 400,
|
||||
ease: 'Back.in',
|
||||
onComplete: () => { if (plot.sprite) plot.sprite.destroy(); }
|
||||
});
|
||||
}
|
||||
|
||||
// Reset plota (poorano ostane, crop zbrisano)
|
||||
plot.crop = null;
|
||||
plot.sprite = null;
|
||||
plot.dayPlanted = null;
|
||||
plot.dayWatered = null;
|
||||
plot.stage = 0;
|
||||
plot.wilted = false;
|
||||
|
||||
// Tla postanejo svetlejša (prazna)
|
||||
this.scene.tweens.add({
|
||||
targets: plot.tileSprite,
|
||||
alpha: 0.9,
|
||||
duration: 500,
|
||||
});
|
||||
|
||||
console.log(`🌾 Harvest: ${def.harvestItem} ×${count} = ${value}g`);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// DNEVNI TICK — Kliči enkrat na dan (ob sleep/new day)
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
onNewDay(day) {
|
||||
this.currentDay = day;
|
||||
|
||||
for (const plot of this.tilledPlots) {
|
||||
if (!plot.crop || plot.wilted) continue;
|
||||
|
||||
const def = this._getCropDef(plot.crop);
|
||||
|
||||
// ── Preveri zalivanje ──
|
||||
if (plot.dayWatered < day - 1) {
|
||||
// Ni bilo zalivano včeraj → Uvene!
|
||||
this._wiltCrop(plot);
|
||||
continue;
|
||||
}
|
||||
|
||||
// ── Rast ──
|
||||
const daysGrown = day - plot.dayPlanted;
|
||||
// Enakomerno razporedimo stopnje čez daysToGrow
|
||||
const newStage = Math.min(
|
||||
Math.floor((daysGrown / def.daysToGrow) * def.stages),
|
||||
def.stages - 1
|
||||
);
|
||||
|
||||
if (newStage > plot.stage) {
|
||||
plot.stage = newStage;
|
||||
this._updateCropSprite(plot);
|
||||
|
||||
if (newStage === def.stages - 1) {
|
||||
// ZRELA!
|
||||
this._showFloatingText(plot.x, plot.y - 40, '🌟 Zrelo!', '#ffd700', 24);
|
||||
this._glowPulse(plot.sprite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`🌞 Dan ${day} tick — ${this.tilledPlots.filter(p => p.crop).length} crop-ov aktiv`);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// UVENJANJE
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
_wiltCrop(plot) {
|
||||
plot.wilted = true;
|
||||
|
||||
// Sprite potemni in se trese
|
||||
if (plot.sprite) {
|
||||
this.scene.tweens.add({
|
||||
targets: plot.sprite,
|
||||
tint: 0x554433,
|
||||
alpha: 0.5,
|
||||
duration: 800,
|
||||
ease: 'Sine.in',
|
||||
onComplete: () => {
|
||||
if (plot.sprite) plot.sprite.setTint(0x554433).setAlpha(0.45);
|
||||
}
|
||||
});
|
||||
}
|
||||
this._showFloatingText(plot.x, plot.y - 30, '🍂 Uvelo!', '#cc6633');
|
||||
console.warn(`🍂 Rastlina uvela @ ${plot.x},${plot.y}`);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// POMOŽNE METODE
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
_getCropDef(key) {
|
||||
return this.CROPS[key] || null;
|
||||
}
|
||||
|
||||
_updateCropSprite(plot) {
|
||||
const def = this._getCropDef(plot.crop);
|
||||
const stageKey = def.stageKeys[plot.stage];
|
||||
|
||||
// Ciljana višina: 20px (stage0) → 70px (zrela)
|
||||
const minH = 20, maxH = 70;
|
||||
const cropH = minH + (plot.stage / (def.stages - 1)) * (maxH - minH);
|
||||
|
||||
const texture = this.scene.textures.get(stageKey);
|
||||
const srcH = texture?.getSourceImage()?.height || 150;
|
||||
const scale = cropH / srcH;
|
||||
|
||||
if (plot.sprite) {
|
||||
// Animiran prehod na novo stopnjo
|
||||
this.scene.tweens.add({
|
||||
targets: plot.sprite,
|
||||
scaleX: { from: plot.sprite.scaleX, to: scale },
|
||||
scaleY: { from: plot.sprite.scaleY, to: scale },
|
||||
duration: 600,
|
||||
ease: 'Back.out',
|
||||
onStart: () => { if (plot.sprite) plot.sprite.setTexture(stageKey); }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_removeCrop(plot) {
|
||||
if (plot.sprite) { plot.sprite.destroy(); plot.sprite = null; }
|
||||
plot.crop = null;
|
||||
plot.dayPlanted = null;
|
||||
plot.dayWatered = null;
|
||||
plot.stage = 0;
|
||||
plot.wilted = false;
|
||||
if (plot.tileSprite) plot.tileSprite.setAlpha(0.9).clearTint();
|
||||
}
|
||||
|
||||
_getPlotNear(kai) {
|
||||
let closest = null;
|
||||
let minDist = this.interactRange;
|
||||
for (const plot of this.tilledPlots) {
|
||||
const d = Phaser.Math.Distance.Between(kai.x, kai.y, plot.x, plot.y);
|
||||
if (d < minDist) { minDist = d; closest = plot; }
|
||||
}
|
||||
return closest;
|
||||
}
|
||||
|
||||
_getEmptyGroundNear(kai) {
|
||||
// Snap na tile center — Kai mora biti v bližini centra tile-a
|
||||
const ts = this.tileSize;
|
||||
const snappedX = Math.floor(kai.x / ts) * ts + ts / 2;
|
||||
const snappedY = Math.floor(kai.y / ts) * ts + ts / 2;
|
||||
const dist = Phaser.Math.Distance.Between(kai.x, kai.y, snappedX, snappedY);
|
||||
if (dist > this.interactRange) return null;
|
||||
if (this.tilledPlots.some(p => Math.abs(p.x - snappedX) < 8 && Math.abs(p.y - snappedY) < 8)) return null;
|
||||
return { x: snappedX, y: snappedY };
|
||||
}
|
||||
|
||||
_drawTooltip(plot) {
|
||||
const def = plot.crop ? this._getCropDef(plot.crop) : null;
|
||||
let label = '';
|
||||
if (!plot.crop) label = '🌱 [E] Posadi';
|
||||
else if (plot.wilted) label = '🍂 [E] Odstrani';
|
||||
else if (plot.stage >= (def?.stages - 1)) label = '🌾 [E] Poženi!';
|
||||
else if (this.activeTool === 'watering_can') label = '💧 [E] Zalij';
|
||||
else label = `🌿 ${plot.crop} (${plot.stage + 1}/${def?.stages})`;
|
||||
|
||||
// Tooltip — svetla, jasna, pri vrhu tilled tile-a
|
||||
if (!this._tooltipText) {
|
||||
this._tooltipText = this.scene.add.text(0, 0, '', {
|
||||
fontFamily: 'Arial Black',
|
||||
fontSize: '13px',
|
||||
color: '#ffffff',
|
||||
stroke: '#000000',
|
||||
strokeThickness: 4,
|
||||
backgroundColor: '#00000099',
|
||||
padding: { x: 8, y: 4 },
|
||||
}).setDepth(9999).setScrollFactor(1);
|
||||
}
|
||||
const W = 48, H = 24;
|
||||
this._tooltipText
|
||||
.setText(label)
|
||||
.setPosition(plot.x - this._tooltipText.width / 2, plot.y - H / 2 - 20);
|
||||
}
|
||||
|
||||
_showFloatingText(x, y, msg, color = '#ffffff', fontSize = 20) {
|
||||
const txt = this.scene.add.text(x, y, msg, {
|
||||
fontFamily: 'Arial Black',
|
||||
fontSize: `${fontSize}px`,
|
||||
color,
|
||||
stroke: '#000000',
|
||||
strokeThickness: 4,
|
||||
}).setOrigin(0.5).setDepth(9998);
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: txt,
|
||||
y: y - 60,
|
||||
alpha: { from: 1, to: 0 },
|
||||
duration: 1400,
|
||||
ease: 'Cubic.out',
|
||||
onComplete: () => txt.destroy(),
|
||||
});
|
||||
}
|
||||
|
||||
_waterRipple(x, y) {
|
||||
const gfx = this.scene.add.graphics().setDepth(9997);
|
||||
let r = 4, alpha = 0.7;
|
||||
const expand = this.scene.time.addEvent({
|
||||
delay: 40,
|
||||
repeat: 8,
|
||||
callback: () => {
|
||||
gfx.clear();
|
||||
gfx.lineStyle(2, 0x4499ff, alpha);
|
||||
gfx.strokeCircle(x, y, r);
|
||||
r += 6; alpha -= 0.08;
|
||||
if (r > 55) { gfx.destroy(); expand.remove(); }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_glowPulse(sprite) {
|
||||
if (!sprite) return;
|
||||
this.scene.tweens.add({
|
||||
targets: sprite,
|
||||
alpha: { from: 1, to: 0.5 },
|
||||
duration: 400,
|
||||
yoyo: true,
|
||||
repeat: 3,
|
||||
ease: 'Sine.inOut',
|
||||
});
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// PUBLIC API — Za GrassScene
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/** Nastavi aktiven tool (kliče InventorySystem) */
|
||||
setTool(tool) { this.activeTool = tool; }
|
||||
|
||||
/** Nastavi aktivno seme (kliče InventorySystem) */
|
||||
setSeed(seed) { this.activeSeed = seed; }
|
||||
|
||||
/** Vrni vse activate plots (za save) */
|
||||
getState() {
|
||||
return this.tilledPlots.map(p => ({
|
||||
x: p.x, y: p.y,
|
||||
crop: p.crop,
|
||||
dayPlanted: p.dayPlanted,
|
||||
dayWatered: p.dayWatered,
|
||||
stage: p.stage,
|
||||
wilted: p.wilted,
|
||||
}));
|
||||
}
|
||||
|
||||
/** Destroy */
|
||||
destroy() {
|
||||
this.highlightGfx?.destroy();
|
||||
this._tooltipText?.destroy();
|
||||
this.tilledPlots.forEach(p => {
|
||||
p.tileSprite?.destroy();
|
||||
p.sprite?.destroy();
|
||||
});
|
||||
this.tilledPlots = [];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user