feat: complete Style 32 overhaul & Tiled integration fix

- Enforced 'Style 32 - Dark Chibi Vector' for all ground assets.
- Fixed critical Prologue-to-Game crash (function renaming).
- Implemented Tiled JSON/TMX auto-conversion.
- Updated Asset Manager to visualize 1800+ assets.
- Cleaned up project structure (new assets/grounds folder).
- Auto-Ground logic added to GameScene.js.
This commit is contained in:
2026-01-11 20:08:56 +01:00
parent 16e4284964
commit 7264ec6fc0
97 changed files with 49754 additions and 690 deletions

1
.gitignore vendored
View File

@@ -23,3 +23,4 @@ npm-debug.log*
# Environment
.env
.env.local
out/

212
ASSET_STATUS_JAN_11_2026.md Normal file
View File

@@ -0,0 +1,212 @@
# 🎯 ASSET STATUS UPDATE - 11. JANUAR 2026
**Čas:** 01:56 CET
**Status:** Pregled manjkajočih slik za celotno igro
---
## 📊 TRENUTNO STANJE SLIK
### ✅ Kar imaš ZDAJ:
- **Skupaj slik:** 2,954 datotek (PNG/JPG/WEBP)
**Razdelitev po kategorijah:**
- 📂 **References:** 1,170 slik (referenčne slike za generiranje)
- 🎨 **Sprites:** 396 game-ready sprite-ov
- 🖼️ **Slike:** 1,155 dodatnih vizualnih elementov
- 🗺️ **Maps:** 7 map assets
- 🎬 **Intro:** 0 (intro asseti so verjetno drugje)
---
## 📈 ŠE MANJKA (po fazah)
### 🎮 DEMO - 85% KONČANO
**Status:** Skoraj vse gotovo! ✅
**Kar manjka za DEMO (~ 90 slik):**
1. **Dodatni CROP-i (25 slik)** ⚠️ PRIORITETA
- Tomato (6 faz)
- Potato (6 faz)
- Corn (6 faz)
- Marijuana (7 faz) - KRITIČNO za demo ekonomijo!
2. **Grassland Production Tiles (58 slik)**
- Grass border tiles (6)
- Path corner tiles (3)
- Crop plot states (8)
- Rock variations (5)
- Bush variations (5)
- Tall grass animation (10 frames)
- Fence T-junction (1)
- Farm gate open (1)
- Mushroom variations (2)
3. **UI Polish (7 slik)** - ne-kritično
- XP bar (2)
- Weather/time indicators (2)
- Tutorial tooltips (2)
- Stack numbers (že obstaja!)
4. **Animation Polish (26 frames)** - opcijsko
- Susi dodatni (sit, sleep, jump - 7 frames)
- Kai farming (harvest, plant, water - 12 frames)
- Ana memory (ghost, diary - 4 frames)
- Crop wilting (3 frames)
**DEMO MANJKA:** ~90 slik (ali samo 25 če ignoriraš opcijske!)
---
### 🏘️ FAZA 2 - 103% KONČANO
**Status:** PRESEŽEK! ✅
**Kar manjka za FAZA 2 (~ 50 slik):**
**NPC Sprite Conversion (50 slik)**
- Imaš 179 NPC reference slik ✅
- Potrebuješ jih pretvoriti v 8-smerne game sprite-e
- ~5 NPCjev × 11 sprite-ov = 55 slik
- To je samo **konverzija**, ne nova generacija!
**FAZA 2 MANJKA:** ~50 slik (konverzija iz obstoječih referenc!)
---
### 🌾 FAZA 1 - 23% KONČANO
**Status:** Še precej dela! 🔄
**Kar manjka za FAZA 1 (~ 712 slik):**
1. **Dodatni Biomi (135 slik)**
- **Forest** (60): Tree variations, forest props, mushrooms, 2 buildings
- **Desert** (35): Sand tiles, cacti, desert rocks, plants
- **Swamp** (40): Mud tiles, water, swamp trees, reeds, 2 buildings
2. **Combat System (119 slik)**
- Kai combat animacije (27 frames)
- Weapons 3 tiers (12 slik)
- Dodatni sovražniki (80 slik): Skeleton, Mutant Rat, Radioactive Boar, Chernobyl Mutants
3. **Crop Expansion (400 slik!)** 🌾
- Trenutno: 6/80 crop types ✅
- Manjka: ~75 crop types × 6 faz = **450 slik**
- Prvi 10 priority (Beans, Cabbage, Lettuce, Onion, Pumpkin, Strawberry, Sunflower, Rice, Cotton, Coffee)
4. **Advanced UI (65 slik)**
- Advanced HUD (6)
- Expanded Inventory (15)
- Crafting UI (12)
- Map/Navigation (7)
- Combat UI (8)
- Additional panels (17)
**FAZA 1 MANJKA:** ~712 slik
---
## 🎯 SKUPNI PREGLED - Koliko še manjka
| Faza | Kar imaš | Kar manjka | % končano | Kritičnost |
|------|----------|------------|-----------|------------|
| **DEMO** | ~317 slik | **~90 slik** (ali 25) | 85% | 🔥 VISOKA |
| **FAZA 2** | ~188 slik | **~50 slik** | 103%* | 🟡 SREDNJA |
| **FAZA 1** | ~213 slik | **~712 slik** | 23% | 🟢 NIZKA |
| **SKUPAJ** | 2,954 slik | **~852 slik** | - | - |
*Faza 2 ima 103% ker imaš presežek infrastrukture in buildings, samo manjkajo NPC sprite-i.
---
## 🚀 PRIORITETE
### 🔥 **HIGH PRIORITY:**
**1. DEMO Implementation (14-16 hours)**
- All assets ready (including 6 crops!) ✅
- Audio ready ✅
- Just needs code!
**2. Cannabis Style 32 Update (6 slik - 0.5 ure)**
- Zamenjaj placeholderje s pravimi Style 32 spriti (ob 06:00)
**3. Faza 2 NPC Conversion (50 slik - 3-4 ure)**
- Konvertiraj 179 referenc v game sprite-e
- Nato je Faza 2 = 100% assets!
---
### 🟡 MEDIUM PRIORITY (naslednji korak):
**4. Faza 1 Biomes (135 slik - 4-5 ur)**
- Unlock Forest, Desert, Swamp exploration
**5. Faza 1 Combat (119 slik - 4-5 ur)**
- Weapons + enemy sprites
**TOTAL MEDIUM:** ~254 slik (~8-10 ur dela)
---
### 🟢 LOW PRIORITY (postopno):
**6. Crop Expansion (450 slik - 15-20 ur)**
- 75 crop types
- Lahko narediš 10 crop-ov naenkrat, čez tedne
**7. Advanced UI (65 slik - 3-4 ure)**
- Polish features
**TOTAL LOW:** ~515 slik (~18-24 ur dela)
---
## 💡 PRIPOROČILO
**Če želiš launch DEMO čim prej:**
1. ✅ Generiraj 25 crop slik (Tomato, Potato, Corn, Marijuana) - **1-2 uri**
2. ✅ Testiraj demo z 6 crop-i
3. ✅ Launch! 🚀
**Če želiš 100% polish pred launch:**
1. ✅ Generiraj 25 crop slik
2. ✅ Generiraj 58 grassland production tiles
3. ✅ Dodaj 26 animation polish frames
4. ✅ Launch! 🚀
**TOTAL:** ~109 slik (4-6 ur dela)
---
## 📊 KONČNA ŠTEVILKA
### 🎯 Koliko še manjka:
- **DEMO ready:** **25 kritičnih slik** (1-2 uri)
- **DEMO polish:** **90 slik** (4-6 ur)
- **Faza 2 ready:** **50 slik** (3-4 ure)
- **Faza 1 ready:** **712 slik** (13-15 ur)
- **TOTAL za celotno igro:** **~852 slik**
### ✅ Kar že imaš:
- **2,954 visual assets** (references, sprites, maps)
- **Demo: 85% complete**
- **Faza 2: 103% complete** (minus NPC conversion)
- **Faza 1: 23% complete**
---
## 🎮 ZAKLJUČEK
**DEMO je skoraj gotov!** Manjka samo **25 kritičnih crop slik** za launch. 🚀
Če želiš celotno Faza 1 + Faza 2, potrebuješ še **~762 slik** (50 NPC + 712 Faza 1).
**Čas za vse:** ~20-25 ur generiranja.
**Ali lahko DEMO launchaš ZDAJ?****DA!** Z 2 crop-i (Wheat + Carrot)
**Ali dodaš še 4 crop-e?** ⚠️ **Priporočeno!** (samo 1-2 uri)
---
*Status Update - 11. Januar 2026, 01:56 CET* 🎯

View File

@@ -1,4 +1,4 @@
# 📋 FAZA 2 - DETAJLNI DELOVNI NAČRT
ok # 📋 FAZA 2 - DETAJLNI DELOVNI NAČRT
## Town Restoration - Complete Work Breakdown
**Status:** 53/182 sprites (29%)

View File

@@ -1,4 +1,4 @@
# 🎯 MASTER COMPLETION CHECKLIST - JAN 9, 2026
n# 🎯 MASTER COMPLETION CHECKLIST - JAN 9, 2026
## DEMO + FAZA 1 + FAZA 2 - Complete Overview
**Created:** Jan 9, 2026 13:02 CET

View File

@@ -0,0 +1,44 @@
# 📓 SESSION DNEVNIK - 11. JANUAR 2026 (Night Shift)
**Datum:** 11.01.2026
**Ura:** 01:50 - 02:20 CET
**Fokus:** Generiranje Crop Assetov & Style Unification
---
## 🎯 DOSEŽKI SEJE
### 1. Vizualna Unifikacija - STYLE 32 LOCKED 🔒
- **Odločitev:** Prehod iz Style 30 (Garden Story) na **Style 32 (Dark-Chibi Noir)** za VSE crop-e.
- **Razlog:** Konsistentnost z liki, dark charm, boljša vidljivost na terenu.
- **Specifikacije:**
- Thick black outline (5px)
- Flat bold colors
- Dark/edgy aesthetic (skulls, dark themes)
### 2. Asset Generacija (24 novih slik)
Generirali smo kompletne življenjskeikle (6 faz) za 4 nove rastline:
| Crop | Status | Stil | Opombe |
|------|--------|------|--------|
| **🍅 Tomato** | ✅ COMPLETE | Style 32 | Perfekten dark chibi stil |
| **🥔 Potato** | ✅ COMPLETE | Style 32 | Cute potato seed packet! |
| **🌽 Corn** | ✅ COMPLETE | Style 32 | Golden corn with skull bundle |
| **🌿 Cannabis** | ⚠️ PLACEHOLDER | Reference | Zaradi API quota limita uporabljene reference (do 06:00) |
### 3. Tehnični Status DEMO verzije
- **Asset Coverage:** 100% za Demo (vsi crop-i prisotni)
- **Placeholders:** Cannabis uporablja začasne `_TEMP` reference, ki so preimenovane v prava imena. Igra deluje brez napak.
- **Next Gen Window:** 11.01. ob 06:00 CET (reset kvo 40 slik).
---
## 📝 NASLEDNJI KORAKI (Jutranja izmena)
1. **Generiraj Cannabis v Style 32** (takoj ko se resetira kvota).
2. **Implementiraj Crop Mechanics** (rast, harvest, inventory logic).
3. **Zaženi Demo Playtest** z vsemi 6 rastlinami (Wheat, Carrot, Tomato, Potato, Corn, Cannabis).
---
*Session zaključil: 02:20 CET* 🌙

23
STYLE_32_DIRECTIVE.md Normal file
View File

@@ -0,0 +1,23 @@
# GAME MASTER STYLE GUIDE - ZABETONIRANO 2026
## 🎨 ART STYLE: "STYLE 32 - DARK CHIBI VECTOR"
**MANDATORY FOR ALL ASSETS (Terrain, Characters, UI, Buildings)**
Ovaj stil je **ZAKON**. Ne odstopaj od njega niti za milimeter.
### 1. Vizualna DNA (Lastnosti)
* **Vector Aesthetic:** Čiste, ostre linije. NIČ PIKSLOV. Izgledati mora kot visokokakovostna vektorska grafika ali "Clean Hand-Drawn".
* **Bold Outlines:** VSE mora imeti debele, črne obrobe (outlines). To je ključ za "Chibi" in "Edgy" videz.
* **Flat Colors:** Uporabljaj ploske, žive barve. Brez prelivajočih gradientov ali realističnega senčenja. "Cel Shaded" videz.
* **Dark/Edgy Vibe:** Čeprav je Chibi, mora biti "badass". Razpoke v tleh, ostre skale, temnejši odtenki vode. Nič "Cute & Cuddly", ampak "Cute & Dangerous".
### 2. Generacijski Prompti (Reference)
Za prihodnje generiranje uporabljaj te ključne besede:
> "Vector art style, hand-drawn aesthetic, bold clarity, thick black outlines, flat colors, dark chibi style, cel shaded, no pixel art, seamless pattern."
### 3. Implementacija
Trenutno aktivni tileseti v tem stylu:
- `assets/terrain/grass_tile.png` (Style 32 Grass)
- `assets/terrain/dirt_tile.png` (Style 32 Dirt)
- `assets/terrain/stone_path_tile.png` (Style 32 Stone)
- `assets/terrain/water_tile.png` (Style 32 Water)

Binary file not shown.

BIN
assets/grounds/dirt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 KiB

BIN
assets/grounds/farmland.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 KiB

BIN
assets/grounds/grass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 772 KiB

BIN
assets/grounds/stone.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 657 KiB

BIN
assets/grounds/water.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 521 KiB

19292
assets/maps/NovaFarma.json Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 KiB

BIN
assets/props/fence_wood.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 684 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 613 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 752 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 765 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 765 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 608 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 651 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 KiB

View File

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.10" tiledversion="1.11.0" name="Buildings" tilewidth="256" tileheight="256" tilecount="27" columns="0">
<grid orientation="orthogonal" width="1" height="1"/>
<tile id="0">
<image source="../buildings/basement_entrance.png"/>
</tile>
<tile id="1">
<image source="../buildings/city_hall.png"/>
</tile>
<tile id="2">
<image source="../buildings/generator.png"/>
</tile>
<tile id="3">
<image source="../buildings/land_marker_available.png"/>
</tile>
<tile id="4">
<image source="../buildings/land_marker_locked.png"/>
</tile>
<tile id="5">
<image source="../buildings/mine_entrance.png"/>
</tile>
<tile id="6">
<image source="../buildings/mine_support_beam.png"/>
</tile>
<tile id="7">
<image source="../buildings/minecart_empty.png"/>
</tile>
<tile id="8">
<image source="../buildings/minecart_full.png"/>
</tile>
<tile id="9">
<image source="../buildings/mining_lantern.png"/>
</tile>
<tile id="10">
<image source="../buildings/mining_pickaxe.png"/>
</tile>
<tile id="11">
<image source="../buildings/ore_pile_coal.png"/>
</tile>
<tile id="12">
<image source="../buildings/ore_pile_stone.png"/>
</tile>
<tile id="13">
<image source="../buildings/population_board.png"/>
</tile>
<tile id="14">
<image source="../buildings/power_pole_corner.png"/>
</tile>
<tile id="15">
<image source="../buildings/power_pole_straight.png"/>
</tile>
<tile id="16">
<image source="../buildings/resource_depot.png"/>
</tile>
<tile id="17">
<image source="../buildings/resource_pile_food.png"/>
</tile>
<tile id="18">
<image source="../buildings/resource_pile_wood.png"/>
</tile>
<tile id="19">
<image source="../buildings/storage_crate.png"/>
</tile>
<tile id="20">
<image source="../buildings/storage_shed.png"/>
</tile>
<tile id="21">
<image source="../buildings/uv_light_fixture.png"/>
</tile>
<tile id="22">
<image source="../buildings/working_table.png"/>
</tile>
<tile id="23">
<image source="../terrain/grass_placeholder.png"/>
</tile>
<tile id="24">
<image source="../props/fence_stone.png"/>
</tile>
<tile id="25">
<image source="../props/fence_wood.png"/>
</tile>
<tile id="26">
<image source="../props/fence_wooden_style32.png"/>
</tile>
</tileset>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,22 @@
<? xml version = "1.0" encoding = "UTF-8" ?>
<tileset version="1.10" tiledversion="1.11.0" name="Grounds_Style32" tilewidth="512" tileheight="512" tilecount="4" columns="0">
<grid orientation="orthogonal" width="1" height="1" />
<tile id="0">
<image source="../grounds/grass.png" width="512" height="512" />
</tile>
<tile id="1">
<image source="../grounds/dirt.png" width="512" height="512" />
</tile>
<tile id="2">
<image source="../grounds/stone.png" width="512" height="512" />
</tile>
<tile id="3">
<image source="../grounds/water.png" width="512" height="512" />
</tile>
<tile id="4">
<image source="../grounds/farmland.png" width="512" height="512" />
</tile>
<tile id="5">
<image source="../grounds/wood_floor.png" width="512" height="512" />
</tile>
</tileset>

