neki bo
This commit is contained in:
BIN
assets/.DS_Store
vendored
BIN
assets/.DS_Store
vendored
Binary file not shown.
BIN
assets/DEMO_FAZA1/.DS_Store
vendored
BIN
assets/DEMO_FAZA1/.DS_Store
vendored
Binary file not shown.
BIN
nova farma TRAE/.DS_Store
vendored
BIN
nova farma TRAE/.DS_Store
vendored
Binary file not shown.
BIN
nova farma TRAE/assets/.DS_Store
vendored
BIN
nova farma TRAE/assets/.DS_Store
vendored
Binary file not shown.
BIN
nova farma TRAE/assets/DEMO_FAZA1/.DS_Store
vendored
BIN
nova farma TRAE/assets/DEMO_FAZA1/.DS_Store
vendored
Binary file not shown.
@@ -4,6 +4,10 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Nova Farma - Clean Start</title>
|
||||
<!-- Google Fonts za UTF-8 in šumnike -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;700&family=Noto+Sans+SC:wght@400;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
|
||||
97
nova farma TRAE/public/assets/localization.json
Normal file
97
nova farma TRAE/public/assets/localization.json
Normal file
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"sl": {
|
||||
"menu_play": "IGRAJ",
|
||||
"menu_options": "NASTAVITVE",
|
||||
"menu_exit": "IZHOD",
|
||||
"lang_btn": "JEZIK: SL",
|
||||
"acc_menu": "MENI ZA DOSTOPNOST",
|
||||
"acc_deaf": "🔊 Vizualna Opozorila (Deaf Mode)",
|
||||
"acc_autism": "⚡ Senzorni Način (Reduce Motion)",
|
||||
"acc_adhd": "🎯 Zen/ADHD Način (Fokus Cilja)",
|
||||
"acc_font": "🔎 Povečana Pisava",
|
||||
"acc_contrast": "🔲 Visok Kontrast",
|
||||
"acc_colorblind": "👁️ Filter Barvne Slepote",
|
||||
"acc_onehand": "🕹️ Enoročni Način",
|
||||
"acc_close": "[ X ZAPRI ]",
|
||||
"day": "DAN",
|
||||
"map": "MAPA",
|
||||
"crafting": "CRAFTING",
|
||||
"adhd_goal": "⬇️ TVOJ TRENUTNI CILJ: ZALIJ PŠENICO! ⬇️"
|
||||
},
|
||||
"en": {
|
||||
"menu_play": "PLAY",
|
||||
"menu_options": "OPTIONS",
|
||||
"menu_exit": "EXIT",
|
||||
"lang_btn": "LANGUAGE: EN",
|
||||
"acc_menu": "ACCESSIBILITY MENU",
|
||||
"acc_deaf": "🔊 Visual Alerts (Deaf Mode)",
|
||||
"acc_autism": "⚡ Sensory Mode (Reduce Motion)",
|
||||
"acc_adhd": "🎯 Zen/ADHD Mode (Goal Focus)",
|
||||
"acc_font": "🔎 Large Font",
|
||||
"acc_contrast": "🔲 High Contrast",
|
||||
"acc_colorblind": "👁️ Colorblind Filter",
|
||||
"acc_onehand": "🕹️ One-handed Mode",
|
||||
"acc_close": "[ X CLOSE ]",
|
||||
"day": "DAY",
|
||||
"map": "MAP",
|
||||
"crafting": "CRAFTING",
|
||||
"adhd_goal": "⬇️ YOUR CURRENT GOAL: WATER THE WHEAT! ⬇️"
|
||||
},
|
||||
"de": {
|
||||
"menu_play": "SPIELEN",
|
||||
"menu_options": "OPTIONEN",
|
||||
"menu_exit": "BEENDEN",
|
||||
"lang_btn": "SPRACHE: DE",
|
||||
"acc_menu": "BARRIEREFREIHEITS-MENÜ",
|
||||
"acc_deaf": "🔊 Visuelle Alarme (Gehörlosenmodus)",
|
||||
"acc_autism": "⚡ Sensibler Modus (Weniger Bewegung)",
|
||||
"acc_adhd": "🎯 Zen/ADHD-Modus (Zielfokus)",
|
||||
"acc_font": "🔎 Große Schrift",
|
||||
"acc_contrast": "🔲 Hoher Kontrast",
|
||||
"acc_colorblind": "👁️ Farbenblind-Filter",
|
||||
"acc_onehand": "🕹️ Einhandmodus",
|
||||
"acc_close": "[ X SCHLIESSEN ]",
|
||||
"day": "TAG",
|
||||
"map": "KARTE",
|
||||
"crafting": "HERSTELLUNG",
|
||||
"adhd_goal": "⬇️ DEIN AKTUELLES ZIEL: WEIZEN GIESSEN! ⬇️"
|
||||
},
|
||||
"it": {
|
||||
"menu_play": "GIOCA",
|
||||
"menu_options": "OPZIONI",
|
||||
"menu_exit": "ESCI",
|
||||
"lang_btn": "LINGUA: IT",
|
||||
"acc_menu": "MENU ACCESSIBILITÀ",
|
||||
"acc_deaf": "🔊 Avvisi Visivi (Modalità Sordi)",
|
||||
"acc_autism": "⚡ Modalità Sensoriale (Riduci Movimento)",
|
||||
"acc_adhd": "🎯 Modalità Zen/ADHD (Focus Obiettivo)",
|
||||
"acc_font": "🔎 Carattere Grande",
|
||||
"acc_contrast": "🔲 Alto Contrasto",
|
||||
"acc_colorblind": "👁️ Filtro Daltonismo",
|
||||
"acc_onehand": "🕹️ Modalità Una Mano",
|
||||
"acc_close": "[ X CHIUDI ]",
|
||||
"day": "GIORNO",
|
||||
"map": "MAPPA",
|
||||
"crafting": "CREAZIONE",
|
||||
"adhd_goal": "⬇️ IL TUO OBIETTIVO ATTUALE: ANNAFFIA IL GRANO! ⬇️"
|
||||
},
|
||||
"cn": {
|
||||
"menu_play": "开始游戏",
|
||||
"menu_options": "设置",
|
||||
"menu_exit": "退出",
|
||||
"lang_btn": "语言: CN",
|
||||
"acc_menu": "无障碍菜单",
|
||||
"acc_deaf": "🔊 视觉警报 (聋人模式)",
|
||||
"acc_autism": "⚡ 感觉模式 (减少动画)",
|
||||
"acc_adhd": "🎯 禅/ADHD模式 (目标专注)",
|
||||
"acc_font": "🔎 大字体",
|
||||
"acc_contrast": "🔲 高对比度",
|
||||
"acc_colorblind": "👁️ 色盲滤镜",
|
||||
"acc_onehand": "🕹️ 单手模式",
|
||||
"acc_close": "[ X 关闭 ]",
|
||||
"day": "天",
|
||||
"map": "地图",
|
||||
"crafting": "制作",
|
||||
"adhd_goal": "⬇️ 你当前的目标:给小麦浇水! ⬇️"
|
||||
}
|
||||
}
|
||||
@@ -293,12 +293,12 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
this.cameras.main.setBackgroundColor('#001d3d'); // Deep Blue Ocean
|
||||
|
||||
// --- ZOOM CONTROL ---
|
||||
this.cameras.main.setZoom(0.8);
|
||||
this.cameras.main.setZoom(1.0); // Privzet zoom za Demo
|
||||
|
||||
this.input.on('wheel', (pointer, gameObjects, deltaX, deltaY, deltaZ) => {
|
||||
const zoomFactor = -0.001;
|
||||
const newZoom = this.cameras.main.zoom + deltaY * zoomFactor;
|
||||
this.cameras.main.setZoom(Phaser.Math.Clamp(newZoom, 0.2, 5.0));
|
||||
this.cameras.main.setZoom(Phaser.Math.Clamp(newZoom, 0.5, 2.5)); // Omejitev 0.5 do 2.5
|
||||
});
|
||||
|
||||
// --- 1. DYNAMIC OCEAN & ISLAND SYSTEM ---
|
||||
@@ -674,7 +674,9 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
/*
|
||||
// Trnje (Thorns) - Draggable
|
||||
this.trnje = this.add.image(startX - 200, startY + 100, 'trnje');
|
||||
this.trnje.setOrigin(0.5, 1.0); // Sidrišče čisto na dno
|
||||
this.trnje.setScale(0.5); // Adjust scale if needed
|
||||
this.trnje.setDepth(this.trnje.y); // Y-sorting
|
||||
this.trnje.setInteractive({ draggable: true });
|
||||
// Trigger Amnesia Clear on interaction
|
||||
this.trnje.on('pointerdown', () => {
|
||||
@@ -683,9 +685,10 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
|
||||
// --- NEW: RAIN CATCHER ---
|
||||
this.rainCatcher = this.physics.add.image(startX + 150, startY + 50, 'rain_catcher');
|
||||
this.rainCatcher.setOrigin(0.5, 1.0); // Sidrišče čisto na dno
|
||||
this.rainCatcher.setScale(0.8);
|
||||
this.rainCatcher.setInteractive({ draggable: true });
|
||||
this.rainCatcher.setDepth(startY + 50); // Y-sort
|
||||
this.rainCatcher.setDepth(this.rainCatcher.y); // Y-sort
|
||||
this.rainCatcher.body.setImmovable(true);
|
||||
// Collider added later with Kai
|
||||
*/
|
||||
@@ -993,21 +996,35 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
|
||||
});
|
||||
*/
|
||||
// ─── SPALNA VREČA & STARTER CHEST (Kišta) ────────────────────────
|
||||
this.sleepingBag = this.physics.add.image(SPAWN_X + 150, 5600, 'sleeping_bag');
|
||||
this.sleepingBag.setOrigin(0.5, 1.0);
|
||||
this.sleepingBag.setScale(0.3);
|
||||
this.sleepingBag.setDepth(this.sleepingBag.y);
|
||||
// ─── HARDCODED DEMO BASE (8x8) ────────────────────────
|
||||
// Zgoraj Levo: Šotor (2x2)
|
||||
this.sotor = this.physics.add.image(SPAWN_X - 128, SPAWN_Y - 128, 'sotor');
|
||||
this.sotor.setOrigin(0.5, 1.0);
|
||||
this.sotor.setScale(2.5); // iz BuildingSystem.js
|
||||
this.sotor.setDepth(this.sotor.y);
|
||||
this.sotor.body.setSize(160, 40);
|
||||
this.sotor.body.setOffset(-80, -40);
|
||||
this.sotor.body.setImmovable(true);
|
||||
this.sleepingBag = this.sotor; // Uporabi šotor kot checkpoint za spanje
|
||||
|
||||
this.starterChest = this.physics.add.image(SPAWN_X - 100, 5600, 'chest_closed');
|
||||
this.starterChest.setOrigin(0.5, 1.0);
|
||||
// Sredina: Taborni ogenj (1x1)
|
||||
this.campfire = this.physics.add.image(SPAWN_X - 32, SPAWN_Y - 32, 'campfire');
|
||||
this.campfire.setOrigin(0.5, 1.0);
|
||||
this.campfire.setDepth(this.campfire.y);
|
||||
this.campfire.body.setSize(50, 20);
|
||||
this.campfire.body.setOffset(25, 30);
|
||||
this.campfire.body.setImmovable(true);
|
||||
|
||||
// Sredina: Skrinja
|
||||
this.starterChest = this.physics.add.image(SPAWN_X + 64, SPAWN_Y - 32, 'chest_closed');
|
||||
this.starterChest.setOrigin(0.5, 1.0); // Sidrišče čisto na dno
|
||||
this.starterChest.setScale(0.18);
|
||||
this.starterChest.setDepth(5600);
|
||||
this.starterChest.setDepth(this.starterChest.y); // Y-sorting
|
||||
this.starterChest.body.setSize(this.starterChest.width * 0.18, this.starterChest.height * 0.18);
|
||||
this.starterChest.body.setImmovable(true);
|
||||
this.starterChest.opened = false;
|
||||
|
||||
let chestText = this.add.text(SPAWN_X - 100, 5600 - 100, '[E] Odpri Kišto', { fontFamily: 'Arial Black', fontSize: '13px', color: '#ffdd00', stroke: '#000', strokeThickness: 4, align: 'center' }).setOrigin(0.5, 0.5);
|
||||
let chestText = this.add.text(this.starterChest.x, this.starterChest.y - 50, '[E] Odpri Kišto', { fontFamily: 'Arial Black', fontSize: '13px', color: '#ffdd00', stroke: '#000', strokeThickness: 4, align: 'center' }).setOrigin(0.5, 0.5);
|
||||
chestText.setDepth(9999);
|
||||
|
||||
this.input.keyboard.on('keydown-E', () => {
|
||||
@@ -1041,43 +1058,42 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
}
|
||||
});
|
||||
// ─────────────────────────────────────────────────────────────────
|
||||
// === RANDOM TREE GENERATION (AUTO-LOADER) ===
|
||||
// === NEPREBOJEN GOZD (IMPENETRABLE FOREST WALL) ===
|
||||
this.treesGroup = this.physics.add.staticGroup();
|
||||
|
||||
const treeKeys = ['tree_adult_0', 'tree_adult_1', 'tree_adult_2', 'tree_adult_3', 'tree_adult_4', 'tree_adult_5'];
|
||||
const TREE_COUNT = 40;
|
||||
|
||||
for (let i = 0; i < TREE_COUNT; i++) {
|
||||
// Place on random edge to keep center farming area free
|
||||
const edge = Math.floor(Math.random() * 4);
|
||||
let tx, ty;
|
||||
const PADDING = 200;
|
||||
|
||||
switch (edge) {
|
||||
case 0: // Top
|
||||
tx = this.islandX + Math.random() * this.islandWidth;
|
||||
ty = this.islandY + PADDING + Math.random() * 300;
|
||||
break;
|
||||
case 1: // Right
|
||||
tx = this.islandX + this.islandWidth - PADDING - Math.random() * 300;
|
||||
ty = this.islandY + Math.random() * this.islandHeight;
|
||||
break;
|
||||
case 2: // Bottom
|
||||
tx = this.islandX + Math.random() * this.islandWidth;
|
||||
ty = this.islandY + this.islandHeight - PADDING - Math.random() * 300;
|
||||
break;
|
||||
case 3: // Left
|
||||
tx = this.islandX + PADDING + Math.random() * 300;
|
||||
ty = this.islandY + Math.random() * this.islandHeight;
|
||||
break;
|
||||
}
|
||||
const TREE_RADIUS = 400; // Velikost 8x8 cone
|
||||
|
||||
// Inner dense circle
|
||||
for (let angle = 0; angle < Math.PI * 2; angle += 0.25) {
|
||||
let tx = SPAWN_X + Math.cos(angle) * TREE_RADIUS + (Math.random() - 0.5) * 60;
|
||||
let ty = SPAWN_Y + Math.sin(angle) * TREE_RADIUS + (Math.random() - 0.5) * 60;
|
||||
let tKey = Phaser.Utils.Array.GetRandom(treeKeys);
|
||||
let t = this.loadTree(tx, ty, tKey);
|
||||
t.setMask(this.islandMask);
|
||||
this.treesGroup.add(t);
|
||||
if(t) this.treesGroup.add(t);
|
||||
}
|
||||
|
||||
// Outer dense circle
|
||||
for (let angle = 0; angle < Math.PI * 2; angle += 0.15) {
|
||||
let tx = SPAWN_X + Math.cos(angle) * (TREE_RADIUS + 120) + (Math.random() - 0.5) * 80;
|
||||
let ty = SPAWN_Y + Math.sin(angle) * (TREE_RADIUS + 120) + (Math.random() - 0.5) * 80;
|
||||
let tKey = Phaser.Utils.Array.GetRandom(treeKeys);
|
||||
let t = this.loadTree(tx, ty, tKey);
|
||||
if(t) this.treesGroup.add(t);
|
||||
}
|
||||
|
||||
// === FOG OF WAR (Temna megla izven baze) ===
|
||||
this.fowGraphics = this.add.graphics();
|
||||
this.fowGraphics.setDepth(6000);
|
||||
this.fowGraphics.fillStyle(0x0a0f12, 0.98); // Zelo temno modro-siva megla
|
||||
|
||||
// Narišemo 4 pravokotnike, ki pustijo luknjo na sredini
|
||||
const FOW_R = TREE_RADIUS + 60;
|
||||
this.fowGraphics.fillRect(0, 0, WORLD_W, SPAWN_Y - FOW_R); // Zgoraj
|
||||
this.fowGraphics.fillRect(0, SPAWN_Y + FOW_R, WORLD_W, WORLD_H); // Spodaj
|
||||
this.fowGraphics.fillRect(0, SPAWN_Y - FOW_R, SPAWN_X - FOW_R, FOW_R * 2); // Levo
|
||||
this.fowGraphics.fillRect(SPAWN_X + FOW_R, SPAWN_Y - FOW_R, WORLD_W, FOW_R * 2); // Desno
|
||||
|
||||
// Add solid collision against trees!
|
||||
this.physics.add.collider(this.kai, this.treesGroup);
|
||||
// ===================================================================
|
||||
@@ -1094,8 +1110,9 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
// REMOVED PER USER REQUEST
|
||||
/*
|
||||
this.gronk = this.physics.add.sprite(startX - 150, startY - 100, 'gronk');
|
||||
this.gronk.setOrigin(0.5, 1.0); // Sidrišče čisto na dno
|
||||
this.gronk.setScale(0.8); // Gronk is big!
|
||||
this.gronk.setDepth(startY - 100);
|
||||
this.gronk.setDepth(this.gronk.y); // Y-sorting
|
||||
this.gronk.setImmovable(true);
|
||||
this.gronk.body.setSize(80, 60);
|
||||
this.gronk.body.setOffset(88, 190); // Adjusted for 256x256 frame
|
||||
@@ -1152,8 +1169,11 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
this.kai.stop();
|
||||
|
||||
// Camera setup logic
|
||||
this.cameras.main.startFollow(this.kai, true, 0.1, 0.1);
|
||||
this.cameras.main.startFollow(this.kai, true, 0.08, 0.08); // Zelo mehko sledenje
|
||||
this.cameras.main.setRoundPixels(true); // Prevent jitter
|
||||
|
||||
// Spremenljivka za gladko drsenje kamere naprej
|
||||
this.cameraLookahead = { x: 0, y: 0 };
|
||||
this.cursors = this.input.keyboard.createCursorKeys();
|
||||
// Add WASD keys
|
||||
this.keys = this.input.keyboard.addKeys({
|
||||
@@ -1348,14 +1368,25 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
|
||||
console.log('✅ FarmingSystem ready — [E] ore, posadi, zalij, pozeni!');
|
||||
|
||||
// Spodaj: Fiksno zgenerirana polja za kmetovanje
|
||||
const farmStartX = this.islandX + this.islandWidth / 2 - 80;
|
||||
const farmStartY = this.islandY + this.islandHeight / 2 + 140;
|
||||
for (let i = 0; i < 4; i++) {
|
||||
for (let j = 0; j < 2; j++) {
|
||||
if (this.farmingSystem._tillGround) {
|
||||
this.farmingSystem._tillGround(farmStartX + i * 48, farmStartY + j * 48);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ─── WATER SYSTEM ────────────────────────────────────────
|
||||
this.waterSystem = new WaterSystem(this, {
|
||||
tileSize: this.TILE_SIZE,
|
||||
});
|
||||
|
||||
// Postavi Rain Catcher blizu centra otoka (kamor Kai spawn-a)
|
||||
const rcX = this.islandX + this.islandWidth / 2 + 200;
|
||||
const rcY = this.islandY + this.islandHeight / 2;
|
||||
// Zgoraj Desno: Lovilec deževnice (Fiksno za DEMO)
|
||||
const rcX = this.islandX + this.islandWidth / 2 + 128;
|
||||
const rcY = this.islandY + this.islandHeight / 2 - 128;
|
||||
this.waterSystem.placeRainCatcher(rcX, rcY);
|
||||
|
||||
// Poveži water system z farming sistemom (preverj vodo pred zalivanjem)
|
||||
@@ -1373,7 +1404,16 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
|
||||
// ─── DAY/NIGHT SYSTEM ─────────────────────────────────
|
||||
this.dayNightSystem = new DayNightSystem(this, {
|
||||
speed: 1, // 1 sec real = 1 min igre (24 min = 1 dan)
|
||||
speed: 1.2, // 1.2 sec igre na 1 realno sec (20 minut = 1 dan)
|
||||
});
|
||||
|
||||
// ─── ACCESSIBILITY SYSTEM ─────────────────────────────
|
||||
this.accessState = {
|
||||
deafMode: false, autismMode: false, adhdMode: false,
|
||||
fontMode: false, contrastMode: false, colorblindMode: false, onehandMode: false
|
||||
};
|
||||
this.game.events.on('accessibility-changed', (state) => {
|
||||
this.accessState = state;
|
||||
});
|
||||
|
||||
// === EVENT WIRE-UP ===
|
||||
@@ -1459,6 +1499,63 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
|
||||
console.log('✅ ZombieSystem ready — [SPACE] za Alfa Moč!');
|
||||
|
||||
// ─── ODKLEP FAZA 1 (FOG OF WAR LIFT) ──────────────────────
|
||||
this.game.events.on('unlock-faza1', () => {
|
||||
console.log("🔓 FAZA 1 ODKLENJENA! Zmegljen Fog of War, odklenjene zgradbe.");
|
||||
|
||||
// 1. Vizualni indikator umikanja megle
|
||||
const cx = this.cameras.main.centerX;
|
||||
const cy = this.cameras.main.centerY;
|
||||
let fogLiftText = this.add.text(cx, cy - 150, 'NOVA OBMOČJA ODKRITA\n(Megla vojne se dviga)', {
|
||||
fontFamily: 'Arial Black',
|
||||
fontSize: '42px',
|
||||
color: '#44aaff',
|
||||
stroke: '#000',
|
||||
strokeThickness: 8,
|
||||
align: 'center'
|
||||
}).setScrollFactor(0).setOrigin(0.5, 0.5).setDepth(9999).setAlpha(0);
|
||||
|
||||
this.tweens.add({
|
||||
targets: fogLiftText,
|
||||
alpha: 1,
|
||||
y: cy - 200,
|
||||
duration: 2000,
|
||||
ease: 'Sine.easeOut',
|
||||
yoyo: true,
|
||||
hold: 3000,
|
||||
onComplete: () => fogLiftText.destroy()
|
||||
});
|
||||
|
||||
// Umik Fog Of War grafike
|
||||
if (this.fowGraphics) {
|
||||
this.tweens.add({
|
||||
targets: this.fowGraphics,
|
||||
alpha: 0,
|
||||
duration: 3000,
|
||||
ease: 'Sine.easeInOut',
|
||||
onComplete: () => this.fowGraphics.destroy()
|
||||
});
|
||||
}
|
||||
|
||||
// 2. Dodamo nove zgradbe v BuildingSystem
|
||||
if (this.buildingSystem) {
|
||||
this.buildingSystem.catalogue.push(
|
||||
{
|
||||
key: 'garage_ruin',
|
||||
label: 'Garaža',
|
||||
scale: 4.0,
|
||||
colliderW: 200, colliderH: 80, colliderOffsetX: -100, colliderOffsetY: -40
|
||||
},
|
||||
{
|
||||
key: 'barn_ruin',
|
||||
label: 'Hlev',
|
||||
scale: 4.0,
|
||||
colliderW: 200, colliderH: 80, colliderOffsetX: -100, colliderOffsetY: -40
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// === TAKOJ SPAWNI ZOMBIJA (za testiranje, podnevi+ponoči) ===
|
||||
this.time.delayedCall(3000, () => {
|
||||
if (this.zombieSystem) {
|
||||
@@ -1525,8 +1622,10 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
console.log("SFX: THUD!");
|
||||
// this.sound.play('tree_thud');
|
||||
|
||||
// Visual: Screen Shake
|
||||
// Visual: Screen Shake (izklopljen v Autism Mode)
|
||||
if (!this.accessState?.autismMode) {
|
||||
this.cameras.main.shake(300, 0.005);
|
||||
}
|
||||
|
||||
tree.destroy();
|
||||
|
||||
@@ -1880,6 +1979,26 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
/* Removed for cleanup */
|
||||
|
||||
update(time, delta) {
|
||||
if (this.kai && this.kai.active) {
|
||||
// --- LOOKAHEAD CAMERA OFFSET (Gledanje naprej) ---
|
||||
const maxOffset = 180; // Koliko pikslov naprej naj pogleda kamera
|
||||
let targetOffsetX = 0;
|
||||
let targetOffsetY = 0;
|
||||
|
||||
if (this.kai.body.velocity.x > 10) targetOffsetX = maxOffset;
|
||||
else if (this.kai.body.velocity.x < -10) targetOffsetX = -maxOffset;
|
||||
|
||||
if (this.kai.body.velocity.y > 10) targetOffsetY = maxOffset;
|
||||
else if (this.kai.body.velocity.y < -10) targetOffsetY = -maxOffset;
|
||||
|
||||
// Gladko lerpanje proti tarči offseta (manjša vrednost = bolj gladko)
|
||||
this.cameraLookahead.x = Phaser.Math.Linear(this.cameraLookahead.x, targetOffsetX, 0.03);
|
||||
this.cameraLookahead.y = Phaser.Math.Linear(this.cameraLookahead.y, targetOffsetY, 0.03);
|
||||
|
||||
// V Phaserju pozitiven offset zamakne *tarčo*, kar pomeni da gre kamera v drugo smer!
|
||||
this.cameras.main.setFollowOffset(this.cameraLookahead.x, this.cameraLookahead.y);
|
||||
}
|
||||
|
||||
// --- ANIMATE OCEAN ---
|
||||
// (Parallax skipped for rectangles, logic removed to prevent errors)
|
||||
// --- ANIMATE FOAM ---
|
||||
@@ -1935,10 +2054,25 @@ export default class GrassSceneClean extends Phaser.Scene {
|
||||
const velocity = new Phaser.Math.Vector2(0, 0);
|
||||
|
||||
// Input helpers
|
||||
const left = this.cursors.left.isDown || this.keys.left.isDown;
|
||||
const right = this.cursors.right.isDown || this.keys.right.isDown;
|
||||
const up = this.cursors.up.isDown || this.keys.up.isDown;
|
||||
const down = this.cursors.down.isDown || this.keys.down.isDown;
|
||||
let left = this.cursors.left.isDown || this.keys.left.isDown;
|
||||
let right = this.cursors.right.isDown || this.keys.right.isDown;
|
||||
let up = this.cursors.up.isDown || this.keys.up.isDown;
|
||||
let down = this.cursors.down.isDown || this.keys.down.isDown;
|
||||
|
||||
// ── ENOROČNI NAČIN (Sledenje miški z držanjem klika) ──
|
||||
if (this.accessState?.onehandMode && this.input.activePointer.isDown) {
|
||||
const ptr = this.input.activePointer;
|
||||
// Preprečimo tresenje, če je miška preblizu lika
|
||||
if (Phaser.Math.Distance.Between(this.kai.x, this.kai.y - 30, ptr.worldX, ptr.worldY) > 25) {
|
||||
const angle = Phaser.Math.Angle.Between(this.kai.x, this.kai.y - 30, ptr.worldX, ptr.worldY);
|
||||
const dx = Math.cos(angle);
|
||||
const dy = Math.sin(angle);
|
||||
if (dx < -0.3) left = true;
|
||||
if (dx > 0.3) right = true;
|
||||
if (dy < -0.3) up = true;
|
||||
if (dy > 0.3) down = true;
|
||||
}
|
||||
}
|
||||
const space = this.cursors.space.isDown;
|
||||
|
||||
if (left) velocity.x = -1;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
* - Fog (megla) ki se premika
|
||||
* ============================================================
|
||||
*/
|
||||
import LocalizationSystem from '../systems/LocalizationSystem.js';
|
||||
export default class MenuScene extends Phaser.Scene {
|
||||
constructor() {
|
||||
super({ key: 'MenuScene' });
|
||||
@@ -20,6 +21,9 @@ export default class MenuScene extends Phaser.Scene {
|
||||
preload() {
|
||||
this.load.path = 'assets/';
|
||||
|
||||
// Naloži prevode
|
||||
this.load.json('localization', 'localization.json');
|
||||
|
||||
// Ozadje
|
||||
this.load.image('menu_bg', 'DEMO_FAZA1/UI/menu_background.png');
|
||||
|
||||
@@ -38,6 +42,10 @@ export default class MenuScene extends Phaser.Scene {
|
||||
const W = this.cameras.main.width; // 1920
|
||||
const H = this.cameras.main.height; // 1080
|
||||
|
||||
// ─── INITIALIZE LOCALIZATION ───
|
||||
this.i18n = new LocalizationSystem(this);
|
||||
this.i18n.init();
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────
|
||||
// OZADJE
|
||||
// ─────────────────────────────────────────────────────────────────
|
||||
@@ -165,9 +173,10 @@ export default class MenuScene extends Phaser.Scene {
|
||||
const BTN_GAP = 95;
|
||||
|
||||
const buttons = [
|
||||
{ label: '▶ IGRAJ', id: 'play', color: '#44ffcc', hColor: '#ffffff' },
|
||||
{ label: '⚙ NASTAVITVE', id: 'settings', color: '#aabbcc', hColor: '#ffffff' },
|
||||
{ label: '✕ IZHOD', id: 'quit', color: '#cc6666', hColor: '#ff8888' },
|
||||
{ label: '▶ ' + this.i18n.t('menu_play'), id: 'play', color: '#44ffcc', hColor: '#ffffff' },
|
||||
{ label: '⚙ ' + this.i18n.t('menu_options'), id: 'settings', color: '#aabbcc', hColor: '#ffffff' },
|
||||
{ label: '🌍 ' + this.i18n.t('lang_btn'), id: 'lang', color: '#ccddaa', hColor: '#ffffff' },
|
||||
{ label: '✕ ' + this.i18n.t('menu_exit'), id: 'quit', color: '#cc6666', hColor: '#ff8888' },
|
||||
];
|
||||
|
||||
this._btns = [];
|
||||
@@ -188,7 +197,7 @@ export default class MenuScene extends Phaser.Scene {
|
||||
|
||||
// Gumb tekst
|
||||
const txt = this.add.text(BTN_X, y, b.label, {
|
||||
fontFamily: '"Arial Black", Arial',
|
||||
fontFamily: this.i18n.fontFamily,
|
||||
fontSize: '26px',
|
||||
color: b.color,
|
||||
stroke: '#000000',
|
||||
@@ -284,6 +293,15 @@ export default class MenuScene extends Phaser.Scene {
|
||||
// TODO: SettingsScene
|
||||
this._showToast('Nastavitve kmalu! 🔧');
|
||||
}
|
||||
else if (id === 'lang') {
|
||||
// Cycle language
|
||||
const langs = this.i18n.supportedLangs;
|
||||
let idx = langs.indexOf(this.i18n.currentLang);
|
||||
idx = (idx + 1) % langs.length;
|
||||
this.i18n.setLanguage(langs[idx]);
|
||||
// Restart scene to apply new language
|
||||
this.scene.restart();
|
||||
}
|
||||
else if (id === 'quit') {
|
||||
// Electron quit
|
||||
if (typeof window !== 'undefined' && window.electronAPI) {
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
* OVERLAY: Health Critical pulse (pri < 25% HP)
|
||||
* =============================================================
|
||||
*/
|
||||
import LocalizationSystem from '../systems/LocalizationSystem.js';
|
||||
import AccessibilityManager from '../systems/AccessibilityManager.js';
|
||||
|
||||
export default class UIScene extends Phaser.Scene {
|
||||
constructor() {
|
||||
super({ key: 'UIScene', active: false }); // Zaženemo ročno iz GrassScene
|
||||
@@ -31,6 +34,11 @@ export default class UIScene extends Phaser.Scene {
|
||||
inventoryOpen: false,
|
||||
hotbarItems: [null, null, null, null, null, null, null], // 7 slotov
|
||||
activeSlot: 0,
|
||||
isFullGame: false,
|
||||
accessibility: {
|
||||
deafMode: false, autismMode: false, adhdMode: false,
|
||||
fontMode: false, contrastMode: false, colorblindMode: false, onehandMode: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -56,6 +64,10 @@ export default class UIScene extends Phaser.Scene {
|
||||
const H = this.cameras.main.height; // 1080
|
||||
const PAD = 24;
|
||||
|
||||
// ─── INITIALIZE LOCALIZATION ───
|
||||
this.i18n = new LocalizationSystem(this);
|
||||
this.i18n.init();
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────
|
||||
// TOP LEFT — Trial badge + HP + Energy
|
||||
// ─────────────────────────────────────────────────────────────────
|
||||
@@ -76,6 +88,14 @@ export default class UIScene extends Phaser.Scene {
|
||||
ease: 'Sine.easeInOut',
|
||||
});
|
||||
|
||||
// ── NAKUP IGRE LOGIKA ──
|
||||
this.trialBadge.setInteractive({ useHandCursor: true });
|
||||
this.trialBadge.on('pointerdown', () => {
|
||||
if (!this.gameState.isFullGame) {
|
||||
this.unlockFullGame();
|
||||
}
|
||||
});
|
||||
|
||||
// ── HP Bar (health_bar.png je vertikalni triptih: full/empty/empty) ─
|
||||
// Spritesheet je 3 vrstice: top=HP full, mid=HP empty, bot=Energy
|
||||
// Uporabljamo health_bar.png kot ozadje in rišemo fill čez njega
|
||||
@@ -135,6 +155,23 @@ export default class UIScene extends Phaser.Scene {
|
||||
// Prvič nariši
|
||||
this._redrawBars();
|
||||
|
||||
// ── ACCESSIBILITY MENU BUTTON ──
|
||||
this.accBtn = this.add.text(W - PAD, PAD + 180, '⚙️ ' + this.i18n.t('acc_menu'), {
|
||||
fontFamily: this.i18n.fontFamily,
|
||||
fontSize: '18px',
|
||||
color: '#ffffff',
|
||||
backgroundColor: '#000000aa',
|
||||
padding: { x: 10, y: 5 },
|
||||
stroke: '#ff00ff',
|
||||
strokeThickness: 2
|
||||
}).setOrigin(1, 0).setInteractive({ useHandCursor: true }).setDepth(1000);
|
||||
|
||||
// ── INIT ACCESSIBILITY MANAGER ──
|
||||
this.accManager = new AccessibilityManager(this);
|
||||
this.accManager.setupMenu(W, H);
|
||||
|
||||
this.accBtn.on('pointerdown', () => this.accManager.toggleMenu());
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────
|
||||
// TOP RIGHT — Weather Widget (ura + vreme)
|
||||
// ─────────────────────────────────────────────────────────────────
|
||||
@@ -153,8 +190,8 @@ export default class UIScene extends Phaser.Scene {
|
||||
}).setOrigin(0.5, 0.5).setDepth(1005);
|
||||
|
||||
// Dan label (pod uro)
|
||||
this.dayText = this.add.text(W - PAD - 135, PAD + 10, 'DAN 1', {
|
||||
fontFamily: 'Arial Black',
|
||||
this.dayText = this.add.text(W - PAD - 135, PAD + 10, this.i18n.t('day') + ' 1', {
|
||||
fontFamily: this.i18n.fontFamily,
|
||||
fontSize: '18px',
|
||||
color: '#ffdd44',
|
||||
stroke: '#000000',
|
||||
@@ -217,8 +254,8 @@ export default class UIScene extends Phaser.Scene {
|
||||
this.actionBtn.on('pointerout', () => this.actionBtn.clearTint());
|
||||
|
||||
// Crafting label
|
||||
this.add.text(this.actionBtn.x, H - PAD + 2, 'CRAFTING', {
|
||||
fontFamily: 'Arial',
|
||||
this.add.text(this.actionBtn.x, H - PAD + 2, this.i18n.t('crafting'), {
|
||||
fontFamily: this.i18n.fontFamily,
|
||||
fontSize: '13px',
|
||||
color: '#aaaaaa',
|
||||
stroke: '#000',
|
||||
@@ -254,8 +291,8 @@ export default class UIScene extends Phaser.Scene {
|
||||
this._mmR = MM_SIZE / 2 - 16;
|
||||
|
||||
// "MAP" label
|
||||
this.add.text(mmCx, mmCy + MM_SIZE / 2 - 8, 'MAPA', {
|
||||
fontFamily: 'Arial',
|
||||
this.add.text(mmCx, mmCy + MM_SIZE / 2 - 8, this.i18n.t('map'), {
|
||||
fontFamily: this.i18n.fontFamily,
|
||||
fontSize: '11px',
|
||||
color: '#556655',
|
||||
}).setOrigin(0.5, 1).setDepth(1002);
|
||||
@@ -643,4 +680,96 @@ export default class UIScene extends Phaser.Scene {
|
||||
this.minimapKaiDot.lineStyle(2, 0xffffff, 0.6);
|
||||
this.minimapKaiDot.strokeCircle(dotX, dotY, 7);
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
// FULL GAME UNLOCK
|
||||
// =========================================================
|
||||
unlockFullGame() {
|
||||
this.gameState.isFullGame = true;
|
||||
|
||||
// Zamenjaj badge
|
||||
this.trialBadge.setTexture('ui_badge_buy');
|
||||
this.trialBadge.clearTint();
|
||||
|
||||
// Dark-Chibi Noir UI stil: Velik napis preko ekrana
|
||||
const W = this.cameras.main.width;
|
||||
const H = this.cameras.main.height;
|
||||
let unlockText = this.add.text(W / 2, H / 2, 'ODKLENJENO\nFULL GAME', {
|
||||
fontFamily: 'Arial Black',
|
||||
fontSize: '72px',
|
||||
color: '#44ffaa',
|
||||
stroke: '#000000',
|
||||
strokeThickness: 10,
|
||||
align: 'center'
|
||||
}).setOrigin(0.5, 0.5).setDepth(9999).setAlpha(0);
|
||||
|
||||
// Zatemnitev ozadja
|
||||
let dim = this.add.rectangle(W/2, H/2, W, H, 0x000000, 0.6)
|
||||
.setDepth(9998).setAlpha(0);
|
||||
|
||||
this.tweens.add({
|
||||
targets: [unlockText, dim],
|
||||
alpha: 1,
|
||||
duration: 1500,
|
||||
ease: 'Power2',
|
||||
yoyo: true,
|
||||
hold: 3000,
|
||||
onComplete: () => {
|
||||
unlockText.destroy();
|
||||
dim.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
// Pošlji signal v GrassScene, da se odklene Faza 1
|
||||
this.game.events.emit('unlock-faza1');
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
// ADHD MODE TOGGLE
|
||||
// =========================================================
|
||||
toggleADHDMode(isOn) {
|
||||
let alpha = isOn ? 0.0 : 1.0; // Popolnoma skrij ali prikaži
|
||||
|
||||
// Vse elemente, ki niso nujni, skrijemo
|
||||
const hideEls = [
|
||||
this.weatherWidget, this.timeText, this.dayText,
|
||||
this.trialBadge, this.hpBg, this.hpFill, this.hpText,
|
||||
this.energyBg, this.energyFill, this.energyText,
|
||||
this.hotbarBg, this.actionBtn,
|
||||
this.minimapFrame, this.minimapBg, this.minimapKaiDot
|
||||
// this.accBtn namerno ni tukaj, da ga igralec še vedno lahko klikne in ugasne mode!
|
||||
];
|
||||
|
||||
for (const el of hideEls) {
|
||||
if (el) el.setAlpha(alpha);
|
||||
}
|
||||
|
||||
// Skrij tudi hotbar slot elemente
|
||||
if (this.hotbarSlots) {
|
||||
for (const slot of this.hotbarSlots) {
|
||||
if (slot.numLabel) slot.numLabel.setAlpha(alpha);
|
||||
if (slot.highlight) slot.highlight.setAlpha(alpha);
|
||||
if (slot.itemSprite) slot.itemSprite.setAlpha(alpha);
|
||||
if (slot.qtyText) slot.qtyText.setAlpha(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
// Prikaži velik utripajoč cilj
|
||||
if (isOn && !this.adhdGoal) {
|
||||
const W = this.cameras.main.width;
|
||||
this.adhdGoal = this.add.text(W / 2, 100, this.i18n.t('adhd_goal'), {
|
||||
fontFamily: this.i18n.fontFamily, fontSize: '32px', color: '#ffff00', backgroundColor: '#000000aa', padding: { x: 20, y: 10 }, stroke: '#000', strokeThickness: 6
|
||||
}).setOrigin(0.5).setDepth(9998);
|
||||
this.tweens.add({ targets: this.adhdGoal, alpha: 0.3, duration: 800, yoyo: true, repeat: -1 });
|
||||
} else if (!isOn && this.adhdGoal) {
|
||||
this.adhdGoal.destroy();
|
||||
this.adhdGoal = null;
|
||||
}
|
||||
}
|
||||
|
||||
update(time, delta) {
|
||||
if (this.accManager) {
|
||||
this.accManager.update(time, delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
190
nova farma TRAE/src/systems/AccessibilityManager.js
Normal file
190
nova farma TRAE/src/systems/AccessibilityManager.js
Normal file
@@ -0,0 +1,190 @@
|
||||
/**
|
||||
* AccessibilityManager.js
|
||||
*
|
||||
* Vodi celoten Accessibility Meni ter vizualna opozorila za Deaf Mode.
|
||||
*/
|
||||
export default class AccessibilityManager {
|
||||
constructor(scene) {
|
||||
this.scene = scene; // UIScene
|
||||
this.deafAlertRed = null;
|
||||
this.twinBondGlow = null;
|
||||
this.glitchOverlay = null;
|
||||
|
||||
// Poslušaj evente
|
||||
if (this.scene.game) {
|
||||
this.scene.game.events.on('twinBondPulse', this.triggerTwinBondGlow, this);
|
||||
this.scene.game.events.on('flashbackPulse', this.triggerFlashbackGlitch, this);
|
||||
}
|
||||
}
|
||||
|
||||
// Nastavi celoten meni (klicano iz UIScene)
|
||||
setupMenu(W, H) {
|
||||
this.accMenuContainer = this.scene.add.container(W / 2, H / 2).setDepth(9999).setVisible(false);
|
||||
|
||||
let bg = this.scene.add.rectangle(0, 0, 800, 500, 0x111111, 0.95).setStrokeStyle(4, 0xff00ff);
|
||||
let title = this.scene.add.text(0, -210, this.scene.i18n.t('acc_menu'), {
|
||||
fontFamily: this.scene.i18n.fontFamily, fontSize: '24px', color: '#ffdd00'
|
||||
}).setOrigin(0.5);
|
||||
|
||||
// STOLPEC 1
|
||||
let btn1 = this.createAccButton(-190, -110, this.scene.i18n.t('acc_deaf'), 'deafMode');
|
||||
let btn2 = this.createAccButton(-190, -40, this.scene.i18n.t('acc_autism'), 'autismMode');
|
||||
let btn3 = this.createAccButton(-190, 30, this.scene.i18n.t('acc_adhd'), 'adhdMode');
|
||||
let btn4 = this.createAccButton(-190, 100, this.scene.i18n.t('acc_onehand'), 'onehandMode');
|
||||
|
||||
// STOLPEC 2
|
||||
let btn5 = this.createAccButton(190, -110, this.scene.i18n.t('acc_font'), 'fontMode');
|
||||
let btn6 = this.createAccButton(190, -40, this.scene.i18n.t('acc_contrast'), 'contrastMode');
|
||||
let btn7 = this.createAccButton(190, 30, this.scene.i18n.t('acc_colorblind'), 'colorblindMode');
|
||||
|
||||
let closeBtn = this.scene.add.text(0, 200, this.scene.i18n.t('acc_close'), { fontFamily: this.scene.i18n.fontFamily, fontSize: '20px', color: '#ff4444' })
|
||||
.setOrigin(0.5).setInteractive({ useHandCursor: true });
|
||||
closeBtn.on('pointerdown', () => this.toggleMenu());
|
||||
|
||||
this.accMenuContainer.add([bg, title, btn1, btn2, btn3, btn4, btn5, btn6, btn7, closeBtn]);
|
||||
}
|
||||
|
||||
createAccButton(x, y, text, key) {
|
||||
let container = this.scene.add.container(x, y);
|
||||
let bg = this.scene.add.rectangle(0, 0, 360, 50, 0x222222).setInteractive({ useHandCursor: true });
|
||||
let txt = this.scene.add.text(0, 0, text + ' [OFF]', { fontFamily: this.scene.i18n.fontFamily, fontSize: '15px', color: '#aaaaaa' }).setOrigin(0.5);
|
||||
|
||||
bg.on('pointerdown', () => {
|
||||
this.scene.gameState.accessibility[key] = !this.scene.gameState.accessibility[key];
|
||||
let isOn = this.scene.gameState.accessibility[key];
|
||||
bg.fillColor = isOn ? 0x004400 : 0x222222;
|
||||
txt.setColor(isOn ? '#44ff44' : '#aaaaaa');
|
||||
txt.setText(text + (isOn ? ' [ON]' : ' [OFF]'));
|
||||
|
||||
this.scene.game.events.emit('accessibility-changed', this.scene.gameState.accessibility);
|
||||
|
||||
// Apply specific immediate effects
|
||||
if (key === 'adhdMode') this.scene.toggleADHDMode(isOn);
|
||||
if (key === 'contrastMode' || key === 'colorblindMode') this.updateCanvasFilters();
|
||||
if (key === 'fontMode') this.toggleLargeFont(isOn);
|
||||
});
|
||||
|
||||
container.add([bg, txt]);
|
||||
return container;
|
||||
}
|
||||
|
||||
updateCanvasFilters() {
|
||||
const isContrast = this.scene.gameState.accessibility.contrastMode;
|
||||
const isColorblind = this.scene.gameState.accessibility.colorblindMode;
|
||||
|
||||
let filters = [];
|
||||
if (isContrast) filters.push('contrast(1.5) drop-shadow(0 0 10px rgba(0,0,0,0.8))');
|
||||
if (isColorblind) filters.push('saturate(1.5) sepia(0.3) hue-rotate(15deg)'); // Simple protanopia filter tweak
|
||||
|
||||
const canvas = document.querySelector('canvas');
|
||||
if (canvas) {
|
||||
canvas.style.filter = filters.length > 0 ? filters.join(' ') : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
toggleLargeFont(isOn) {
|
||||
// Enostavna povečava vseh tekstov v UI (če je true, x1.2)
|
||||
const scale = isOn ? 1.25 : 1.0;
|
||||
this.scene.children.list.forEach(child => {
|
||||
if (child.type === 'Text' && child !== this.accMenuContainer) {
|
||||
this.scene.tweens.add({ targets: child, scaleX: scale, scaleY: scale, duration: 200 });
|
||||
}
|
||||
});
|
||||
// Tudi v GrassScene
|
||||
const grass = this.scene.scene.get('GrassScene');
|
||||
if (grass) {
|
||||
grass.children.list.forEach(child => {
|
||||
if (child.type === 'Text') {
|
||||
grass.tweens.add({ targets: child, scaleX: scale, scaleY: scale, duration: 200 });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
toggleMenu() {
|
||||
if (this.accMenuContainer) {
|
||||
this.accMenuContainer.setVisible(!this.accMenuContainer.visible);
|
||||
}
|
||||
}
|
||||
|
||||
// Klicano v UIScene update
|
||||
update(time, delta) {
|
||||
const deafModeActive = this.scene.gameState.accessibility.deafMode;
|
||||
|
||||
if (!deafModeActive) {
|
||||
if (this.deafAlertRed) { this.deafAlertRed.destroy(); this.deafAlertRed = null; }
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. Nevarnost zombijev
|
||||
const grass = this.scene.scene.get('GrassScene');
|
||||
if (grass && grass.zombieSystem && grass.kai) {
|
||||
const zombies = grass.zombieSystem.getZombies();
|
||||
let near = false;
|
||||
for (const z of zombies) {
|
||||
if (!z.tamed && Phaser.Math.Distance.Between(z.x, z.y, grass.kai.x, grass.kai.y) < 550) {
|
||||
near = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (near) {
|
||||
if (!this.deafAlertRed) {
|
||||
const W = this.scene.cameras.main.width;
|
||||
const H = this.scene.cameras.main.height;
|
||||
this.deafAlertRed = this.scene.add.rectangle(W/2, H/2, W, H).setStrokeStyle(30, 0xff0000).setDepth(9999);
|
||||
this.deafAlertRed.isFilled = false;
|
||||
this.scene.tweens.add({ targets: this.deafAlertRed, alpha: 0.2, duration: 400, yoyo: true, repeat: -1 });
|
||||
}
|
||||
} else {
|
||||
if (this.deafAlertRed) { this.deafAlertRed.destroy(); this.deafAlertRed = null; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Twin Bond Glow
|
||||
triggerTwinBondGlow() {
|
||||
if (!this.scene.gameState.accessibility.deafMode) return;
|
||||
if (this.twinBondGlow) { this.twinBondGlow.destroy(); }
|
||||
|
||||
const W = this.scene.cameras.main.width;
|
||||
const H = this.scene.cameras.main.height;
|
||||
this.twinBondGlow = this.scene.add.rectangle(W/2, H/2, W, H, 0xaa00ff, 0.4)
|
||||
.setDepth(9998)
|
||||
.setBlendMode(Phaser.BlendModes.SCREEN);
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: this.twinBondGlow,
|
||||
alpha: 0,
|
||||
duration: 2000,
|
||||
ease: 'Sine.inOut',
|
||||
onComplete: () => {
|
||||
if (this.twinBondGlow) { this.twinBondGlow.destroy(); this.twinBondGlow = null; }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 3. Amnezija Spomini (Flashback glitch)
|
||||
triggerFlashbackGlitch() {
|
||||
if (!this.scene.gameState.accessibility.deafMode) return;
|
||||
if (this.glitchOverlay) { this.glitchOverlay.destroy(); }
|
||||
|
||||
const W = this.scene.cameras.main.width;
|
||||
const H = this.scene.cameras.main.height;
|
||||
|
||||
// Screen pulse / flash za flashback
|
||||
this.glitchOverlay = this.scene.add.rectangle(W/2, H/2, W, H, 0xffffff, 0.9).setDepth(10000);
|
||||
|
||||
// Močan tresljaj kamere
|
||||
this.scene.cameras.main.shake(300, 0.03);
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: this.glitchOverlay,
|
||||
alpha: 0,
|
||||
duration: 400,
|
||||
ease: 'Bounce.out',
|
||||
onComplete: () => {
|
||||
if (this.glitchOverlay) { this.glitchOverlay.destroy(); this.glitchOverlay = null; }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -36,9 +36,8 @@ export default class DayNightSystem {
|
||||
this.hour = 6; // Začne ob 6:00
|
||||
this.minute = 0;
|
||||
|
||||
// Hitrost: 1 real sekunda = N minut v igri
|
||||
// Default: 24 real minut = 1 dan → 1 real sec = 1 igra minuta
|
||||
this.gameMinutesPerRealSecond = options.speed || 1;
|
||||
// Hitrost: 1.2 igra minut = 1 real sekunda (24 ur v igri = 1200 real sekund = 20 minut)
|
||||
this.gameMinutesPerRealSecond = options.speed || 1.2;
|
||||
|
||||
// Interaktivni objekti za spanje
|
||||
this.sleepObjects = []; // { x, y, sprite, type }
|
||||
@@ -124,6 +123,11 @@ export default class DayNightSystem {
|
||||
this._onMidnight();
|
||||
}
|
||||
|
||||
// Kazen za nespametne: Omedli ob 02:00, če še ne spi
|
||||
if (this.hour === 2 && this.minute === 0 && !this.isSleeping) {
|
||||
this.passOut();
|
||||
}
|
||||
|
||||
// Emit UI update vsako minuto
|
||||
this.scene.events.emit('timeChanged', {
|
||||
day: this.day,
|
||||
@@ -226,6 +230,63 @@ export default class DayNightSystem {
|
||||
});
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// PASS OUT — Omedli ob 02:00 (Kazen)
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
passOut() {
|
||||
if (this.isSleeping) return;
|
||||
this.isSleeping = true;
|
||||
console.log(`💀 KAI JE OMEDLEL OD UTRUJENOSTI (02:00)!`);
|
||||
|
||||
// Zatemnitev zaslona in rdeč napis
|
||||
this.scene.cameras.main.fadeOut(1500, 20, 0, 0);
|
||||
|
||||
const cx = this.scene.cameras.main.centerX;
|
||||
const cy = this.scene.cameras.main.centerY;
|
||||
|
||||
let passOutText = this.scene.add.text(cx, cy, 'OMEDLEL SI\n(Kazen: -Energija, -Denar)', {
|
||||
fontFamily: 'Arial Black',
|
||||
fontSize: '48px',
|
||||
color: '#ff2222',
|
||||
stroke: '#000000',
|
||||
strokeThickness: 8,
|
||||
align: 'center'
|
||||
}).setOrigin(0.5, 0.5).setDepth(9999).setScrollFactor(0);
|
||||
|
||||
this.scene.time.delayedCall(2000, () => {
|
||||
// Skok na jutro
|
||||
this.hour = 6;
|
||||
this.minute = 0;
|
||||
|
||||
// Kazni
|
||||
if (this.scene.gameState) {
|
||||
this.scene.gameState.energy = Math.max(10, this.scene.gameState.energy - 50); // Zelo malo energije ostane
|
||||
this.scene.events.emit('ui-update-energy', this.scene.gameState.energy);
|
||||
}
|
||||
if (this.scene.playerGold !== undefined) {
|
||||
this.scene.playerGold = Math.max(0, this.scene.playerGold - 50); // Izgubi 50g
|
||||
const uiScene = this.scene.scene.get('UIScene');
|
||||
if (uiScene && uiScene.events) uiScene.events.emit('goldChanged', this.scene.playerGold);
|
||||
}
|
||||
|
||||
// Emit morning events
|
||||
this.scene.events.emit('morningArrived', { day: this.day });
|
||||
this.scene.events.emit('timeChanged', {
|
||||
day: this.day, hour: 6, minute: 0, timeStr: '06:00'
|
||||
});
|
||||
|
||||
// Odstrani tekst in fade in
|
||||
passOutText.destroy();
|
||||
this.scene.cameras.main.fadeIn(1500, 0, 0, 0);
|
||||
|
||||
this._showDayOverlay(this.day);
|
||||
|
||||
this.scene.time.delayedCall(1600, () => {
|
||||
this.isSleeping = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// AMBIENT OSVETLITEV
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
@@ -256,14 +317,14 @@ export default class DayNightSystem {
|
||||
alpha = 0.35 + t * 0.25;
|
||||
r = 0x00; g = 0x00; b = 0x44;
|
||||
} else if (h >= 22 || h < 4) {
|
||||
// Noč: globoka modra tema
|
||||
alpha = 0.60;
|
||||
r = 0x00; g = 0x00; b = 0x22;
|
||||
// Noč: globoka modra tema (Dark-Chibi Noir Stil)
|
||||
alpha = 0.85; // Zelo mračno, nevarno
|
||||
r = 0x01; g = 0x01; b = 0x08; // Črna / globoko temno modra
|
||||
} else if (h >= 4 && h < 6) {
|
||||
// Pred zoro
|
||||
const t = (h - 4) / 2;
|
||||
alpha = 0.60 * (1 - t * 0.5);
|
||||
r = 0x00; g = 0x00; b = 0x22;
|
||||
alpha = 0.85 * (1 - t * 0.5);
|
||||
r = 0x01; g = 0x01; b = 0x08;
|
||||
}
|
||||
|
||||
this.ambientOverlay.clear();
|
||||
|
||||
72
nova farma TRAE/src/systems/LocalizationSystem.js
Normal file
72
nova farma TRAE/src/systems/LocalizationSystem.js
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* LocalizationSystem.js
|
||||
*
|
||||
* Sistem za jezike: SL (privzeto), EN, DE, IT, CN.
|
||||
* Samodejno zazna OS jezik.
|
||||
*/
|
||||
export default class LocalizationSystem {
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
this.supportedLangs = ['sl', 'en', 'de', 'it', 'cn'];
|
||||
this.currentLang = 'sl';
|
||||
this.translations = {};
|
||||
|
||||
// UTF-8 pisava s podporo za šumnike in kitajske pismenke
|
||||
this.fontFamily = '"Noto Sans", "Noto Sans SC", "Arial Black", sans-serif';
|
||||
}
|
||||
|
||||
init() {
|
||||
// Preveri če imamo shranjen jezik
|
||||
const savedLang = localStorage.getItem('nova_farma_lang');
|
||||
if (savedLang && this.supportedLangs.includes(savedLang)) {
|
||||
this.currentLang = savedLang;
|
||||
console.log(`🌍 Localization: Loaded saved lang: ${this.currentLang}`);
|
||||
} else {
|
||||
// Zaznaj sistemski jezik igralca
|
||||
const sysLang = navigator.language || navigator.userLanguage;
|
||||
let shortLang = sysLang.split('-')[0].toLowerCase();
|
||||
|
||||
// Preslikava zh -> cn
|
||||
if (shortLang === 'zh') shortLang = 'cn';
|
||||
|
||||
if (this.supportedLangs.includes(shortLang)) {
|
||||
this.currentLang = shortLang;
|
||||
} else {
|
||||
// Če jezika ni podprtega, se vrni na privzeto Slovenščino (po navodilu)
|
||||
this.currentLang = 'sl';
|
||||
}
|
||||
console.log(`🌍 Localization: Detected OS lang: ${sysLang}, using: ${this.currentLang}`);
|
||||
}
|
||||
|
||||
// Naloži JSON slovar iz Phaserjevega Cache-a
|
||||
if (this.scene.cache.json.exists('localization')) {
|
||||
this.translations = this.scene.cache.json.get('localization');
|
||||
} else {
|
||||
console.warn('⚠️ localization.json ni naložen v cache!');
|
||||
}
|
||||
}
|
||||
|
||||
setLanguage(lang) {
|
||||
if (this.supportedLangs.includes(lang)) {
|
||||
this.currentLang = lang;
|
||||
localStorage.setItem('nova_farma_lang', lang);
|
||||
|
||||
// Če želimo emitirati po celem game-u
|
||||
if (this.scene && this.scene.game) {
|
||||
this.scene.game.events.emit('language-changed', this.currentLang);
|
||||
}
|
||||
console.log(`🌍 Jezik spremenjen na: ${this.currentLang}`);
|
||||
}
|
||||
}
|
||||
|
||||
t(key) {
|
||||
if (this.translations[this.currentLang] && this.translations[this.currentLang][key]) {
|
||||
return this.translations[this.currentLang][key];
|
||||
}
|
||||
// Fallback na slovenščino
|
||||
if (this.translations['sl'] && this.translations['sl'][key]) {
|
||||
return this.translations['sl'][key];
|
||||
}
|
||||
return `[${key}]`; // Če ključa sploh ni
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,11 @@ export default class TwinBondSystem {
|
||||
triggerBond() {
|
||||
this.isActive = true;
|
||||
|
||||
// Oddaj event za AccessibilityManager (za Deaf Mode Purple HUD glow)
|
||||
if (this.scene.game) {
|
||||
this.scene.game.events.emit('twinBondPulse');
|
||||
}
|
||||
|
||||
// Zaustavi Kaja za kratek čas (šok)
|
||||
if (this.scene.kai) {
|
||||
this.scene.kai.canMove = false;
|
||||
@@ -76,7 +81,9 @@ export default class TwinBondSystem {
|
||||
const W = this.scene.cameras.main.width;
|
||||
const H = this.scene.cameras.main.height;
|
||||
this.flashOverlay.clear();
|
||||
this.flashOverlay.fillStyle(0x3a0055, 0.85); // Temno vijolična
|
||||
|
||||
let alpha = this.scene.accessState?.autismMode ? 0.2 : 0.85; // Omehčan za avtizem
|
||||
this.flashOverlay.fillStyle(0x3a0055, alpha); // Temno vijolična
|
||||
this.flashOverlay.fillRect(0, 0, W, H);
|
||||
|
||||
// Skrijemo čez 0.15s
|
||||
|
||||
@@ -99,9 +99,10 @@ export default class ZombieSystem {
|
||||
this._nightCount++;
|
||||
|
||||
// Stopnjevanje tezje po vsaki noci
|
||||
this.maxZombies = Math.min(2 + this._nightCount, 8);
|
||||
const spawnDelay = Math.max(6000, 14000 - this._nightCount * 1000);
|
||||
this.zombieSpeed = Math.min(35 + this._nightCount * 3, 65);
|
||||
// Povečana nevarnost: 2x močnejši, večja hitrost in večje število
|
||||
this.maxZombies = Math.min(4 + this._nightCount * 2, 16);
|
||||
const spawnDelay = Math.max(3000, 8000 - this._nightCount * 1000);
|
||||
this.zombieSpeed = Math.min(60 + this._nightCount * 5, 100);
|
||||
|
||||
console.log(`🌙 Noč ${this._nightCount}: max=${this.maxZombies}, delay=${spawnDelay}ms, speed=${this.zombieSpeed}px/s`);
|
||||
|
||||
@@ -112,6 +113,10 @@ export default class ZombieSystem {
|
||||
if (this.zombies.length < this.maxZombies) {
|
||||
this.spawnZombie();
|
||||
}
|
||||
// Samo ponoči: 30% možnost za spawn Rakuna na robu mape
|
||||
if (Math.random() < 0.3) {
|
||||
this.spawnRaccoon();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -205,6 +210,49 @@ export default class ZombieSystem {
|
||||
return zombie;
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// SPAWN RAKUNA (Nočni spawn)
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
spawnRaccoon(x = null, y = null) {
|
||||
if (x === null || y === null) {
|
||||
const edge = Phaser.Math.Between(0, 3);
|
||||
const margin = 100;
|
||||
switch (edge) {
|
||||
case 0: x = this.islandX + Phaser.Math.Between(margin, this.islandW - margin); y = this.islandY + margin; break;
|
||||
case 1: x = this.islandX + this.islandW - margin; y = this.islandY + Phaser.Math.Between(margin, this.islandH - margin); break;
|
||||
case 2: x = this.islandX + Phaser.Math.Between(margin, this.islandW - margin); y = this.islandY + this.islandH - margin; break;
|
||||
case 3: x = this.islandX + margin; y = this.islandY + Phaser.Math.Between(margin, this.islandH - margin); break;
|
||||
}
|
||||
}
|
||||
|
||||
// Uporabimo placeholder zombi sprite, dokler ni rakuna (tint na sivo, pomanjšan)
|
||||
let tex = this.scene.textures.exists('raccoon') ? 'raccoon' : 'zombie_shambler';
|
||||
const sprite = this.scene.add.sprite(x, y, tex, 0)
|
||||
.setScale(tex === 'raccoon' ? 1.0 : 0.3)
|
||||
.setOrigin(0.5, 1.0)
|
||||
.setDepth(y);
|
||||
|
||||
if (tex === 'zombie_shambler') sprite.setTint(0x777777); // Sivo-črna barva za rakuna
|
||||
|
||||
sprite.setAlpha(0);
|
||||
this.scene.tweens.add({ targets: sprite, alpha: 1, duration: 800 });
|
||||
|
||||
const halo = this.scene.add.graphics().setDepth(y - 1);
|
||||
halo.fillStyle(0xffaa00, 0.15); // Oranžen halo za rakune
|
||||
halo.fillCircle(x, y - 10, 20);
|
||||
|
||||
const raccoon = {
|
||||
sprite, halo, x, y, state: 'wandering', tamed: false,
|
||||
hp: 10, maxHp: 10, dir: 'down',
|
||||
wanderTimer: 0, wanderDirX: 0, wanderDirY: 1,
|
||||
isRaccoon: true
|
||||
};
|
||||
|
||||
this.zombies.push(raccoon);
|
||||
console.log(`🦝 Rakun spawnan ponoči @ ${Math.round(x)},${Math.round(y)}`);
|
||||
return raccoon;
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// UPDATE — Kliči vsak frame iz scene.update()
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
@@ -287,10 +335,10 @@ export default class ZombieSystem {
|
||||
moveX = Math.cos(angle) * speed * dt;
|
||||
moveY = Math.sin(angle) * speed * dt;
|
||||
|
||||
// Rdeči halo (nevarnost)
|
||||
// Rdeči halo (nevarnost) ali oranžen za rakune
|
||||
z.halo.clear();
|
||||
z.halo.fillStyle(0xff0000, 0.18);
|
||||
z.halo.fillCircle(z.sprite.x, z.sprite.y - 20, 40);
|
||||
z.halo.fillStyle(z.isRaccoon ? 0xffaa00 : 0xff0000, 0.18);
|
||||
z.halo.fillCircle(z.sprite.x, z.sprite.y - 20, z.isRaccoon ? 20 : 40);
|
||||
|
||||
} else {
|
||||
// === TAVANJE ===
|
||||
|
||||
Reference in New Issue
Block a user