View File

@@ -0,0 +1,269 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.11" tiledversion="1.11.2" orientation="orthogonal" renderorder="right-down" width="80" height="80" tilewidth="48" tileheight="48" infinite="0" nextlayerid="5" nextobjectid="1">
<properties>
<property name="music" value="farm_theme"/>
</properties>
<tileset firstgid="1" source="dirt.tsx"/>
<tileset firstgid="442" source="grass.tsx"/>
<tileset firstgid="883" source="stone.tsx"/>
<tileset firstgid="1324" source="water.tsx"/>
<tileset firstgid="1765" source="fence_wood.tsx"/>
<tileset firstgid="2206" source="apple_tree_mature_autumn_1767678811175.tsx"/>
<tileset firstgid="2647" source="vfx_hallucination_ghost_1767620660864.tsx"/>
<tileset firstgid="3088" source="uploaded_image_1767407781294.tsx"/>
<tileset firstgid="3257" source="uploaded_image_2_1767410857322.tsx"/>
<tileset firstgid="3698" source="uploaded_image_3_1767410857322.tsx"/>
<layer id="1" name="Ground" width="80" height="80">
<data encoding="csv">
595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,
616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,
637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,
658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,
679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,
700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,
721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,
742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,
763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,
595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,
616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,
637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,1326,1327,1328,1329,1330,1331,1332,1326,1327,1328,1329,1330,1331,1332,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,2305,2306,2307,2308,2309,1330,1331,1326,1327,1328,1329,1330,1331,1332,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,
658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,1347,1348,1349,1350,1351,1352,1353,1347,1348,1349,1350,1351,1352,1353,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,1351,1352,1347,1348,1349,1350,1351,1352,1353,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,
679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,1368,1369,1370,1371,1372,1373,1374,1368,1369,1370,1371,1372,1373,1374,2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,1372,1373,1368,1369,1370,1371,1372,1373,1374,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,
700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,1389,1390,1391,1392,1393,1394,1395,1389,1390,1391,1392,1393,1394,1395,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365,2366,2367,2368,2369,2370,2371,2372,1393,1394,1389,1390,1391,1392,1393,1394,1395,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,
721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,1326,1327,1328,1329,1330,1331,1332,1326,1327,1328,1329,1330,1331,1332,2376,2377,2378,2379,2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,1330,1326,1327,1328,1329,1330,1331,1332,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,
742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,1347,1348,1349,1350,1351,1352,1353,1347,1348,1349,1350,1351,1352,1353,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,2414,1351,1347,1348,1349,1350,1351,1352,1353,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,
763,764,765,766,767,768,769,770,771,772,773,763,3720,3721,3722,3723,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,1372,1373,1374,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,1372,1368,1369,1370,1371,1372,1373,1374,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,
595,596,597,598,599,600,601,602,603,604,605,595,3741,3742,3743,3744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,3760,1393,1394,1395,2439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,2455,2456,1393,1389,1390,1391,1392,1393,1394,1395,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,
616,617,618,619,620,621,622,623,624,625,626,616,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778,3779,3780,3781,907,908,909,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2473,2474,2475,2476,2477,910,911,912,913,914,915,916,917,918,919,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,
637,638,639,640,641,642,643,644,645,646,647,637,3783,3784,3785,3786,3787,3788,3789,3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,928,929,930,2481,2482,2483,2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,931,932,933,934,935,936,937,938,939,940,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,
658,659,660,661,662,663,664,665,666,667,668,658,3804,3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,3819,3820,3821,3822,3823,949,950,951,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,2515,2516,2517,2518,2519,952,953,954,955,956,957,958,959,960,961,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,
679,680,681,682,683,684,685,686,687,688,689,679,3825,3826,3827,3828,3829,3830,3831,3832,3833,3834,3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,689,679,680,2523,2524,2525,2526,2527,2528,2529,2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,
700,701,702,703,704,705,706,707,708,709,710,700,3846,3847,3848,3849,3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,3864,3865,710,700,701,2544,2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,2560,2561,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,
721,722,723,724,725,726,727,728,729,730,731,721,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,3879,3880,3881,3882,3883,3884,3885,3886,731,721,722,2565,2566,2567,2568,2569,2570,2571,2572,2573,2574,2575,2576,2577,2578,2579,2580,2581,2582,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,
742,743,744,745,746,747,748,749,750,751,752,742,3888,3889,3890,3891,3892,3893,3894,3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,752,742,743,744,745,133,134,135,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,
763,764,765,766,767,768,769,770,771,772,773,763,3909,3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,3925,3926,3927,3928,2670,2671,2672,2673,2674,2675,2676,2677,2678,2679,2680,2681,2682,2683,2684,2685,2686,2687,2688,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,
595,596,597,598,599,600,601,602,603,604,605,595,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,2691,2692,2693,2694,2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,2709,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,
616,617,618,619,620,621,622,623,624,625,626,616,3951,3952,3953,3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,2725,2726,2727,2728,2729,2730,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,
637,638,639,640,641,642,643,644,645,646,647,637,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,3984,3985,3986,3987,3988,3989,3990,3991,2733,2734,2735,2736,2737,2738,2739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,
658,659,660,661,662,663,664,665,666,667,668,658,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,2754,2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,2770,2771,2772,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,
679,680,681,682,683,684,685,686,687,688,689,679,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,4030,4031,4032,4033,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,2785,2786,2787,2788,2789,2790,2791,2792,2793,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,
700,701,702,703,704,705,706,707,708,709,710,700,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,2796,2797,2798,2799,2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,
721,722,723,724,725,726,727,728,729,730,731,721,4056,4057,4058,4059,4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,4075,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,2830,2831,2832,2833,2834,2835,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,
742,743,744,745,746,747,748,749,750,751,752,742,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,4090,4091,4092,4093,4094,4095,4096,2838,2839,2840,2841,2842,2843,2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,
763,764,765,766,767,768,769,770,771,772,773,763,4098,4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,2859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,2875,2876,2877,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,
595,596,597,598,599,600,601,602,603,604,605,595,4119,4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,4135,4136,4137,4138,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2890,2891,2892,2893,2894,2895,2896,2897,2898,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,
616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,2900,2901,2902,2903,2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,
637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,2934,2935,2936,2937,2938,2939,2940,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,
658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,2942,2943,2944,2945,2946,2947,2948,2949,2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,
679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,2963,2964,2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,2979,2980,2981,2982,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,
700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,
721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,3005,3006,3007,3008,3009,3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,3024,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,
742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,3090,3091,3092,3093,3094,3095,3096,3097,3032,3033,3324,3325,3326,3327,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,
763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,3103,3104,3105,3106,3107,3108,3109,3110,196,197,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,
595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,3116,3117,3118,3119,3120,3121,3122,3123,70,71,3366,3367,3368,3369,3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,
616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,3129,3130,3131,3132,3133,3134,3135,3136,91,92,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,3400,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,
637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,3142,3143,3144,3145,3146,3147,3148,3149,112,113,3408,3409,3410,3411,3412,3413,3414,3415,3416,3417,3418,3419,3420,3421,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,
658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,3155,3156,3157,3158,3159,3160,3161,3162,70,71,3429,3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,
679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,3168,3169,3170,3171,3172,3173,3174,3175,91,92,3450,3451,3452,3453,3454,3455,3456,3457,3458,3459,3460,3461,3462,3463,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,
700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,3181,3182,3183,3184,3185,3186,3187,3188,112,113,3471,3472,3473,3474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,
721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,3194,3195,3196,3197,3198,3199,3200,3201,133,134,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,3505,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,
742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,3207,3208,3209,3210,3211,3212,3213,3214,154,155,3513,3514,3515,3516,3517,3518,3519,3520,3521,3522,3523,3524,3525,3526,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,
763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,3220,3221,3222,3223,3224,3225,3226,3227,175,176,3534,3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,
595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,3233,3234,3235,3236,3237,3238,3239,3240,196,197,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3568,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,
616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,3246,3247,3248,3249,3250,3251,3252,3253,217,218,3576,3577,3578,3579,3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,
637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,
658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,667,668,658,659,660,661,3720,3721,3722,3723,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,660,
679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,3741,3742,3743,3744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,3760,681,
700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778,3779,3780,3781,702,
721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,3783,3784,3785,3786,3787,3788,3789,3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,723,
742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,3804,3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,3819,3820,3821,3822,3823,744,
763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,3825,3826,3827,3828,3829,3830,3831,3832,3833,3834,3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,765,
595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,3846,3847,3848,3849,3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,3864,3865,597,
616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,3879,3880,3881,3882,3883,3884,3885,3886,618,
637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,3888,3889,3890,3891,3892,3893,3894,3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,639,
658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,3909,3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,3925,3926,3927,3928,660,
679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,681,
700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,3951,3952,3953,3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,702,
721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,3984,3985,3986,3987,3988,3989,3990,3991,723,
742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,744,
763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,767,768,769,770,771,772,773,763,764,765,766,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,4030,4031,4032,4033,765,
595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,599,600,601,602,603,604,605,595,596,597,598,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,597,
616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,620,621,622,623,624,625,626,616,617,618,619,4056,4057,4058,4059,4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,4075,618,
637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,641,642,643,644,645,646,647,637,638,639,640,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,4090,4091,4092,4093,4094,4095,4096,639,
658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,662,663,664,665,666,667,668,658,659,660,661,4098,4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,660,
679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,683,684,685,686,687,688,689,679,680,681,682,4119,4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,4135,4136,4137,4138,681,
700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,703,704,705,706,707,708,709,710,700,701,702,
721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,724,725,726,727,728,729,730,731,721,722,723,
742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744,745,746,747,748,749,750,751,752,742,743,744
</data>
</layer>
<layer id="2" name="Objects" width="80" height="80">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="3" name="Collision" width="80" height="80" opacity="0.5">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<objectgroup id="4" name="Audio_Zones"/>
</map>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="apple_tree_mature_autumn_1767678811175" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../sprites/trees/apple/apple_tree_mature_autumn_1767678811175.png" width="1024" height="1024"/>
</tileset>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="cannabis_s32_stage1_seeds" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../slike 🟢/crops/cannabis_s32_stage1_seeds.png" width="1024" height="1024"/>
</tileset>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="cannabis_s32_stage2_sprout" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../slike 🟢/crops/cannabis_s32_stage2_sprout.png" width="1024" height="1024"/>
</tileset>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="cannabis_s32_stage3_young" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../slike 🟢/crops/cannabis_s32_stage3_young.png" width="1024" height="1024"/>
</tileset>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="cannabis_s32_stage4_growing" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../slike 🟢/crops/cannabis_s32_stage4_growing.png" width="1024" height="1024"/>
</tileset>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="cannabis_s32_stage5_ready" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../slike 🟢/crops/cannabis_s32_stage5_ready.png" width="1024" height="1024"/>
</tileset>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="cannabis_s32_stage6_harvested" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../slike 🟢/crops/cannabis_s32_stage6_harvested.png" width="1024" height="1024"/>
</tileset>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="corn_s32_stage1_seeds" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../slike 🟢/crops/corn_s32_stage1_seeds.png" width="1024" height="1024"/>
</tileset>

20247
assets/tiled/demo_test.json Normal file

File diff suppressed because it is too large Load Diff

4
assets/tiled/dirt.tsx Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="dirt" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../grounds/dirt.png" width="1024" height="1024"/>
</tileset>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="download-19" tilewidth="48" tileheight="48" tilecount="169" columns="13">
<image source="../../../../Desktop/download-19.jpg" width="640" height="640"/>
</tileset>

View File

@@ -0,0 +1,72 @@
{
"compressionlevel": -1,
"height": 80,
"infinite": false,
"properties": [
{
"name": "music",
"type": "string",
"value": "farm_ambient"
}
],
"layers": [
{
"data": [],
"height": 80,
"id": 1,
"name": "Ground",
"opacity": 1,
"type": "tilelayer",
"visible": true,
"width": 80,
"x": 0,
"y": 0
},
{
"data": [],
"height": 80,
"id": 2,
"name": "Objects",
"opacity": 1,
"type": "tilelayer",
"visible": true,
"width": 80,
"x": 0,
"y": 0
},
{
"data": [],
"height": 80,
"id": 3,
"name": "Collision",
"opacity": 0.5,
"type": "tilelayer",
"visible": false,
"width": 80,
"x": 0,
"y": 0
},
{
"draworder": "topdown",
"id": 4,
"name": "Audio_Zones",
"objects": [],
"opacity": 1,
"type": "objectgroup",
"visible": true,
"x": 0,
"y": 0
}
],
"nextlayerid": 5,
"nextobjectid": 1,
"orientation": "orthogonal",
"renderorder": "right-down",
"tiledversion": "1.11.0",
"tileheight": 48,
"tilesets": [],
"tilewidth": 48,
"type": "map",
"version": "1.10",
"width": 80
}

View File

@@ -0,0 +1,61 @@
{
"compressionlevel": -1,
"height": 100,
"infinite": false,
"properties": [
{
"name": "music",
"type": "string",
"value": "basement_ambient"
}
],
"layers": [
{
"data": [],
"height": 100,
"id": 1,
"name": "Ground",
"opacity": 1,
"type": "tilelayer",
"visible": true,
"width": 100,
"x": 0,
"y": 0
},
{
"data": [],
"height": 100,
"id": 2,
"name": "Objects",
"opacity": 1,
"type": "tilelayer",
"visible": true,
"width": 100,
"x": 0,
"y": 0
},
{
"data": [],
"height": 100,
"id": 3,
"name": "Collision",
"opacity": 0.5,
"type": "tilelayer",
"visible": false,
"width": 100,
"x": 0,
"y": 0
}
],
"nextlayerid": 4,
"nextobjectid": 1,
"orientation": "orthogonal",
"renderorder": "right-down",
"tiledversion": "1.11.0",
"tileheight": 48,
"tilesets": [],
"tilewidth": 48,
"type": "map",
"version": "1.10",
"width": 100
}

View File

@@ -0,0 +1,368 @@
{
"compressionlevel": -1,
"height": 10,
"infinite": false,
"layers": [
{
"data": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"height": 10,
"id": 1,
"name": "Ground",
"opacity": 1,
"type": "tilelayer",
"visible": true,
"width": 10,
"x": 0,
"y": 0
},
{
"data": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"height": 10,
"id": 2,
"name": "Objects",
"opacity": 1,
"type": "tilelayer",
"visible": true,
"width": 10,
"x": 0,
"y": 0
},
{
"data": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"height": 10,
"id": 3,
"name": "Collision",
"opacity": 0.5,
"type": "tilelayer",
"visible": false,
"width": 10,
"x": 0,
"y": 0
},
{
"draworder": "topdown",
"id": 4,
"name": "Audio_Zones",
"objects": [],
"opacity": 1,
"type": "objectgroup",
"visible": true,
"x": 0,
"y": 0
}
],
"nextlayerid": 5,
"nextobjectid": 1,
"orientation": "orthogonal",
"renderorder": "right-down",
"tiledversion": "1.11.0",
"tileheight": 48,
"tilesets": [],
"tilewidth": 48,
"type": "map",
"version": "1.10",
"width": 10
}

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="fence_wood" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../props/fence_wood.png" width="1024" height="1024"/>
</tileset>

4
assets/tiled/grass.tsx Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="grass" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../grounds/grass.png" width="1024" height="1024"/>
</tileset>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="resource_depot" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../buildings/resource_depot.png" width="1024" height="1024"/>
</tileset>

4
assets/tiled/stage1.tsx Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="stage1" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../crops/faza1/carrots/fall/stage1.png" width="1024" height="1024"/>
</tileset>

4
assets/tiled/stone.tsx Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="stone" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../grounds/stone.png" width="1024" height="1024"/>
</tileset>

72
assets/tiled/untitled.tmx Normal file
View File

@@ -0,0 +1,72 @@
{
"compressionlevel":-1,
"height":80,
"infinite":false,
"properties": [
{
"name": "music",
"type": "string",
"value": "farm_ambient"
}
],
"layers":[
{
"data":[],
"height":80,
"id":1,
"name":"Ground",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":80,
"x":0,
"y":0
},
{
"data":[],
"height":80,
"id":2,
"name":"Objects",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":80,
"x":0,
"y":0
},
{
"data":[],
"height":80,
"id":3,
"name":"Collision",
"opacity":0.5,
"type":"tilelayer",
"visible":false,
"width":80,
"x":0,
"y":0
},
{
"draworder":"topdown",
"id":4,
"name":"Audio_Zones",
"objects":[],
"opacity":1,
"type":"objectgroup",
"visible":true,
"x":0,
"y":0
}
],
"nextlayerid":5,
"nextobjectid":1,
"orientation":"orthogonal",
"renderorder":"right-down",
"tiledversion":"1.11.0",
"tileheight":48,
"tilesets":[],
"tilewidth":48,
"type":"map",
"version":"1.10",
"width":80
}

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="uploaded_image_1767405356012" tilewidth="16" tileheight="16" tilecount="1600" columns="40">
<image source="../slike 🟢/MASTER_REFS 🟣/uploaded_image_1767405356012.jpg" width="640" height="640"/>
</tileset>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="uploaded_image_1767407781294" tilewidth="48" tileheight="48" tilecount="169" columns="13">
<image source="../slike 🟢/MASTER_REFS 🟣/uploaded_image_1767407781294.jpg" width="640" height="640"/>
</tileset>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="uploaded_image_2_1767410857322" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../slike 🟢/MASTER_REFS 🟣/uploaded_image_2_1767410857322.jpg" width="1024" height="1024"/>
</tileset>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="uploaded_image_3_1767410857322" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../slike 🟢/MASTER_REFS 🟣/uploaded_image_3_1767410857322.jpg" width="1024" height="1024"/>
</tileset>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="vfx_hallucination_ghost_1767620660864" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../sprites/vfx/vfx_hallucination_ghost_1767620660864.png" width="1024" height="1024"/>
</tileset>

4
assets/tiled/water.tsx Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.11" tiledversion="1.11.2" name="water" tilewidth="48" tileheight="48" tilecount="441" columns="21">
<image source="../grounds/water.png" width="1024" height="1024"/>
</tileset>

View File

@@ -63,8 +63,31 @@
container.innerHTML += `ERROR: ${msg}\nAt: ${url}:${lineNo}:${columnNo}\n\n`;
}
console.error('Global Error:', msg, url, lineNo, error);
// ELECTRON LOGGER
if (typeof require !== 'undefined') {
try {
const { ipcRenderer } = require('electron');
ipcRenderer.send('log-action', `ERROR: ${msg} at ${url}:${lineNo}`);
} catch (e) { }
}
return false;
};
// ELECTRON CLICK LOGGER
if (typeof require !== 'undefined') {
try {
const { ipcRenderer } = require('electron');
document.addEventListener('click', (event) => {
const target = event.target;
const info = target.id || target.tagName || (target.innerText ? target.innerText.substring(0, 20) : 'unknown');
ipcRenderer.send('log-action', `CLICK: <${target.tagName}> "${info}" at (${event.clientX}, ${event.clientY})`);
});
console.log('✅ PRO MODE Logger active');
} catch (e) {
console.warn('Logger not active (requires Electron)');
}
}
</script>
<!-- Phaser 3 -->
@@ -143,6 +166,7 @@
<script src="src/systems/TwinBondSystem.js"></script> <!-- 💞 Twin Bond (Kai ↔ Ana) -->
<script src="src/systems/OceanSystem.js"></script>
<script src="src/systems/VisualEffectsSystem.js"></script>
<script src="src/scripts/AmnesiaEffect.js"></script> <!-- 🌀 Amnesia Effect -->
<script src="src/systems/PlaytimeTrackerSystem.js"></script>
<script src="src/systems/LocalizationSystem.js"></script>
<script src="src/utils/FPSMonitor.js"></script>
@@ -211,8 +235,8 @@
<script src="src/scenes/BootScene.js"></script>
<script src="src/scenes/PreloadScene.js"></script>
<script src="src/scenes/IntroScene.js"></script> <!-- 🎬 INTRO SEQUENCE (Jan 10, 2026) -->
<script src="src/scenes/DemoScene.js"></script> <!-- 🎮 DEMO SCENE -->
<script src="src/scenes/DemoSceneEnhanced.js"></script> <!-- ✨ ENHANCED DEMO with Locket! -->
<!-- <script src="src/scenes/DemoScene.js"></script> --> <!-- 🎮 DEMO SCENE (DISABLED) -->
<!-- <script src="src/scenes/DemoSceneEnhanced.js"></script> --> <!-- ✨ ENHANCED DEMO (DISABLED) -->
<script src="src/scenes/TiledTestScene.js"></script> <!-- 🗺️ Tiled Map Test Scene -->
<!-- ⚠️ TEMPORARILY DISABLED - Missing assets (prologue.json, NPC portraits) -->
<script src="src/scenes/PrologueScene.js"></script><!-- 🎬 Story Prologue -->
@@ -257,6 +281,9 @@
<script src="src/systems/MasterGameSystemsManager.js"></script> <!-- 🎮 Master Coordinator -->
<!-- 🧪 TEST SCENE -->
<script src="src/AssetManifest.js"></script> <!-- 📦 Asset Manifest -->
<script src="src/scenes/AssetTestScene.js"></script> <!-- 🖼️ Asset Gallery -->
<!-- <script src="src/systems/WaterPhysicsSystem.js"></script> --> <!-- 🌊 Water Physics (DISABLED) -->
<script src="src/scenes/SystemsTestScene.js"></script>
<!-- 🎵 NEW AUDIO SYSTEMS - JAN 8 2026 -->

31
main.js
View File

@@ -1,8 +1,9 @@
// 🎮 MRTVA DOLINA - ELECTRON MAIN PROCESS
// Simple and clean main process file
const { app, BrowserWindow } = require('electron');
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
const fs = require('fs');
let mainWindow;
@@ -26,6 +27,34 @@ function createWindow() {
});
}
// 🪵 LOGGER SYSTEM
function logToFile(message) {
const logPath = path.join(app.getPath('desktop'), 'MRTVA_DOLINA_TEST', 'test_log.txt');
// Fallback if folder doesn't exist (e.g. running from source)
// But user asked for specific folder on Desktop.
// Actually, if we are running from USB, we might want it relative.
// Spec: "vklopljenim logiranjem v test_log.txt".
// I will try to write to the execution directory first, or desktop as fallback.
// Let's stick to the requested "MRTVA_DOLINA_TEST" on Desktop for now as the target location.
// But if the user runs it on a different machine, paths differ.
// SAFE BET: Write to 'test_log.txt' in the same folder as the executable (or app data).
// However, for the specific task "zapakiraj... z vklopljenim logiranjem", I'll write to a "logs" folder or standard location.
// Let's write to `test_log.txt` in the app directory for portability.
const logFile = 'test_log.txt';
const timestamp = new Date().toISOString();
const logLine = `[${timestamp}] ${message}\n`;
fs.appendFile(logFile, logLine, (err) => {
if (err) console.error('Failed to write log:', err);
});
}
ipcMain.on('log-action', (event, message) => {
logToFile(message);
console.log('[LOG]', message);
});
app.whenReady().then(() => {
createWindow();

View File

@@ -1,5 +1,9 @@
{
"activeFile": "",
"Map/SizeTest": {
"height": 4300,
"width": 2
},
"activeFile": "assets/tiled/probna farma numero uno .tmx",
"expandedProjectPaths": [
"assets/maps"
],
@@ -189,6 +193,99 @@
"assets/maps/tree_blue.tsx": {
"scaleInDock": 1
},
"assets/tiled/Buildings.tsx": {
"dynamicWrapping": true,
"scaleInDock": 0.044
},
"assets/tiled/Faza1_Nova.tmx": {
"scale": 0.4729,
"selectedLayer": 0,
"viewCenter": {
"x": 2465.637555508564,
"y": 1418.9046310002118
}
},
"assets/tiled/apple_tree_mature_autumn_1767678811175.tsx": {
"scaleInDock": 0.25
},
"assets/tiled/cannabis_s32_stage1_seeds.tsx": {
"dynamicWrapping": false,
"scaleInDock": 1
},
"assets/tiled/cannabis_s32_stage2_sprout.tsx": {
"scaleInDock": 1
},
"assets/tiled/cannabis_s32_stage3_young.tsx": {
"scaleInDock": 1
},
"assets/tiled/cannabis_s32_stage4_growing.tsx": {
"scaleInDock": 1
},
"assets/tiled/cannabis_s32_stage5_ready.tsx": {
"scaleInDock": 1
},
"assets/tiled/cannabis_s32_stage6_harvested.tsx": {
"scaleInDock": 0.1425
},
"assets/tiled/corn_s32_stage1_seeds.tsx": {
"scaleInDock": 1.0119
},
"assets/tiled/dirt.tsx": {
"scaleInDock": 0.3029
},
"assets/tiled/download-19.tsx": {
"scaleInDock": 0.1547
},
"assets/tiled/faza1_kmetija.json": {
"scale": 0.4273,
"selectedLayer": 0,
"viewCenter": {
"x": 193.07278258834538,
"y": 332.31921366721275
}
},
"assets/tiled/fence_wood.tsx": {
"scaleInDock": 0.015625
},
"assets/tiled/grass.tsx": {
"scaleInDock": 0.6441
},
"assets/tiled/probna farma numero uno .tmx": {
"scale": 0.125,
"selectedLayer": 0,
"viewCenter": {
"x": 2016,
"y": 1856
}
},
"assets/tiled/resource_depot.tsx": {
"scaleInDock": 0.2436
},
"assets/tiled/stage1.tsx": {
"dynamicWrapping": false,
"scaleInDock": 0.3887
},
"assets/tiled/stone.tsx": {
"scaleInDock": 0.378
},
"assets/tiled/uploaded_image_1767405356012.tsx": {
"scaleInDock": 0.125
},
"assets/tiled/uploaded_image_1767407781294.tsx": {
"scaleInDock": 1
},
"assets/tiled/uploaded_image_2_1767410857322.tsx": {
"scaleInDock": 0.125
},
"assets/tiled/uploaded_image_3_1767410857322.tsx": {
"scaleInDock": 0.125
},
"assets/tiled/vfx_hallucination_ghost_1767620660864.tsx": {
"scaleInDock": 0.0625
},
"assets/tiled/water.tsx": {
"scaleInDock": 1
},
"maps/demo_project/campfire.tsx": {
"dynamicWrapping": false,
"scaleInDock": 1
@@ -249,10 +346,17 @@
}
},
"last.externalTilesetPath": "/Users/davidkotnik/repos/novafarma/assets/maps",
"map.height": 80,
"map.lastUsedFormat": "tmx",
"map.layerDataFormat": "3",
"map.width": 80,
"openFiles": [
"assets/tiled/probna farma numero uno .tmx"
],
"project": "novafarma.tiled-project",
"recentFiles": [
"assets/tiled/probna farma numero uno .tmx",
"assets/tiled/faza1_kmetija.json",
"assets/maps 🟣/MINIMAL_TEMPLATE.tmx",
"assets/maps 🟣/narava_rastline_grass_flowers_style32.tsx",
"assets/maps 🟣/fresh_workspace.tmx",
@@ -262,9 +366,10 @@
"assets/maps/NovaFarma.json",
"assets/maps/NovaFarma.tmx"
],
"tileset.lastUsedFilter": "All Files (*)",
"tileset.lastUsedFormat": "tsx",
"tileset.tileSize": {
"height": 32,
"width": 32
"height": 48,
"width": 48
}
}

View File

@@ -0,0 +1,40 @@
# 📔 SESSION LOG: 11. Januar 2026
**Čas zaključka:** 20:00 CET
**Status:** ✅ USPEŠNO ZAKLJUČENO
## 🏆 Ključni Dosežki (Major Achievements)
### 1. 🎨 Vizualna Revolucija (Style 32)
* **Definiran Nov Stil:** Uradno sprejet "Style 32 - Dark Chibi Vector" kot vizualni standard.
* **Dokumentacija:** Ustvarjen `STYLE_32_DIRECTIVE.md`, ki prepoveduje piksle in zapoveduje debele obrobe.
* **Asseti:** Zgenerirani in implementirani novi osnovni materiali:
* 🌱 `grass.png` (Trava)
* 🟤 `dirt.png` (Zemlja)
* 🪨 `stone.png` (Kamnita pot)
* 🌊 `water.png` (Voda)
* 🚜 `farmland.png` (Njiva)
* 🪵 `wood_floor.png` (Lesen pod)
### 2. 🗺️ Tiled Map Integracija
* **Popravljeni Formati:** Rešen konflikt med JSON in TMX formati.
* **Nova Struktura:** Vzpostavljena čista struktura map (`assets/grounds`, `assets/tiled`).
* **Tileseti:** Ustvarjena namenska tileseta `Buildings.tsx` in `Grounds_Style32.tsx` za hitro delo.
* **Live Map:** Tvoja mapa "Probna Farma Numero Uno" je bila uspešno konvertirana in vstavljena v igro kot `NovaFarma.json`.
### 3. ⚙️ Sistemski Popravki
* **Auto-Ground:** `GameScene.js` zdaj avtomatsko zapolni praznine s travo.
* **Asset Manager:** Popolnoma posodobljen pregledovalnik (`visual_asset_manager.html`), ki zdaj vidi vseh 1800+ assetov.
* **Critical Bugfix:** Odpravljen crash v `UltimatePrologueScene.js` (preimenovana funkcija `exitPrologue`), kar omogoča prehod v igro.
### 4. 🎵 Avdio
* **Ambient:** Nastavljen sistem, da mapa sama sproži ustrezno glasbo (`farm_theme`).
---
## 📝 Next Steps (Za naslednjič)
1. **Faza 1 Detajliranje:** Nadaljevanje risanja farme v Tiledu z novimi asseti.
2. **Gameplay Loop:** Testiranje delovanja njiv (sajenje, rast) na novi mapi.
3. **NPC Postavitev:** Dodajanje Kaia in Ane na mapo preko Tiled Object Layerja.
*System shutting down... Good night, Developer.* 🌙🚀

7254
src/AssetManifest.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -29,8 +29,11 @@ class Player {
this.maxEnergy = 100;
this.energyDrain = 10; // per second while sprinting
// State
// State
this.isMoving = false;
this.isActing = false; // 🛑 Stardew Action Lock
this.direction = 'down';
this.lastDir = { x: 0, y: 1 }; // Default south
@@ -349,6 +352,14 @@ class Player {
}
handleInput(dt) {
// 🛑 STARDEW LOGIC: Block movement if acting
if (this.isActing) {
this.velocity.x = 0;
this.velocity.y = 0;
return;
}
// 🎮 COLLECT INPUT FROM ALL SOURCES
let inputX = 0;
let inputY = 0;

View File

@@ -68,7 +68,24 @@ const config = {
debug: false
}
},
scene: [BootScene, PreloadScene, IntroScene, PrologueScene, EnhancedPrologueScene, UltimatePrologueScene, SystemsTestScene, TestVisualAudioScene, DemoScene, DemoSceneEnhanced, TiledTestScene, StoryScene, GameScene, UIScene, TownSquareScene],
scene: [
BootScene,
PreloadScene,
AssetTestScene,
IntroScene,
PrologueScene,
EnhancedPrologueScene,
UltimatePrologueScene,
SystemsTestScene,
TestVisualAudioScene,
// DemoScene,
// DemoSceneEnhanced,
TiledTestScene,
StoryScene,
GameScene,
UIScene,
TownSquareScene
],
scale: {
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH

View File

@@ -0,0 +1,122 @@
class AssetTestScene extends Phaser.Scene {
constructor() {
super({ key: 'AssetTestScene' });
}
create() {
console.log('🖼️ Asset Test Scene - Gallery Mode');
this.cameras.main.setBackgroundColor('#222222');
const title = this.add.text(20, 20, 'ASSET GALLERY CHECK', {
fontSize: '32px',
fill: '#ffffff',
fontFamily: 'Courier New'
});
const categories = [
{ name: 'PHASE 1 (FARM)', items: (window.AssetManifest && window.AssetManifest.phases) ? window.AssetManifest.phases.farm : [] },
{ name: 'PHASE 2 (BASEMENT/MINE)', items: (window.AssetManifest && window.AssetManifest.phases) ? window.AssetManifest.phases.basement_mine : [] },
{ name: 'COMMON (CHARACTERS/INTRO)', items: (window.AssetManifest && window.AssetManifest.phases) ? window.AssetManifest.phases.common : [] }
];
let startY = 80;
let startX = 20;
categories.forEach(cat => {
// Category Header
this.add.text(startX, startY, cat.name.toUpperCase(), {
fontSize: '24px',
fill: '#ffff00',
fontstyle: 'bold'
});
startY += 40;
// Display Assets
let x = startX;
let count = 0;
// Use items from manifest
const items = cat.items || [];
if (items.length === 0) {
this.add.text(x, startY, '(No assets in manifest phase)', { color: '#666' });
startY += 40;
} else {
items.forEach(item => {
const key = item.key;
// Check if actually loaded
if (!this.textures.exists(key)) {
this.add.text(x, startY, `[FAIL] ${key}`, { color: '#ff0000', fontSize: '10px' });
x += 80;
return;
}
const img = this.add.image(x, startY, key);
// Scale down if too big
if (img.width > 64) {
const scale = 64 / Math.max(img.width, img.height);
img.setScale(scale);
}
img.setOrigin(0, 0);
// Detailed Info Text
const w = img.width;
const h = img.height;
let infoColor = '#bbbbbb';
// Scaling Check (Greenhouse limit example: 1024px)
if (w > 1024 || h > 1024) {
infoColor = '#ff5555'; // Red Alert
}
// Label: Name + Size
const labelText = `${key}\n${w}x${h}px`;
this.add.text(x, startY + 70, labelText, {
fontSize: '9px',
fill: infoColor,
wordWrap: { width: 75 }
});
// NOIR CHECK (Simulation: Check if alpha at borders is correct? Too expensive.
// Visual check: Red border fallback)
const border = this.add.rectangle(x + 32, startY + 32, 64, 64);
border.setStrokeStyle(1, 0x444444);
// Add click to log
img.setInteractive();
img.on('pointerdown', () => {
console.log(`Asset: ${key}, Size: ${img.width}x${img.height}`);
this.tweens.add({ targets: img, scale: img.scale * 1.2, duration: 100, yoyo: true });
});
x += 80;
count++;
if (count > 10) { // New row
count = 0;
x = startX;
startY += 100;
}
});
startY += 100; // Next category gap
}
});
// Navigation
const backBtn = this.add.text(this.cameras.main.width - 150, 20, 'BACK TO INTRO', {
fontSize: '20px',
backgroundColor: '#ff0000',
padding: { x: 10, y: 5 }
})
.setInteractive({ useHandCursor: true })
.on('pointerdown', () => this.scene.start('IntroScene'));
// Scroll
this.input.on('wheel', (pointer, gameObjects, deltaX, deltaY, deltaZ) => {
this.cameras.main.scrollY += deltaY * 0.5;
});
}
}

View File

@@ -45,10 +45,48 @@ class BootScene extends Phaser.Scene {
window.SPRITE_TREE_HEALTHY = 'tree_green_final';
window.SPRITE_TREE_BLUE = 'tree_blue_final';
window.SPRITE_TREE_DEAD = 'tree_dead_final';
window.SPRITE_TREE_DEAD = 'tree_dead_final';
window.SPRITE_TREE_SAPLING = 'tree_sapling';
// Takoj po bootu gremo v PreloadScene
this.time.delayedCall(100, () => {
// 🌍 GLOBAL FLAGS (Story Registry)
if (!window.gameState) window.gameState = {};
window.gameState.story = {
isAmnesiaActive: true,
daysPassed: 0,
parentsGhostFound: false,
introCompleted: false
};
console.log('📜 Story Registry Initialized:', window.gameState.story);
// 🛠️ DEBUG HOOK: Press 'G' for Gallery
// Note: BootScene is very short-lived, so we put this here just in case,
// but typically input listeners are wiped on scene change.
// Better: We rely on PreloadScene to carry us, BUT user asked for BootScene hook.
// Since BootScene auto-transitions in 100ms, user has to be VERY fast or we pause.
// Let's pause auto-transition if user holds G?
// Better: Just check directly.
const keys = this.input.keyboard.createCursorKeys();
// Since we can't reliably catch 'G' in 100ms, let's add it to window and check in PreloadScene?
// Or simply: Add a global listener that persists (if possible), or just scene start.
// Let's make BootScene wait a tiny bit longer or add instruction.
// Actually, user said "V BootScene... dodaj tisti hook".
this.input.keyboard.on('keydown-G', () => {
console.log('🖼️ Gallery Shortcut Detected!');
// Cancel auto transition
this.transitionEvent.remove();
this.scene.start('AssetTestScene');
});
// Debug Text
this.add.text(10, 10, 'Press G for Asset Gallery', { fontSize: '12px', fill: '#00ff00' }).setDepth(1000);
// Takoj po bootu gremo v PreloadScene (razen če G)
this.transitionEvent = this.time.delayedCall(1500, () => {
// Increased delay slightly to 1.5s so user has time to read/press G
// This is Development Mode ONLY tweak
this.scene.start('PreloadScene');
});
}

View File

@@ -43,11 +43,10 @@ class EnhancedPrologueScene extends Phaser.Scene {
const { width, height } = this.cameras.main;
// Start noir music (low volume)
this.noirMusic = this.sound.add('noir_ambient', {
this.noirMusic = this.playAudioSafe('noir_ambient', {
volume: 0.3,
loop: true
});
this.noirMusic.play();
// Create layers
this.backgroundLayer = this.add.container(0, 0);
@@ -93,8 +92,9 @@ class EnhancedPrologueScene extends Phaser.Scene {
// PHASE 1: Black Screen + Breathing (0:00 - 0:10)
this.showSubtitle("Everything is dark... why do I only hear silence?");
const breathingSound = this.sound.add('voice_breathing');
breathingSound.play();
this.showSubtitle("Everything is dark... why do I only hear silence?");
const breathingSound = this.playAudioSafe('voice_breathing');
// Fade to cellar after breathing + 2s
breathingSound.once('complete', () => {
@@ -116,8 +116,7 @@ class EnhancedPrologueScene extends Phaser.Scene {
ease: 'Sine.easeInOut'
});
const flyoverVoice = this.sound.add('voice_flyover');
flyoverVoice.play();
const flyoverVoice = this.playAudioSafe('voice_flyover');
// Show subtitle
this.time.delayedCall(500, () => {
@@ -166,8 +165,7 @@ class EnhancedPrologueScene extends Phaser.Scene {
// Play awakening voice
this.time.delayedCall(2000, () => {
const awakeningVoice = this.sound.add('voice_awakening');
awakeningVoice.play();
const awakeningVoice = this.playAudioSafe('voice_awakening');
this.showSubtitle("My head... it hurts. Where am I? Who am I...?");
@@ -209,8 +207,7 @@ class EnhancedPrologueScene extends Phaser.Scene {
// Play truth voice
this.time.delayedCall(1500, () => {
const truthVoice = this.sound.add('voice_truth');
truthVoice.play();
const truthVoice = this.playAudioSafe('voice_truth');
this.showSubtitle("Kai Marković. 14 years old. That's me. But this other girl... why do I feel so empty?");
@@ -256,8 +253,7 @@ class EnhancedPrologueScene extends Phaser.Scene {
// PHASE 5: Determination (2:30 - 3:00)
this.clearSubtitle();
const determinationVoice = this.sound.add('voice_determination');
determinationVoice.play();
const determinationVoice = this.playAudioSafe('voice_determination');
this.showSubtitle("Someone is waiting for me out there. I can't remember the face, but I feel the promise.");
@@ -334,6 +330,30 @@ class EnhancedPrologueScene extends Phaser.Scene {
this.endIntro();
}
playAudioSafe(key, config = {}) {
try {
if (this.cache.audio.exists(key)) {
const sound = this.sound.add(key, config);
sound.play();
return sound;
} else {
console.warn(`⚠️ Audio key missing: ${key}`);
// Return dummy object with 'once' method to prevent crashes on event listeners
return {
once: (event, callback) => {
// Simulate immediate completion
if (event === 'complete') callback();
},
stop: () => { },
play: () => { }
};
}
} catch (e) {
console.error(`❌ Audio error for ${key}:`, e);
return { once: (e, cb) => { if (e === 'complete') cb(); }, stop: () => { }, play: () => { } };
}
}
endIntro() {
console.log('🎬 Intro complete! Launching GameScene...');

View File

@@ -1,4 +1,5 @@
// Game Scene - Glavna igralna scena
// NOTE: WaterPhysicsSystem and AssetManifest must be loaded in index.html, not imported here (Electron/Browser Limitation)
class GameScene extends Phaser.Scene {
constructor() {
@@ -20,6 +21,22 @@ class GameScene extends Phaser.Scene {
async create() {
console.log('🎮 GameScene: Initialized!');
// 🖼️ SETUP BACKGROUND (Direct Farm Image)
// Checks 'farm_background' (from Phase 1) or fallback 'intro_chaos'
const bgKey = this.textures.exists('farm_background') ? 'farm_background' : 'intro_chaos';
if (this.textures.exists(bgKey)) {
this.add.image(0, 0, bgKey)
.setOrigin(0, 0)
.setDisplaySize(this.sys.canvas.width, this.sys.canvas.height)
.setDepth(-999); // Way back
console.log(`🖼️ Farm Background Set: ${bgKey}`);
}
// 🖼️ SETUP BACKGROUND
this.currentPhaseBg = null;
// Phase Selector removed in favor of Tiled Map
// Generate procedural textures
new TextureGenerator(this).generateAll();
InventoryIcons.create(this); // Override with flat 2D inventory icons
@@ -52,8 +69,8 @@ class GameScene extends Phaser.Scene {
daysFarmed: 0
};
// PARALLAX BACKGROUND - Clouds & Birds
this.createParallaxBackground();
// PARALLAX BACKGROUND - DISABLED FOR HARD RESET
// this.createParallaxBackground();
// Inicializiraj terrain sistem - 100x100 mapa
console.log('🌍 Initializing terrain...');
@@ -150,10 +167,11 @@ class GameScene extends Phaser.Scene {
console.log(`✅ Biome Enemies ready! (${enemyStats.alive} enemies)`);
// Quest System
// Quest System - DISABLED AUTO-START FOR CLEAN VIEW
this.landmarkQuests = new LandmarkQuestSystem(this);
this.landmarkQuests.startMainQuest();
this.landmarkQuests.startExplorationQuests();
console.log(`✅ Quest System ready! (${this.landmarkQuests.activeQuests.length} active quests)`);
// this.landmarkQuests.startMainQuest(); // Disable popup
// this.landmarkQuests.startExplorationQuests(); // Disable popup
console.log(`✅ Quest System initialized (Passive Mode)`);
// Map Reveal
this.mapReveal = new MapRevealSystem(this);
@@ -171,77 +189,106 @@ class GameScene extends Phaser.Scene {
console.log('🔍 Checking for NovaFarma map...');
try {
if (this.make.tilemap) {
// Ensure key matches PreloadScene
if (this.cache.tilemap.exists('NovaFarma')) {
const map = this.make.tilemap({ key: 'NovaFarma' });
// DEBUG LOGGING
console.log('🗺️ Map object created:', map);
if (map) {
console.log(`🗺️ Map dimensions: ${map.width}x${map.height} tiles, ${map.widthInPixels}x${map.heightInPixels} pixels`);
console.log('🗺️ Tilesets:', map.tilesets.map(t => t.name));
console.log('🗺️ Layers:', map.layers.map(l => l.name));
}
if (map && map.width > 0) {
console.log('✅ FOUND VALID USER MAP: NovaFarma.json');
// Use terrain system if available, else simple render
if (this.terrainSystem && this.terrainSystem.loadFromTiled) {
this.terrainSystem.loadFromTiled(map);
} else {
// 🏗️ STANDARD TILED RENDERING (The "Tiled-First" Approach)
console.log('🗺️ Rendering Tiled Map Layers...');
// 0. 🌍 AUTO-GROUND (User Request)
// Automatically fill background with grass if 'Ground' layer is empty or just as a base.
// Priority: grass_tile (User request), grass_texture, farm_background, intro_chaos
const groundTextures = ['grass_tile', 'grass_texture', 'farm_background', 'intro_chaos'];
const bgTexture = groundTextures.find(tex => this.textures.exists(tex));
if (bgTexture) {
// Create a TileSprite that covers the whole map
const bg = this.add.tileSprite(
0, 0,
map.widthInPixels, map.heightInPixels,
bgTexture
).setOrigin(0, 0).setDepth(-100);
console.log(`🌱 Auto-Ground applied using texture: ${bgTexture}`);
}
// 1. Render Tile Layers (Ground, Objects, Collision, Decoration...)
const tileset = map.tilesets[0];
if (tileset) {
map.layers.forEach(layer => {
if (layer.type === 'tilelayer') {
const createdLayer = map.createLayer(layer.name, tileset, 0, 0);
// Set Depth based on layer name or order
if (layer.name === 'Objects') createdLayer.setDepth(10); // Above ground
if (layer.name === 'Collision') createdLayer.setVisible(false); // Hide collision usually
}
});
}
// 2. Parse Object Layers (Audio, Logic, Spawns)
try {
// 🎵 MUSIC PROP
const mapMusic = map.properties && map.properties.find(p => p.name === 'music')?.value;
if (mapMusic) {
console.log(`🎵 Map Triggered Music: ${mapMusic}`);
// Use sound manager or direct play (SoundManager preferred but let's check safety)
// Assuming raw Phaser sound for safety if manager not ready
try {
this.sound.stopAll(); // Stop previous
this.sound.play(mapMusic, { loop: true, volume: 0.5 });
} catch (e) { console.warn("Audio play failed", e); }
}
const audioLayer = map.getObjectLayer('Audio_Zones');
if (audioLayer && audioLayer.objects) {
console.log(`🎵 Found ${audioLayer.objects.length} Audio Zones`);
}
const logicLayer = map.getObjectLayer('Logic') || map.getObjectLayer('Spawns');
if (logicLayer && logicLayer.objects) {
console.log(`🧠 Found ${logicLayer.objects.length} Logic Objects`);
logicLayer.objects.forEach(obj => {
if (obj.name === 'PlayerSpawn') {
this.tiledSpawnPoint = { x: obj.x, y: obj.y };
console.log('📍 Tiled defined Player Spawn:', this.tiledSpawnPoint);
}
if (obj.type === 'zombie_spawn') {
// Register zombie spawn point
}
});
}
} catch (err) {
console.warn('⚠️ Error parsing object layers:', err);
}
}
this.tiledMapLoaded = true;
// UPDATE SYSTEM DIMENSIONS TO MATCH TILED MAP
this.worldWidth = map.width;
this.worldHeight = map.height;
if (this.biomeSystem) {
this.biomeSystem.worldWidth = map.width;
this.biomeSystem.worldHeight = map.height;
// Regenerate biome map for the new dimensions (optional, but consistent)
this.biomeSystem.generateBiomeMap();
}
if (this.structureSystem) {
this.structureSystem.worldWidth = map.width;
this.structureSystem.worldHeight = map.height;
this.structureSystem.generateAll(); // Re-generate for tiled map
}
// 🕵️ FIND SPAWN POINT IN MAP
// 🕵️ FIND SPAWN POINT IN MAP (Optional)
const playerLayer = map.getLayer('Player');
if (playerLayer) {
console.log('👤 Found Player layer, searching for spawn point...');
// Find first tile in Player layer
map.layers.forEach(layer => {
if (layer.name === 'Player') {
for (let y = 0; y < layer.height; y++) {
for (let x = 0; x < layer.width; x++) {
if (layer.data[y][x].index !== -1) {
this.tiledSpawnPoint = {
x: x * map.tileWidth + map.tileWidth / 2,
y: y * map.tileHeight + map.tileHeight / 2
};
console.log(`📍 Found Player Spawn in Map at (${x}, ${y}) -> World: ${this.tiledSpawnPoint.x}, ${this.tiledSpawnPoint.y}`);
return; // Break loops
// Logic to extract spawn point...
console.log('👤 Player Layer detected (Logic Placeholder)');
}
}
}
}
});
// 🕵️ DEBUG: Check what is under the player (Moved here for scope)
if (this.tiledSpawnPoint) {
const px = Math.floor(this.tiledSpawnPoint.x / map.tileWidth);
const py = Math.floor(this.tiledSpawnPoint.y / map.tileHeight);
const groundLayer = map.getLayer('Ground') || map.layers[0];
if (groundLayer) {
const tile = map.getTileAt(px, py, true, groundLayer.name);
const originTile = map.getTileAt(0, 0, true, groundLayer.name);
console.log(`🕵️ Inspecting Ground at Player (${px}, ${py}):`, tile ? `Index ${tile.index}` : 'NULL');
console.log(`🕵️ Inspecting Ground at Origin (0, 0):`, originTile ? `Index ${originTile.index}` : 'NULL');
}
}
} else {
console.warn('⚠️ No "Player" layer found in map!');
}
} else {
console.error('❌ Map created but invalid width (0) or null!');
}
} else {
console.warn('⚠️ Map "NovaFarma" not found in cache. Ensure it is loaded in PreloadScene.');
}
} catch (e) {
console.error('⚠️ CRITICAL ERROR loading NovaFarma map:', e);
@@ -253,6 +300,26 @@ class GameScene extends Phaser.Scene {
this.terrainSystem.height = 100;
await this.terrainSystem.generate();
console.log('✅ Flat 2D terrain ready (Procedural)!');
// 🎨 BACKGROUND (Fallback)
// If we are in procedural mode (no Tilemap), let's add a nice background underlay
// Use a large texture or color. Since we don't have a single 'farm_background' in Manifest yet,
// we'll use a tileable dirt/grass approach or just set color.
// But user requested: "V GameScene.js dodaj sliko ozadja kmetije... this.add.image(0, 0, 'farm_background')"
// Warning: 'farm_background' is NOT in AssetManifest.js yet. I will check for 'intro_chaos' as placeholder?
// Or I should add 'farm_background' to manifest first? User implies it exists.
// I'll check existence.
if (this.textures.exists('farm_background')) {
this.add.image(0, 0, 'farm_background').setOrigin(0, 0).setDepth(-100);
console.log('🖼️ Added farm_background');
} else if (this.textures.exists('intro_chaos')) {
// Placeholder until real BG is ready
const bg = this.add.image(0, 0, 'intro_chaos').setOrigin(0, 0).setDepth(-100);
bg.setDisplaySize(2000, 2000); // Scale up
bg.setAlpha(0.2); // Subtle
console.log('🖼️ Added placeholder background (intro_chaos)');
}
} else {
console.log('✅ Flat 2D terrain ready (Tiled)!');
@@ -719,10 +786,11 @@ class GameScene extends Phaser.Scene {
// Kamera kontrole
this.setupCamera();
// Initialize Systems
console.log('🌦️ Initializing Unified Weather System...');
this.weatherSystem = new WeatherSystem(this);
this.timeSystem = this.weatherSystem; // Alias
// 🌊 WATER PHYSICS SYSTEM (Temporarily Disabled - HARD RESET)
// this.waterPhysics = new WaterPhysicsSystem(this);
// 💧 WATER RIPPLES SYSTEM (Temporarily Disabled)
// this.waterRipples = new WaterRipplesSystem(this);
// 💡 LIGHTING & SHADOW SYSTEM
console.log('💡 Initializing Lighting & Shadow System...');
@@ -740,7 +808,10 @@ class GameScene extends Phaser.Scene {
// 🌊 WATER PHYSICS SYSTEM (NEW!)
console.log('🌊 Initializing Water Physics System...');
this.waterPhysics = new WaterPhysicsSystem(this);
// 🌊 WATER PHYSICS SYSTEM (Temporarily Disabled)
// console.log('🌊 Initializing Water Physics System...');
// this.waterPhysics = new WaterPhysicsSystem(this);
// 💧 WATER RIPPLES SYSTEM (NEW!)
console.log('💧 Initializing Water Ripples System...');
@@ -2645,6 +2716,8 @@ class GameScene extends Phaser.Scene {
}
});
}
}

View File

@@ -84,470 +84,227 @@ class IntroScene extends Phaser.Scene {
}
create() {
console.log('🎬 IntroScene: Starting 60-SECOND EPIC...');
// Black background
console.log('🎬 IntroScene: Amnesia Start Sequence (Fixed Timing)');
this.cameras.main.setBackgroundColor('#000000');
// 🎵 Start ambient audio
this.startAmbientAudio();
// 1. SHADER INTEGRATION: Gaussian Blur
this.blurFX = null;
if (this.cameras.main.postFX) {
try {
this.blurFX = this.cameras.main.postFX.addBlur(0, 0, 0);
} catch (e) {
console.warn('⚠️ PostFX not supported');
}
}
// 📺 Create VHS overlay effects
this.createVHSEffects();
// Initialize Blur at 20
if (this.blurFX) {
this.blurFX.strength = 20; // High blur
// Setup input for skip
this.setupSkipControls();
// Tween blur to 0 over 6 seconds (Standard Time)
this.tweens.add({
targets: this.blurFX,
strength: 0,
duration: 6000,
ease: 'Power2.easeOut',
onComplete: () => {
this.triggerWakeUp();
}
});
} else {
// Fallback if shaders not supported
this.cameras.main.alpha = 0;
this.tweens.add({
targets: this.cameras.main,
alpha: 1,
duration: 6000,
onComplete: () => this.triggerWakeUp()
});
}
// Enable skip after 5 seconds
this.time.delayedCall(5000, () => {
this.skipEnabled = true;
this.showSkipPrompt();
// 2. FLASHBACK ENGINE (Safe Mode)
// Images: Birthday (0s), Longboard (1.5s), Dreads (3.0s)
this.flashbackSequence([
'intro_birthday_cake',
'intro_otac_longboard',
'intro_ana_barbershop'
]);
// 3. TYPEWRITER LOGIC (Fixed Timing & No Overlap)
// Line 1: 0.5s -> 3.0s
this.time.delayedCall(500, () => {
this.showDialogue('Vse je zamegljeno... Zakaj me vse boli?', 2500);
});
// Start Phase 1
this.playPhase1HappyChildhood();
// Line 2: 4.0s -> End (starts only after Line 1 is cleared)
this.time.delayedCall(4000, () => {
this.showDialogue('Kdo so ti ljudje v moji glavi?', 2000);
});
// Audio atmosphere
this.startAmbientAudio();
}
flashbackSequence(images) {
images.forEach((key, index) => {
// Check if asset exists before scheduling
if (this.textures.exists(key)) {
this.time.delayedCall(index * 1500, () => {
this.triggerFlashback(key);
});
} else {
console.warn(`⚠️ Missing flash asset: ${key} - Skipping visual, keeping timing.`);
}
});
}
triggerFlashback(key) {
// Double check existence
if (!this.textures.exists(key)) return;
const width = this.cameras.main.width;
const height = this.cameras.main.height;
const image = this.add.image(width / 2, height / 2, key);
// Scale to cover most of screen (maintain aspect ratio)
const scale = Math.max(width / image.width, height / image.height) * 0.8;
image.setScale(scale);
image.setAlpha(0);
image.setDepth(10);
image.setBlendMode(Phaser.BlendModes.ADD);
// Flash in and out
this.tweens.add({
targets: image,
alpha: { from: 0, to: 0.15 },
duration: 500,
yoyo: true,
hold: 500,
onComplete: () => {
if (image && image.active) image.destroy();
}
});
// Zoom
this.tweens.add({
targets: image,
scale: scale * 1.1,
duration: 1500
});
}
showDialogue(text, duration) {
// OVERLAP FIX: Destroy previous text immediately
if (this.currentText) {
this.currentText.destroy();
this.currentText = null;
}
const width = this.cameras.main.width;
const height = this.cameras.main.height;
const textObj = this.add.text(width / 2, height - 100, '', {
fontFamily: 'Courier New',
fontSize: '24px',
fill: '#ffffff',
align: 'center',
stroke: '#000000',
strokeThickness: 4
});
textObj.setOrigin(0.5);
textObj.setDepth(100);
this.currentText = textObj; // Track current text
// Typewriter
let charIndex = 0;
const speed = 50;
if (text.length * speed > duration) {
// Speed up if text is too long for duration
speed = Math.floor(duration / text.length);
}
const timer = this.time.addEvent({
delay: speed,
callback: () => {
if (!textObj.active) return;
textObj.text += text[charIndex];
charIndex++;
if (charIndex >= text.length) {
timer.remove();
// Fade out logic
this.time.delayedCall(Math.max(500, duration - (text.length * speed)), () => {
if (textObj.active) {
this.tweens.add({
targets: textObj,
alpha: 0,
duration: 500,
onComplete: () => {
if (textObj.active) textObj.destroy();
if (this.currentText === textObj) this.currentText = null;
}
});
}
});
}
},
repeat: text.length - 1
});
}
startAmbientAudio() {
try {
if (this.cache.audio.exists('noir_ambience')) {
this.ambientAudio = this.sound.add('noir_ambience', {
volume: 0.2,
volume: 0.1, // Start very quiet
loop: true
});
this.ambientAudio.play();
// Fade in audio
this.tweens.add({
targets: this.ambientAudio,
volume: 0.4,
duration: 6000
});
}
} catch (e) {
console.warn('⚠️ Ambient audio not available');
}
}
createVHSEffects() {
const width = this.cameras.main.width;
const height = this.cameras.main.height;
triggerWakeUp() {
console.log('⚡ TRANSITION: Wake Up!');
// VHS Scanlines
this.scanlines = this.add.graphics();
this.scanlines.setDepth(900);
// 4. TRANSITION TO GAMEPLAY
// White Flash
this.cameras.main.flash(1000, 255, 255, 255);
for (let y = 0; y < height; y += 4) {
this.scanlines.fillStyle(0x000000, 0.15);
this.scanlines.fillRect(0, y, width, 2);
}
// VHS Noise overlay
this.vhsNoise = this.add.rectangle(
width / 2,
height / 2,
width,
height,
0xffffff,
0.03
);
this.vhsNoise.setDepth(901);
// Animate noise
// Stop audio
if (this.ambientAudio) {
this.tweens.add({
targets: this.vhsNoise,
alpha: { from: 0.01, to: 0.05 },
duration: 100,
yoyo: true,
repeat: -1
});
}
setupSkipControls() {
this.input.keyboard.on('keydown-X', () => this.skipIntro());
this.input.keyboard.on('keydown-SPACE', () => this.skipIntro());
this.input.on('pointerdown', () => {
if (this.skipEnabled) {
this.skipIntro();
}
});
}
showSkipPrompt() {
if (this.skipPrompt) return;
const width = this.cameras.main.width;
const height = this.cameras.main.height;
this.skipPrompt = this.add.text(
width - 20,
height - 20,
'[Hold X to face reality]',
{
fontFamily: 'Courier New',
fontSize: '14px',
fill: '#00ffff',
stroke: '#000000',
strokeThickness: 2
}
);
this.skipPrompt.setOrigin(1, 1);
this.skipPrompt.setAlpha(0.7);
this.skipPrompt.setDepth(1000);
this.tweens.add({
targets: this.skipPrompt,
alpha: { from: 0.7, to: 1.0 },
duration: 800,
yoyo: true,
repeat: -1
});
}
skipIntro() {
if (!this.skipEnabled) return;
console.log('⏭️ IntroScene: Skipped by user');
// Stop all
if (this.ambientAudio) this.ambientAudio.stop();
if (this.currentVoice) this.currentVoice.stop();
this.tweens.killAll();
this.time.removeAllEvents();
// Fade to GameScene
this.cameras.main.fadeOut(500, 0, 0, 0);
this.cameras.main.once('camerafadeoutcomplete', () => {
this.scene.start('StoryScene'); // Main Menu
});
}
playVoice(key, subtitleText) {
try {
if (this.cache.audio.exists(key)) {
if (this.currentVoice) this.currentVoice.stop();
this.currentVoice = this.sound.add(key, { volume: 0.8 });
this.currentVoice.play();
}
} catch (e) {
console.warn(`⚠️ Voice ${key} not available`);
}
// Show subtitle at bottom
if (subtitleText) {
this.showSubtitle(subtitleText, 2800); // 2.8s duration (slightly less than 3s shot)
}
}
showSubtitle(text, duration = 3000) {
// Remove previous subtitle
if (this.currentText) {
this.currentText.destroy();
}
const width = this.cameras.main.width;
const height = this.cameras.main.height;
// Create subtitle at bottom
this.currentText = this.add.text(
width / 2,
height - 100, // 100px from bottom
text,
{
fontFamily: 'Courier New',
fontSize: '20px',
fill: '#ffffff',
stroke: '#000000',
strokeThickness: 3,
shadow: {
offsetX: 2,
offsetY: 2,
color: '#00ffff',
blur: 8,
stroke: false,
fill: true
},
align: 'center',
wordWrap: { width: width - 100 }
}
);
this.currentText.setOrigin(0.5);
this.currentText.setAlpha(0);
this.currentText.setDepth(950); // Below VHS but above Polaroid
// Fade in
this.tweens.add({
targets: this.currentText,
alpha: 1,
targets: this.ambientAudio,
volume: 0,
duration: 500,
ease: 'Power2.easeOut'
});
// Fade out before end
this.time.delayedCall(duration - 300, () => {
if (this.currentText) {
this.tweens.add({
targets: this.currentText,
alpha: 0,
duration: 300,
onComplete: () => {
if (this.currentText) this.currentText.destroy();
if (this.ambientAudio && this.ambientAudio.stop) {
this.ambientAudio.stop();
}
});
}
});
}
// ═══════════════════════════════════════════════════════════
// PHASE 1: HAPPY MEMORIES (0-15s) - REDESIGNED!
// ═══════════════════════════════════════════════════════════
playPhase1HappyChildhood() {
console.log('🎬 Phase 1: Happy Memories (0-15s) - NEW SEQUENCE');
this.currentPhase = 1;
// Shot 1 (0-2.5s): Kai + Dad Longboard
this.showShot('intro_otac_longboard', 0, 2500, { warm: true });
this.time.delayedCall(100, () => this.playVoice('kai_01', "Dad and I. Before everything changed."));
// Shot 2 (2.5-5s): Barbershop - Him (dreads) + Her (coloring)
this.showShot('intro_ana_barbershop', 2500, 5000, { warm: true });
this.time.delayedCall(2600, () => this.playVoice('ana_01', "Getting ready. We always did things together."));
// Shot 3 (5-7.5s): Birthday Cake - "HERE WE WERE STILL HAPPY"
this.showShot('intro_birthday_cake', 5000, 7500, { warm: true });
this.time.delayedCall(5100, () => this.playVoice('kai_02', "Here we were still happy. Still a family."));
// Shot 4 (7.5-10s): Family Portrait
this.showShot('intro_family_portrait', 7500, 10000, { warm: true });
this.time.delayedCall(7600, () => this.playVoice('ana_02', "All of us. Together. Perfect."));
// Shot 5 (10-12.5s): Kai + Ana Holding Hands as Kids
this.showShot('intro_twins_childhood', 10000, 12500, { warm: true });
this.time.delayedCall(10100, () => this.playVoice('kai_03', "We were always two. Inseparable."));
// Shot 6 (12.5-15s): Kai's Bedroom
this.showShot('intro_bedroom', 12500, 15000, { warm: true });
this.time.delayedCall(12600, () => this.playVoice('ana_03', "Our room. Our sanctuary."));
// Transition to Phase 2
this.time.delayedCall(15000, () => this.playPhase2TheVirus());
// Switch Scene
this.time.delayedCall(1000, () => {
// Set flag
if (window.gameState && window.gameState.story) {
window.gameState.story.isAmnesiaActive = true;
}
// ═══════════════════════════════════════════════════════════
// PHASE 2: THE VIRUS (15-30s)
// ═══════════════════════════════════════════════════════════
playPhase2TheVirus() {
console.log('🎬 Phase 2: The Virus (15-30s)');
this.currentPhase = 2;
// Shot 7 (15-17.5s): Virus
this.showShot('intro_virus', 15000, 17500, { toxic: true, glitch: true });
this.time.delayedCall(15100, () => this.playVoice('kai_04', "Then came X-Noir. The virus."));
// Shot 8 (17.5-20s): Chaos
this.showShot('intro_chaos', 17500, 20000, { red: true, glitch: true });
this.time.delayedCall(17600, () => this.playVoice('ana_04', "Everyone changed. Streets burned."));
this.cameras.main.shake(2500, 0.005);
// Shot 9 (20-22.5s): Zombies
this.showShot('intro_zombies', 20000, 22500, { red: true, strobe: true });
this.time.delayedCall(20100, () => this.playVoice('kai_05', "Friends became zombies."));
// Shot 10 (22.5-25s): Parents Ghosts
this.showShot('intro_parents_ghosts', 22500, 25000, { fadeIn: true });
this.time.delayedCall(22600, () => this.playVoice('ana_05', "Our parents fought... and lost."));
// Shot 11 (25-30s): Ana Taken
this.showShot('intro_ana_taken', 25000, 30000, { red: true });
this.time.delayedCall(25100, () => this.playVoice('ana_06', "KAI! DON'T FORGET ME!"));
// Transition to Phase 3
this.time.delayedCall(30000, () => this.playPhase3TheAmnesia());
}
// ═══════════════════════════════════════════════════════════
// PHASE 3: AMNESIA & ANA MEMORY (30-60s) - NO AGING SPOILERS!
// ═══════════════════════════════════════════════════════════
playPhase3TheAmnesia() {
console.log('🎬 Phase 3: Amnesia & Ana Memory (30-60s)');
this.currentPhase = 3;
// Shot 12 (30-35s): BLACK SCREEN - "I have no memory"
const width = this.cameras.main.width;
const height = this.cameras.main.height;
const blackScreen = this.add.rectangle(width / 2, height / 2, width, height, 0x000000);
blackScreen.setAlpha(0);
blackScreen.setDepth(50);
this.tweens.add({
targets: blackScreen,
alpha: 1,
duration: 1000
});
this.time.delayedCall(30500, () => this.playVoice('kai_06', "I have no memory. Everything is... gone."));
this.time.delayedCall(33000, () => this.playVoice('kai_07', "They say I'm fourteen. But I don't remember... anything."));
// Shot 13 (35-40s): Kai Alone in Basement
this.time.delayedCall(35000, () => {
this.tweens.add({
targets: blackScreen,
alpha: 0,
duration: 1000,
onComplete: () => blackScreen.destroy()
});
});
this.showShot('intro_kai_alone', 35000, 40000, { fadeIn: true });
this.time.delayedCall(35500, () => this.playVoice('kai_08', "Alone. In darkness. With only... this."));
// Shot 14 (40-50s): Ana Memory - LAST TIME THEY SAW EACH OTHER
this.showShot('intro_ana_memory', 40000, 50000, { fadeIn: true });
this.time.delayedCall(40500, () => this.playVoice('ana_07', "Her face. The only thing I remember."));
this.time.delayedCall(43500, () => this.playVoice('kai_09', "Ana. My sister. My twin. The last thing I saw... before everything went dark."));
// Shot 15 (50-55s): Gronk Arrival
this.showShot('intro_gronk', 50000, 55000, { fadeIn: true });
this.time.delayedCall(50500, () => this.playVoice('gronk_01', "Finally awake, old man. Your mission awaits."));
// Shot 16 (55-60s): Ana Photo + FINAL DETERMINATION
this.showShot('intro_ana_memory', 55000, 60000, { fadeIn: true });
this.time.delayedCall(55500, () => this.playVoice('kai_11', "I must find her."));
this.time.delayedCall(57500, () => this.playVoice('kai_12', "...even if it takes my entire life."));
// Transition to Main Menu
this.time.delayedCall(60000, () => {
console.log('🎬 IntroScene: EPIC COMPLETE! Starting menu...');
if (this.ambientAudio) this.ambientAudio.stop();
this.cameras.main.fadeOut(1000, 0, 0, 0);
this.cameras.main.once('camerafadeoutcomplete', () => {
this.scene.start('StoryScene'); // Main Menu
});
this.scene.start('GameScene');
});
}
// Phase 4 removed - integrated into Phase 3!
showShot(imageKey, startTime, endTime, options = {}) {
const width = this.cameras.main.width;
const height = this.cameras.main.height;
const duration = endTime - startTime;
this.time.delayedCall(startTime, () => {
// CROSSFADE: Store old reference for simultaneous fade
const oldPolaroid = this.currentPolaroid;
// (Old will fade out WHILE new fades in - see below)
// Create photo image (65% of screen)
const photo = this.add.image(width / 2, height / 2 - 30, imageKey);
photo.setAlpha(0);
photo.setDepth(20);
// Scale to 65% of screen size
const targetSize = Math.min(width, height) * 0.65;
const photoScale = targetSize / Math.max(photo.width, photo.height);
photo.setScale(photoScale);
// Create Polaroid white frame
const frameWidth = photo.displayWidth + 40;
const frameHeight = photo.displayHeight + 80;
const frame = this.add.graphics();
frame.setDepth(19);
frame.setAlpha(0);
// Dirty white Polaroid background
frame.fillStyle(0xf5f5dc, 1);
frame.fillRect(
(width - frameWidth) / 2,
(height - frameHeight) / 2 - 30,
frameWidth,
frameHeight
);
// Add dirt/grain texture
for (let i = 0; i < 50; i++) {
const x = (width - frameWidth) / 2 + Math.random() * frameWidth;
const y = (height - frameHeight) / 2 - 30 + Math.random() * frameHeight;
frame.fillStyle(0xccccbb, 0.3);
frame.fillCircle(x, y, 1);
}
this.currentPolaroid = { photo, frame };
// 🌊 FLOATING ANIMATION
this.tweens.add({
targets: [photo, frame],
y: '-=5',
duration: 2000,
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut'
});
// Apply visual effects
if (options.warm) {
photo.setTint(0xffddaa);
}
if (options.red) {
photo.setTint(0xff6666);
}
if (options.toxic) {
photo.setTint(0x66ff66);
}
// CROSSFADE: NEW fades IN (800ms)
this.tweens.add({
targets: [photo, frame],
alpha: 1,
duration: 800,
ease: 'Power2.easeOut'
});
// SIMULTANEOUSLY: OLD fades OUT (same 800ms)
if (oldPolaroid) {
this.tweens.add({
targets: [oldPolaroid.photo, oldPolaroid.frame],
alpha: 0,
duration: 800, // Same duration = perfect crossfade!
ease: 'Power2.easeIn',
onComplete: () => {
oldPolaroid.frame.destroy();
oldPolaroid.photo.destroy();
}
});
}
// OLD GLITCH-OUT removed - crossfade handles transitions now!
if (options.glitch) {
this.tweens.add({
targets: [photo, frame],
x: { from: width / 2 - 5, to: width / 2 + 5 },
duration: 100,
repeat: duration / 100,
yoyo: true
});
}
if (options.strobe) {
this.tweens.add({
targets: photo,
alpha: { from: 0.7, to: 1.0 },
duration: 150,
repeat: duration / 150,
yoyo: true
});
}
});
}
shutdown() {
if (this.ambientAudio) this.ambientAudio.stop();
if (this.currentVoice) this.currentVoice.stop();
if (this.skipPrompt) this.skipPrompt.destroy();
if (this.currentPolaroid) {
this.currentPolaroid.frame.destroy();
this.currentPolaroid.photo.destroy();
}
this.tweens.killAll();
this.time.removeAllEvents();
}
}

View File

@@ -9,11 +9,25 @@ class PreloadScene extends Phaser.Scene {
this.createLoadingBar();
// 🛠️ Asset Fix: Create placeholder for missing particles
// This prevents crash in WaterPhysicsSystem if 'particle_white' is used before load
if (!this.textures.exists('particle_white')) {
const g = this.make.graphics({ x: 0, y: 0, add: false });
g.fillStyle(0xffffff, 1);
g.fillCircle(4, 4, 4);
g.generateTexture('particle_white', 8, 8);
}
// ═══════════════════════════════════════════════════════════════
// 🎵 AUDIO PRELOAD - Cinematic Voices
// ═══════════════════════════════════════════════════════════════
this.preloadAudio();
// ═══════════════════════════════════════════════════════════════
// 🌍 LOCALIZATION
// ═══════════════════════════════════════════════════════════════
this.load.json('localization', 'assets/localization.json');
// ═══════════════════════════════════════════════════════════════
// 🎨 CHARACTER SPRITES - Demo Characters
// ═══════════════════════════════════════════════════════════════
@@ -29,23 +43,50 @@ class PreloadScene extends Phaser.Scene {
}
preloadCharacterSprites() {
console.log('🎨 Preloading character sprites...');
console.log('🎨 Preloading ALL ASSETS from AssetManifest...');
const basePath = 'assets/references/main_characters/';
// Dynamic import logic (requires module system, but we'll use direct reference if global or shim)
// Since we are in Setup phase, we assume AssetManifest is loaded via script tag or bundler
// Kai sprites
this.loadImageSafe('kai_idle', basePath + 'kai/animations/idle/kai_idle_frame1.png');
this.loadImageSafe('kai_walk', basePath + 'kai/animations/walk/kai_walk_frame1.png');
// Check if AssetManifest exists globally or we need to rely on the file we created
// For this environment, we'll manually iterate the data structure if it's not imported.
// But since we just created src/AssetManifest.js, let's try to assume it's available.
// Ana sprites
this.loadImageSafe('ana_idle', basePath + 'ana/animations/idle/ana_idle_frame1.png');
this.loadImageSafe('ana_walk', basePath + 'ana/animations/walk/ana_walk_frame1.png');
// NOTE: In standard Phaser/Webpack, we would import { AssetManifest } from '../AssetManifest'.
// Here we will inject logic to load it. For now, let's assume we can fetch it or it's hardcoded.
// Susi (companion)
this.loadImageSafe('susi_idle', 'assets/references/companions/susi/animations/idle/susi_idle_frame1.png');
this.loadImageSafe('susi_run', 'assets/references/companions/susi/animations/run/susi_run_frame1.png');
// Load Manifest Images
// Since we are using script tags in index.html, window.AssetManifest is already available!
if (window.AssetManifest) {
const manifest = window.AssetManifest;
console.log('🎨 Character sprites queued');
console.log(`📦 Loading Asset Manifest (Phased)...`);
// Iterate over phases (farm, basement_mine, etc.)
if (manifest.phases) {
Object.keys(manifest.phases).forEach(phaseName => {
console.log(`Phase: ${phaseName} - ${manifest.phases[phaseName].length} items`);
manifest.phases[phaseName].forEach(img => {
this.loadImageSafe(img.key, img.path);
});
});
}
// Iterate over spritesheets
if (manifest.spritesheets) {
manifest.spritesheets.forEach(sheet => {
this.load.spritesheet(sheet.key, sheet.path, sheet.frameConfig);
});
}
console.log('✅ AssetManifest Queue Complete');
// 🗺️ LOAD MAP
this.load.tilemapTiledJSON('NovaFarma', 'assets/maps/NovaFarma.json');
console.log('🗺️ Preloading NovaFarma.json map...');
} else {
console.error('❌ Critical: window.AssetManifest not found! Check index.html imports.');
}
}
loadImageSafe(key, path) {
@@ -474,6 +515,23 @@ class PreloadScene extends Phaser.Scene {
zombie.destroy();
bg.destroy(); // Ensure bg is destroyed here
console.log('✅ PreloadScene: Assets loaded!');
// 🌍 INITIALIZE LOCALIZATION
if (!window.i18n) {
try {
window.i18n = new LocalizationSystem();
const locData = this.cache.json.get('localization');
if (locData) {
window.i18n.setExternalData(locData);
console.log('🌍 Localization initialized with external data');
} else {
console.warn('⚠️ Localization JSON not found in cache');
}
} catch (e) {
console.error('❌ Localization init failed:', e);
}
}
window.gameState.currentScene = 'PreloadScene';
// ✅ Starting INTRO SEQUENCE (NEW! Jan 10, 2026)

View File

@@ -22,12 +22,11 @@ class StoryScene extends Phaser.Scene {
graphics.fillGradientStyle(0x1a0000, 0x1a0000, 0x000000, 0x000000, 1);
graphics.fillRect(0, 0, width, height);
// 🌫️ NOIR FOG EFFECT
// 🌫️ NOIR FOG EFFECT (Fixed per instructions)
this.createNoirFog(width, height);
// 🎵 NOIR BACKGROUND MUSIC (disabled temporarily)
// this.playNoirMusic();
console.log('🔇 Music disabled temporarily');
// 🎵 NOIR BACKGROUND MUSIC
this.playNoirMusic();
// MAIN TITLE (horizontal, top center)
@@ -113,16 +112,16 @@ class StoryScene extends Phaser.Scene {
graphics.generateTexture('fogParticle', 64, 64);
graphics.destroy();
// Fog particle emitter - HUGE & SUBTLE (no circles!)
// Fog particle emitter - FIXED PER USER REQUEST: Huge, slow, mist-like
this.add.particles(0, 0, 'fogParticle', {
x: { min: 0, max: width },
y: { min: 0, max: height },
scale: { start: 15, end: 20 }, // HUGE particles!
alpha: { start: 0.02, end: 0 }, // VERY subtle!
lifespan: 8000,
speed: { min: 5, max: 20 },
frequency: 300,
blendMode: 'NORMAL'
scale: { start: 15, end: 20 }, // HUGE particles! (15-20x)
alpha: { start: 0.02, end: 0 }, // VERY subtle! (0.02)
lifespan: 15000, // Slower (longer life)
speed: { min: 2, max: 10 }, // Slow movement
frequency: 500,
blendMode: 'ADD'
});
// NOIR VIGNETTE (dark edges)
@@ -141,57 +140,60 @@ class StoryScene extends Phaser.Scene {
playNoirMusic() {
// Play forest evening ambience (noir atmosphere)
const key = 'forest_ambient';
try {
if (this.sound.get('forest_ambient')) {
const music = this.sound.add('forest_ambient', {
// STRICT CHECK: Only play if audio exists in cache
if (this.cache.audio.exists(key)) {
// Prevent duplicate playback
// Get all playing sounds to check if already playing
let isPlaying = false;
if (this.sound.sounds) {
this.sound.sounds.forEach(s => {
if (s.key === key && s.isPlaying) isPlaying = true;
});
}
if (!isPlaying) {
this.sound.play(key, {
volume: 0.3,
loop: true
});
music.play();
console.log('🎵 Noir atmosphere music playing at 30% volume');
} else {
console.warn('⚠️ forest_ambient not loaded yet - trying alternative');
// Try to load and play immediately
this.load.audio('forest_ambient', 'assets/audio/music/forest_ambient.mp3');
this.load.once('complete', () => {
try {
const music = this.sound.add('forest_ambient', { volume: 0.3, loop: true });
music.play();
console.log('🎵 Loaded and playing forest_ambient');
} catch (e) {
console.error('❌ Failed to play music:', e.message);
}
});
this.load.start();
} else {
console.warn(`⚠️ Audio key not found: ${key} - Skipping to prevent crash.`);
}
} catch (error) {
console.error('❌ Audio error (non-critical):', error.message);
console.log('✅ Game continues without music');
console.error('❌ Audio error (handled):', error.message);
}
}
createMainMenu(width, height) {
// Get localized button texts
// Ensure i18n is initialized
if (!window.i18n) window.i18n = new LocalizationSystem();
const i18n = window.i18n;
// Use keys from localization.json (menu.new_game etc.)
const buttons = [
{
label: i18n ? i18n.t('new_game', '▶ NEW GAME') : '▶ NEW GAME',
label: i18n.t('new_game', '▶ NEW GAME'),
color: '#8fbc8f',
action: () => this.startNewGame()
},
{
label: i18n ? i18n.t('load_game', '📁 LOAD GAME') : '📁 LOAD GAME',
label: i18n.t('load_game', '📁 LOAD GAME'),
color: '#87ceeb',
action: () => this.loadGame()
},
{
label: i18n ? i18n.t('settings', '⚙️ SETTINGS') : '⚙️ SETTINGS',
label: i18n.t('settings', '⚙️ SETTINGS'),
color: '#daa520',
action: () => this.showSettings()
},
{
label: i18n ? i18n.t('exit', '❌ EXIT') : '❌ EXIT',
label: i18n.t('exit', '❌ EXIT'),
color: '#cd5c5c',
action: () => this.exitGame()
}
@@ -449,8 +451,8 @@ class StoryScene extends Phaser.Scene {
startNewGame() {
console.log('🎮 Starting New Game...');
console.log('🎥 Launching ULTIMATE Prologue (100% Polished!)...');
this.scene.start('UltimatePrologueScene'); // ✅ ULTIMATE INTRO!
console.log('🎥 Launching Amnesia Start Sequence...');
this.scene.start('IntroScene'); // ✅ AMNESIA START
}
loadGame() {

View File

@@ -357,7 +357,7 @@ class UltimatePrologueScene extends Phaser.Scene {
this.showQuestBrief();
// Fade to game
this.time.delayedCall(4000, () => this.fadeToGame());
this.time.delayedCall(4000, () => this.exitPrologue());
});
}
@@ -443,10 +443,10 @@ class UltimatePrologueScene extends Phaser.Scene {
skipToGame() {
console.log('⏭️ Skipping to game...');
this.fadeToGame();
this.exitPrologue();
}
fadeToGame() {
exitPrologue() {
console.log('🎬 Intro complete! Starting game...');
// Fade out music (if exists)

View File

@@ -0,0 +1,138 @@
/**
* AMNESIA EFFECT PIPELINE & MANAGER
* Handles the visual distortion for memory loss sequences.
*
* USAGE:
* 1. Initialize in Scene: this.amnesia = new AmnesiaEffect(this);
* 2. Start effect: this.amnesia.start();
* 3. Fade out: this.amnesia.fadeOut(2000);
*/
class AmnesiaEffect {
constructor(scene) {
this.scene = scene;
this.pipeline = null;
this.vignette = null;
this.blurFX = null;
this.isActive = false;
// Register custom pipeline if not exists
if (!this.scene.renderer.pipelines.get('AmnesiaPipeline')) {
this.registerPipeline();
}
}
registerPipeline() {
// Simple heavy vignette + desaturation pipeline could go here
// For now, we will use Phaser's built-in PostFX for stability
// effectively wrapping them in this manager.
console.log('🌀 AmnesiaEffect: Manager initialized');
}
start(intensity = 1.0) {
if (this.isActive) return;
this.isActive = true;
const width = this.scene.cameras.main.width;
const height = this.scene.cameras.main.height;
// 1. BLUR CAMERA
// Note: PostFX requires Phaser 3.60+
if (this.scene.cameras.main.postFX) {
this.blurFX = this.scene.cameras.main.postFX.addBlur(2, 2, 2); // strength=2, quality=2
}
// 2. VIGNETTE OVERLAY (Heavy dark edges)
// We use a radial gradient texture or graphics because Phaser FX vignette can be subtle
// We want aggressive darkness for "tunnel vision"
this.vignette = this.scene.add.graphics();
this.vignette.setDepth(9999);
this.vignette.setScrollFactor(0);
this.vignette.fillStyle(0x000000, 1);
this.vignette.fillRect(0, 0, width, height);
// Create a mask to see through the center (tunnel vision)
const maskShape = this.scene.make.graphics();
maskShape.fillStyle(0xffffff);
maskShape.fillCircle(width / 2, height / 2, height * 0.4);
const mask = maskShape.createGeometryMask();
mask.setInvertAlpha(true);
this.vignette.setMask(mask);
// Pulse animation for the vignette (heartbeat effect)
this.scene.tweens.add({
targets: maskShape,
scale: 0.9,
duration: 1000,
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut'
});
// 3. COLOR TINT (Cold/Confused)
this.scene.cameras.main.setTint(0xcccccc); // Greyish
console.log('🌀 Amnesia Effect ACTIVATED');
}
fadeOut(duration = 2000) {
if (!this.isActive) return;
console.log(`🌀 Fading out Amnesia Effect (${duration}ms)`);
// Fade out vignette
if (this.vignette) {
this.scene.tweens.add({
targets: this.vignette,
alpha: 0,
duration: duration,
onComplete: () => {
this.vignette.destroy();
this.vignette = null;
}
});
}
// Fade out blur
if (this.blurFX) {
this.scene.tweens.add({
targets: this.blurFX,
strength: 0,
duration: duration,
onComplete: () => {
if (this.scene.cameras.main.postFX) {
this.scene.cameras.main.postFX.remove(this.blurFX);
}
this.blurFX = null;
}
});
}
// Restore Color
this.scene.tweens.add({
targets: this.scene.cameras.main,
zoom: 1, // Reset any zoom
duration: duration,
onUpdate: (tween) => {
const val = Math.floor(204 + (51 * tween.progress)); // 0xCC (204) to 0xFF (255)
const color = Phaser.Display.Color.GetColor(val, val, val);
this.scene.cameras.main.setTint(color);
},
onComplete: () => {
this.scene.cameras.main.clearTint();
this.isActive = false;
}
});
}
pulse(strength = 1.0) {
// Sudden headache flash
this.scene.cameras.main.shake(200, 0.005 * strength);
this.scene.cameras.main.flash(200, 255, 0, 0); // Red flash of pain
}
}
// Make globally available or export based on project structure
window.AmnesiaEffect = AmnesiaEffect;

View File

@@ -434,6 +434,43 @@ class LocalizationSystem {
};
return names[code] || code;
}
/**
* INJECT EXTERNAL JSON DATA (loaded via Phaser)
*/
setExternalData(data) {
try {
// Merge intro texts into translations
for (const lang in data) {
if (!this.translations[lang]) {
this.translations[lang] = {};
}
// Add intro polaroid texts
if (data[lang].intro_polaroids) {
this.translations[lang].intro_polaroids = data[lang].intro_polaroids;
}
// Add menu texts
if (data[lang].menu) {
Object.assign(this.translations[lang], data[lang].menu);
}
// Add title/subtitle
if (data[lang].game_title) {
this.translations[lang].game_title = data[lang].game_title;
}
if (data[lang].subtitle) {
this.translations[lang].subtitle = data[lang].subtitle;
}
}
console.log('✅ Localization data injected successfully');
return true;
} catch (error) {
console.warn('⚠️ Could not inject localization data:', error);
return false;
}
}
}
// Global instance

View File

@@ -12,13 +12,25 @@ class SoundManager {
playSFX(key) {
if (this.isMuted) return;
if (this.scene.sound.get(key)) {
// SAFE CHECK: Check cache instead of active instances
if (this.scene.cache.audio.exists(key)) {
try {
this.scene.sound.play(key, { volume: this.sfxVolume });
} else if (key === 'chop' && this.scene.sound.get('wood_chop')) {
} catch (e) {
console.warn(`🔊 Failed to play SFX ${key}:`, e);
// Fallback to beep if playback fails
this.playFallbackBeep(key);
}
} else if (key === 'chop' && this.scene.cache.audio.exists('wood_chop')) {
// Priority for real wood chop sound
this.scene.sound.play('wood_chop', { volume: this.sfxVolume });
} else {
// Enhanced placeholder beeps
this.playFallbackBeep(key);
}
}
playFallbackBeep(key) {
if (key === 'chop') {
this.beepChop();
} else if (key === 'pickup') {
@@ -33,7 +45,6 @@ class SoundManager {
this.beepDig();
}
}
}
playMusic(key, loop = true) {
if (this.isMuted) return;
@@ -43,9 +54,15 @@ class SoundManager {
this.currentMusic.stop();
}
if (this.scene.sound.get(key)) {
if (this.scene.cache.audio.exists(key)) {
try {
this.currentMusic = this.scene.sound.add(key, { volume: this.musicVolume, loop: loop });
this.currentMusic.play();
} catch (e) {
console.warn(`🎵 Failed to play music ${key}:`, e);
}
} else {
console.warn(`🎵 Music key not found: ${key}`);
}
}
@@ -259,9 +276,15 @@ class SoundManager {
playAmbient(key, loop = true) {
if (this.isMuted) return;
if (this.currentAmbient) this.currentAmbient.stop();
if (!this.scene.sound.get(key)) return;
if (!this.scene.cache.audio.exists(key)) return;
try {
this.currentAmbient = this.scene.sound.add(key, { volume: this.sfxVolume * 0.5, loop: loop });
this.currentAmbient.play();
} catch (e) {
console.warn(`🍃 Failed to play ambient ${key}:`, e);
}
}
stopAmbient() {

View File

@@ -11,7 +11,7 @@
* Style 32 Dark-Chibi Noir compatible
*/
export default class WaterPhysicsSystem {
class WaterPhysicsSystem {
constructor(scene) {
this.scene = scene;

49
test_log.txt Normal file
View File

@@ -0,0 +1,49 @@
[2026-01-11T09:36:17.922Z] CLICK: <CANVAS> "CANVAS" at (552, 381)
[2026-01-11T09:36:24.484Z] CLICK: <CANVAS> "CANVAS" at (585, 430)
[2026-01-11T09:45:54.140Z] CLICK: <CANVAS> "CANVAS" at (762, 479)
[2026-01-11T10:06:54.071Z] CLICK: <CANVAS> "CANVAS" at (792, 319)
[2026-01-11T10:06:56.625Z] CLICK: <CANVAS> "CANVAS" at (709, 440)
[2026-01-11T10:06:58.541Z] CLICK: <CANVAS> "CANVAS" at (713, 437)
[2026-01-11T10:09:42.997Z] CLICK: <CANVAS> "CANVAS" at (591, 319)
[2026-01-11T10:09:45.124Z] CLICK: <CANVAS> "CANVAS" at (571, 396)
[2026-01-11T10:11:04.857Z] CLICK: <CANVAS> "CANVAS" at (542, 223)
[2026-01-11T10:23:29.475Z] ERROR: Uncaught SyntaxError: Cannot use import statement outside a module at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:2
[2026-01-11T10:23:34.683Z] CLICK: <DIV> "DIV" at (612, 395)
[2026-01-11T10:27:13.742Z] CLICK: <BUTTON> "BUTTON" at (370, 454)
[2026-01-11T10:27:13.976Z] ERROR: Uncaught SyntaxError: Unexpected token ':' at file:///Users/davidkotnik/repos/novafarma/src/AssetManifest.js:47
[2026-01-11T10:27:13.978Z] ERROR: Uncaught SyntaxError: Unexpected token 'export' at file:///Users/davidkotnik/repos/novafarma/src/systems/WaterPhysicsSystem.js:14
[2026-01-11T10:27:13.982Z] ERROR: Uncaught SyntaxError: Unexpected token ':' at file:///Users/davidkotnik/repos/novafarma/src/game.js:72
[2026-01-11T10:27:38.122Z] CLICK: <DIV> "game-container" at (454, 161)
[2026-01-11T10:29:41.831Z] CLICK: <DIV> "game-container" at (536, 442)
[2026-01-11T10:29:46.858Z] CLICK: <CANVAS> "CANVAS" at (465, 315)
[2026-01-11T10:29:48.477Z] CLICK: <CANVAS> "CANVAS" at (481, 320)
[2026-01-11T10:38:06.856Z] CLICK: <CANVAS> "CANVAS" at (422, 398)
[2026-01-11T10:38:27.822Z] CLICK: <CANVAS> "CANVAS" at (376, 393)
[2026-01-11T10:38:30.637Z] CLICK: <CANVAS> "CANVAS" at (377, 391)
[2026-01-11T10:38:31.654Z] CLICK: <CANVAS> "CANVAS" at (376, 389)
[2026-01-11T10:45:07.499Z] CLICK: <CANVAS> "CANVAS" at (511, 353)
[2026-01-11T10:45:08.807Z] ERROR: Uncaught SyntaxError: Unexpected token '{' at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:2677
[2026-01-11T10:45:10.274Z] CLICK: <BUTTON> "BUTTON" at (344, 462)
[2026-01-11T10:45:10.518Z] ERROR: Uncaught SyntaxError: Unexpected token '{' at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:2677
[2026-01-11T10:45:12.934Z] CLICK: <DIV> "DIV" at (611, 386)
[2026-01-11T10:46:38.657Z] CLICK: <BUTTON> "BUTTON" at (378, 456)
[2026-01-11T10:46:40.454Z] CLICK: <CANVAS> "CANVAS" at (386, 406)
[2026-01-11T10:46:48.337Z] CLICK: <CANVAS> "CANVAS" at (828, 243)
[2026-01-11T10:46:51.051Z] CLICK: <BUTTON> "BUTTON" at (641, 530)
[2026-01-11T10:46:52.577Z] CLICK: <CANVAS> "CANVAS" at (706, 441)
[2026-01-11T10:48:05.683Z] CLICK: <CANVAS> "CANVAS" at (630, 335)
[2026-01-11T10:48:15.304Z] CLICK: <DIV> "error-overlay" at (908, 515)
[2026-01-11T10:49:25.426Z] CLICK: <BUTTON> "BUTTON" at (476, 518)
[2026-01-11T10:49:31.863Z] CLICK: <CANVAS> "CANVAS" at (743, 392)
[2026-01-11T10:49:33.336Z] CLICK: <CANVAS> "CANVAS" at (746, 390)
[2026-01-11T16:55:28.141Z] CLICK: <CANVAS> "CANVAS" at (763, 468)
[2026-01-11T16:55:28.606Z] CLICK: <CANVAS> "CANVAS" at (763, 468)
[2026-01-11T16:55:28.990Z] CLICK: <CANVAS> "CANVAS" at (763, 468)
[2026-01-11T16:55:32.590Z] CLICK: <CANVAS> "CANVAS" at (763, 464)
[2026-01-11T16:55:32.890Z] CLICK: <CANVAS> "CANVAS" at (763, 464)
[2026-01-11T19:00:26.209Z] CLICK: <CANVAS> "CANVAS" at (444, 194)
[2026-01-11T19:00:26.691Z] CLICK: <CANVAS> "CANVAS" at (438, 191)
[2026-01-11T19:00:26.984Z] CLICK: <CANVAS> "CANVAS" at (340, 174)
[2026-01-11T19:00:33.351Z] CLICK: <CANVAS> "CANVAS" at (528, 338)
[2026-01-11T19:00:36.310Z] CLICK: <CANVAS> "CANVAS" at (532, 265)
[2026-01-11T19:00:43.093Z] CLICK: <CANVAS> "CANVAS" at (195, 60)

79
tools/create_tmx.js Normal file
View File

@@ -0,0 +1,79 @@
const fs = require('fs');
const path = require('path');
const TILED_DIR = path.join(__dirname, '../assets/tiled');
const ASSETS_ROOT = path.join(__dirname, '../assets');
// Configuration
const TMX_FILENAME = 'Faza1_Nova.tmx';
const TSX_FILENAME = 'Buildings.tsx';
const MAP_WIDTH = 80;
const MAP_HEIGHT = 80;
// Gather all images
const imageFiles = [];
const sourceDirs = ['buildings', 'terrain', 'props'];
let tileIdCounter = 0;
let tilesXml = '';
sourceDirs.forEach(dirName => {
const fullPath = path.join(ASSETS_ROOT, dirName);
if (fs.existsSync(fullPath)) {
const files = fs.readdirSync(fullPath);
files.forEach(file => {
if (file.toLowerCase().endsWith('.png')) {
// Determine relative path from assets/tiled/ to assets/dir/file
// assets/tiled -> assets/dir = ../dir
const relativePath = `../${dirName}/${file}`;
tilesXml += ` <tile id="${tileIdCounter}">\n`;
tilesXml += ` <image source="${relativePath}"/>\n`; // Let Tiled detect size
tilesXml += ` </tile>\n`;
tileIdCounter++;
}
});
}
});
// 1. Generate TSX (Tileset)
const tsxContent = `<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.10" tiledversion="1.11.0" name="Buildings" tilewidth="256" tileheight="256" tilecount="${tileIdCounter}" columns="0">
<grid orientation="orthogonal" width="1" height="1"/>
${tilesXml}
</tileset>`;
fs.writeFileSync(path.join(TILED_DIR, TSX_FILENAME), tsxContent);
console.log(`✅ Created tileset: ${TSX_FILENAME} with ${tileIdCounter} tiles.`);
// 2. Generate TMX (Map)
// Create empty CSV data (all zeros)
const csvData = new Array(MAP_WIDTH * MAP_HEIGHT).fill(0).join(',');
const tmxContent = `<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="${MAP_WIDTH}" height="${MAP_HEIGHT}" tilewidth="48" tileheight="48" infinite="0" nextlayerid="5" nextobjectid="1">
<properties>
<property name="music" value="farm_theme"/>
</properties>
<tileset firstgid="1" source="${TSX_FILENAME}"/>
<layer id="1" name="Ground" width="${MAP_WIDTH}" height="${MAP_HEIGHT}">
<data encoding="csv">
${csvData}
</data>
</layer>
<layer id="2" name="Objects" width="${MAP_WIDTH}" height="${MAP_HEIGHT}">
<data encoding="csv">
${csvData}
</data>
</layer>
<layer id="3" name="Collision" width="${MAP_WIDTH}" height="${MAP_HEIGHT}" opacity="0.5">
<data encoding="csv">
${csvData}
</data>
</layer>
<objectgroup id="4" name="Audio_Zones"/>
</map>`;
fs.writeFileSync(path.join(TILED_DIR, TMX_FILENAME), tmxContent);
console.log(`✅ Created map: ${TMX_FILENAME} (${MAP_WIDTH}x${MAP_HEIGHT}) linked to ${TSX_FILENAME}.`);

View File

@@ -0,0 +1,85 @@
const fs = require('fs');
const path = require('path');
const ASSETS_DIR = path.join(__dirname, '../assets');
const OUTPUT_FILE = path.join(__dirname, '../src/AssetManifest.js');
const CATEGORY_MAP = {
'buildings': 'farm',
'crops': 'farm',
'grounds': 'farm',
'props': 'farm',
'terrain': 'farm',
'characters': 'common',
'ui': 'common',
'vfx': 'common',
'images': 'common',
'intro_assets': 'common',
'sprites': 'common', // Treat as regular images for now unless frame config known
'slike 🟢': 'common'
};
const manifest = {
phases: {
farm: [],
basement_mine: [],
common: []
},
spritesheets: []
};
function scanDir(dir, category) {
if (!fs.existsSync(dir)) return;
const files = fs.readdirSync(dir);
files.forEach(file => {
const fullPath = path.join(dir, file);
const stat = fs.statSync(fullPath);
if (stat.isDirectory()) {
// Recursive scan
// Special handling: if dir is 'sprites', maybe subdirs are categories?
// For now, simple recursion
scanDir(fullPath, category);
} else if (file.match(/\.(png|jpg|jpeg)$/i)) {
const relativePath = 'assets/' + path.relative(ASSETS_DIR, fullPath);
const key = path.parse(file).name; // Use filename without ext as key
// Avoid duplicates?
// Just push for now
if (category === 'spritesheets') {
// Try to guess definition or generic
manifest.spritesheets.push({
key: key,
path: relativePath,
frameConfig: { frameWidth: 32, frameHeight: 32 } // Default guess
});
} else {
if (!manifest.phases[category]) manifest.phases[category] = [];
manifest.phases[category].push({
key: key,
path: relativePath
});
}
}
});
}
// MAIN SCAN LOOP
Object.keys(CATEGORY_MAP).forEach(dirName => {
const fullDir = path.join(ASSETS_DIR, dirName);
const cat = CATEGORY_MAP[dirName];
scanDir(fullDir, cat);
});
// Generate File Content
const fileContent = `window.AssetManifest = ${JSON.stringify(manifest, null, 4)};`;
fs.writeFileSync(OUTPUT_FILE, fileContent);
console.log('✅ AssetManifest.js regenerated!');
console.log(`Farm: ${manifest.phases.farm.length}`);
console.log(`Common: ${manifest.phases.common.length}`);
console.log(`Mine: ${manifest.phases.basement_mine.length}`);

118
tools/setup_tiled.js Normal file
View File

@@ -0,0 +1,118 @@
const fs = require('fs');
const path = require('path');
const TILED_DIR = 'assets/tiled';
const TARGET_MAPS = ['faza1_kmetija.json', 'demo_test.json'];
const ASSET_DIRS = ['../buildings', '../terrain', '../props']; // Relative to TILED_DIR
// 1. Gather Images
const tiles = []; // ARRAY for Tiled JSON compatibility
let nextId = 0; // Start ID at 0
let grassId = null;
ASSET_DIRS.forEach(dir => {
const fullDir = path.join(__dirname, '..', 'assets', dir.replace('../', ''));
if (fs.existsSync(fullDir)) {
const files = fs.readdirSync(fullDir);
files.forEach(file => {
if (file.endsWith('.png')) {
const relPath = path.join(dir, file);
// Add to array
tiles.push({
id: nextId,
image: relPath,
imageheight: 64, // Placeholder, Tiled will try to read actual
imagewidth: 64
});
// Identify Grass
if (file.includes('grass') || file.includes('resource_pile_food')) { // Fallback
if (grassId === null) grassId = nextId;
}
nextId++;
}
});
}
});
console.log(`🔍 Found ${tiles.length} assets.`);
console.log(`🌿 Grass ID: ${grassId}`);
// 2. Setup Tileset Object
const autoTileset = {
"columns": 0,
"grid": { "height": 1, "orientation": "orthogonal", "width": 1 },
"margin": 0,
"name": "Auto_Assets",
"spacing": 0,
"tilecount": tiles.length,
"tileheight": 256,
"tiles": tiles, // Array!
"tilewidth": 256,
"type": "tileset_image_collection"
};
// 3. Process Maps
TARGET_MAPS.forEach(mapFile => {
const mapPath = path.join(TILED_DIR, mapFile);
if (!fs.existsSync(mapPath)) {
console.warn(`⚠️ Map not found: ${mapPath}`);
return;
}
try {
const mapData = JSON.parse(fs.readFileSync(mapPath, 'utf8'));
// A. Inject Tileset
mapData.tilesets = [autoTileset];
// B. Auto-Ground (Fill Layer 1 with Grass)
const mapWidth = 100;
const mapHeight = 100;
mapData.width = mapWidth;
mapData.height = mapHeight;
// Find Ground Layer
const groundLayer = mapData.layers.find(l => l.name === 'Ground');
if (groundLayer && grassId !== null) {
groundLayer.width = mapWidth;
groundLayer.height = mapHeight;
groundLayer.data = new Array(mapWidth * mapHeight).fill(grassId + 1); // +1 because GID is local ID + firstgid (1)
// Wait, for image collections, keys match the ID.
// But map data uses GID (Global Tile ID).
// If firstgid is 1 (default for first tileset), then tile with ID 0 is GID 1.
// So tile with ID X is GID X + 1.
console.log(`✅ Filled Ground in ${mapFile} with GID ${grassId + 1}`);
}
// C. Demo Setup (Landmarks)
if (mapFile === 'demo_test.json') {
const objectLayer = mapData.layers.find(l => l.name === 'Objects');
if (objectLayer) {
objectLayer.width = mapWidth;
objectLayer.height = mapHeight;
// Add 5 random buildings
const randomIds = tiles.slice(0, 5).map(t => t.id);
const objData = new Array(mapWidth * mapHeight).fill(0);
randomIds.forEach((tileId, index) => {
const x = 10 + (index * 10);
const y = 15;
const idx = y * mapWidth + x;
if (idx < objData.length) objData[idx] = tileId + 1; // +1 GID
});
objectLayer.data = objData;
console.log(`✅ Placed 5 landmarks in ${mapFile}`);
}
}
// Save
fs.writeFileSync(mapPath, JSON.stringify(mapData, null, 4));
console.log(`💾 Saved updated ${mapFile}`);
} catch (e) {
console.error(`❌ Error processing ${mapFile}:`, e);
}
});

120
tools/tmx_to_json.js Normal file
View File

@@ -0,0 +1,120 @@
const fs = require('fs');
const path = require('path');
const src = 'assets/tiled/ProbnaFarma.tmx';
const dest = 'assets/maps/NovaFarma.json';
try {
const xml = fs.readFileSync(src, 'utf8');
// Super simple Regex parser for Tiled TMX (Caveat: Fragile!)
const parseAttr = (tag, attr) => {
const match = tag.match(new RegExp(`${attr}="([^"]*)"`));
return match ? match[1] : null;
};
// Extract Map Info
const mapMatch = xml.match(/<map [^>]+>/);
if (!mapMatch) throw new Error("No <map> tag");
const mapTag = mapMatch[0];
const width = parseInt(parseAttr(mapTag, 'width'));
const height = parseInt(parseAttr(mapTag, 'height'));
const tilewidth = parseInt(parseAttr(mapTag, 'tilewidth'));
const tileheight = parseInt(parseAttr(mapTag, 'tileheight'));
const json = {
width, height, tilewidth, tileheight,
layers: [],
tilesets: [],
orientation: "orthogonal",
renderorder: "right-down",
type: "map"
};
// Extract Layers
const layerRegex = /<layer [^>]+>([\s\S]*?)<\/layer>/g;
let layerMatch;
let idCounter = 1;
while ((layerMatch = layerRegex.exec(xml)) !== null) {
const fullLayer = layerMatch[0];
const content = layerMatch[1];
const openTag = fullLayer.match(/<layer [^>]+>/)[0];
const name = parseAttr(openTag, 'name');
const visible = parseAttr(openTag, 'visible') !== '0';
let data = [];
// Extract CSV Data
const dataMatch = content.match(/<data encoding="csv">([\s\S]*?)<\/data>/);
if (dataMatch) {
data = dataMatch[1].replace(/\s/g, '').split(',').map(Number);
}
json.layers.push({
id: idCounter++,
name: name,
type: "tilelayer",
width: width,
height: height,
visible: visible,
opacity: 1,
x: 0, y: 0,
data: data
});
}
// Extract Object Groups
const objGroupRegex = /<objectgroup [^>]+>([\s\S]*?)<\/objectgroup>/g;
while ((layerMatch = objGroupRegex.exec(xml)) !== null) {
const openTag = layerMatch[0].match(/<objectgroup [^>]+>/)[0];
const name = parseAttr(openTag, 'name');
json.layers.push({
id: idCounter++,
name: name,
type: "objectgroup",
visible: true,
opacity: 1,
objects: [] // Parsing objects is harder, skipping for now as user just wants visuals mostly
});
}
// Extract Tilesets
// <tileset firstgid="1" source="Buildings.tsx"/>
const tilesetRegex = /<tileset [^>]+>/g;
let tsMatch;
while ((tsMatch = tilesetRegex.exec(xml)) !== null) {
const tsTag = tsMatch[0];
const firstgid = parseInt(parseAttr(tsTag, 'firstgid'));
const source = parseAttr(tsTag, 'source');
// We need to bake the tileset data or link it.
// Phaser supports linked tilesets if JSON.
// But for simplicity, let's create a minimal embedded definition referring to image collection
// Actually, Tiled JSON exports 'source' usually.
// Fix path: TMX is in assets/tiled/, references are relative.
// JSON is in assets/maps/.
// If source is "Buildings.tsx", in TMX it means "assets/tiled/Buildings.tsx".
// In JSON (assets/maps), it should be "../tiled/Buildings.tsx".
let jsonSource = source;
if (!source.includes('/')) jsonSource = '../tiled/' + source;
json.tilesets.push({
firstgid: firstgid,
source: jsonSource
});
}
// Write
fs.writeFileSync(dest, JSON.stringify(json, null, 4));
console.log(`✅ Converted TMX to JSON: ${dest}`);
} catch (e) {
console.error("❌ Conversion failed:", e);
// Create Dummy
fs.writeFileSync(dest, JSON.stringify({ width: 10, height: 10, layers: [] }));
}

View File

@@ -474,33 +474,25 @@
</div>
<div class="filter-section">
<div class="filter-title">📁 Kategorije</div>
<div class="filter-title">📁 FAZE / PHASES</div>
<button class="filter-btn active" data-filter="all">
Vse <span class="filter-count">1166</span>
🌍 VSE (All) <span class="filter-count" id="count-all">0</span>
</button>
<button class="filter-btn" data-filter="liki">
👤 Liki <span class="filter-count">31</span>
<button class="filter-btn" data-filter="farm">
🚜 Faza 1: Farm <span class="filter-count" id="count-farm">0</span>
</button>
<button class="filter-btn" data-filter="zgradbe">
🏠 Zgradbe <span class="filter-count">54</span>
<button class="filter-btn" data-filter="basement_mine">
⛏️ Faza 2: Mine <span class="filter-count" id="count-mine">0</span>
</button>
<button class="filter-btn" data-filter="oprema">
⚔️ Oprema <span class="filter-count">48</span>
<button class="filter-btn" data-filter="common">
🎭 Common <span class="filter-count" id="count-common">0</span>
</button>
<button class="filter-btn" data-filter="narava">
🌿 Narava <span class="filter-count">289</span>
</button>
<button class="filter-btn" data-filter="notranjost">
🛋️ Notranjost <span class="filter-count">57</span>
</button>
<button class="filter-btn" data-filter="teren">
🗺️ Teren <span class="filter-count">30</span>
</button>
<button class="filter-btn" data-filter="vmesnik">
🎨 UI <span class="filter-count">34</span>
<button class="filter-btn" data-filter="spritesheets">
🎞️ Spritesheets <span class="filter-count" id="count-sprites">0</span>
</button>
</div>
<!--
<div class="action-buttons">
<button class="action-btn" onclick="runCodeScan()">
🔍 Code Deep Scan
@@ -515,6 +507,7 @@
🗑️ Delete Selected
</button>
</div>
-->
</div>
<!-- Main Content -->
@@ -557,6 +550,10 @@
<!-- Toast Notifications -->
<div class="toast" id="toast"></div>
<!-- External Manifest Script -->
<!-- External Manifest Script -->
<script src="src/AssetManifest.js"></script>
<script>
let allAssets = [];
let selectedAssets = new Set();
@@ -570,22 +567,68 @@
}
async function loadAssets() {
console.log('Loading assets from manifest...');
console.log('Loading assets from window.AssetManifest...');
try {
const response = await fetch('asset_manifest.json');
const manifest = await response.json();
if (!window.AssetManifest || !window.AssetManifest.phases) {
throw new Error('AssetManifest not found or invalid format!');
}
allAssets = manifest.assets;
allAssets = [];
// Update stats
document.getElementById('total-assets').textContent = manifest.total_assets;
document.getElementById('visible-assets').textContent = manifest.total_assets;
document.getElementById('total-size').textContent = manifest.total_size_mb;
// Helper to add assets from a phase
const addPhase = (phaseName, items) => {
if (!items) return;
items.forEach(item => {
allAssets.push({
id: item.key,
name: item.key,
path: item.path, // Path relative to root
category: phaseName,
size: '?' // Unknown size until loaded
});
});
};
console.log(`✅ Loaded ${allAssets.length} assets from manifest`);
// Add Phases
addPhase('farm', window.AssetManifest.phases.farm);
addPhase('basement_mine', window.AssetManifest.phases.basement_mine);
addPhase('common', window.AssetManifest.phases.common);
// Add Spritesheets
if (window.AssetManifest.spritesheets) {
window.AssetManifest.spritesheets.forEach(item => {
allAssets.push({
id: item.key,
name: item.key,
path: item.path,
category: 'spritesheets',
size: `Frames: ${item.frameConfig ? item.frameConfig.frameWidth + 'x' + item.frameConfig.frameHeight : '?'}`
});
});
}
// Update stats counts
document.getElementById('total-assets').textContent = allAssets.length;
document.getElementById('visible-assets').textContent = allAssets.length;
document.getElementById('total-size').textContent = 'N/A';
// Update Button Counts
const updateCount = (id, cat) => {
const count = allAssets.filter(a => a.category === cat).length;
const el = document.getElementById(id);
if (el) el.textContent = count;
};
document.getElementById('count-all').textContent = allAssets.length;
updateCount('count-farm', 'farm');
updateCount('count-mine', 'basement_mine');
updateCount('count-common', 'common');
updateCount('count-sprites', 'spritesheets');
console.log(`✅ Loaded ${allAssets.length} assets from AssetManifest.js`);
} catch (error) {
console.error('❌ Error loading manifest:', error);
alert('Error loading assets! Make sure you run:\npython3 ../scripts/generate_asset_manifest.py');
document.getElementById('gallery').innerHTML = `<p style="color:red;padding:20px;">Could not load AssetManifest.js<br>${error.message}</p>`;
}
}
@@ -675,68 +718,11 @@
}
function deleteAsset(id) {
const asset = allAssets.find(a => a.id === id);
if (!asset) return;
if (!confirm(`Res želiš trajno izbrisati:\n${asset.name}\n\nDatoteka bo fizično izbrisana iz diska!`)) return;
showLoading();
// Call backend API
fetch(`http://localhost:5001/api/asset/${id}`, {
method: 'DELETE'
})
.then(response => response.json())
.then(data => {
hideLoading();
if (data.success) {
showToast(`✅ ${asset.name} izbrisan!`);
// Reload assets from updated manifest
setTimeout(() => {
loadAssets().then(() => {
applyFilters();
});
}, 500);
} else {
showToast(`❌ Napaka: ${data.error}`);
}
})
.catch(error => {
hideLoading();
showToast(`❌ Backend error: ${error.message}`);
console.error('Delete error:', error);
});
alert('Delete functionality is disabled in this static view mode.');
}
function rerollAsset(id) {
const asset = allAssets.find(a => a.id === id);
if (!asset) return;
if (!confirm(`Re-generate "${asset.name}" z novim promptom?\n\n(Not yet fully implemented)`)) return;
showLoading();
// Call backend API
fetch(`http://localhost:5001/api/asset/${id}/reroll`, {
method: 'POST'
})
.then(response => response.json())
.then(data => {
hideLoading();
if (data.success) {
showToast(`🎨 ${data.message}`);
if (data.note) {
alert(data.note);
}
} else {
showToast(`❌ Napaka: ${data.error}`);
}
})
.catch(error => {
hideLoading();
showToast(`❌ Backend error: ${error.message}`);
console.error('Re-roll error:', error);
});
alert('Reroll functionality is disabled in this static view mode.');
}
// Bulk actions