mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-28 20:55:44 +00:00
6.8 KiB
6.8 KiB
Programmatic Map Image Generation
Overview
Create a tool to programmatically regenerate the Eagle strategic map images with more equalized province sizes while preserving neighbor relationships. Also implement dynamic text rendering for province names that scales with zoom.
Current Map Assets
| File | Description | Dimensions |
|---|---|---|
Assets/Eagle/rawGray.gz.bytes |
Province ID lookup map (gzip compressed) | 3786 x 1834 |
Assets/Eagle/map_bw_labels.png |
B&W map with baked-in province labels | 3786 x 1834, RGBA |
Assets/Eagle/Materials/1.png - 43.png |
Individual province mask images | 3786 x 1834, grayscale |
Province Data
- 43 provinces defined in
src/main/resources/net/eagle0/eagle/province_map.tsv - Each has: id, name, neighbors, neighborPositions, hexMapName
- Problem provinces (too small): Shumal (id=1), Kojaria (id=39), Usvol (id=33), Tumala (id=35), Chia (id=43)
Goals
- Equalize province sizes - Reduce disparity so small provinces are easier to click
- Preserve topology - Maintain all neighbor relationships
- Preserve coastline - Keep ocean/land boundaries
- Dynamic text rendering - Province names scale with zoom level
Part 1: Province Size Equalization Tool
Algorithm: Constrained Voronoi Relaxation
-
Extract current state from rawGray:
- Calculate centroid of each province
- Calculate area (pixel count) of each province
- Identify ocean pixels (value 0 or 255)
-
Iterative relaxation:
For each iteration: For each province: Calculate target area (average of all provinces) If province is too small: Move centroid away from larger neighbors If province is too large: Move centroid toward smaller neighbors Constraint: Don't break neighbor relationships -
Generate new boundaries:
- Use weighted Voronoi diagram from relaxed centroids
- Weight by target area
- Mask with original coastline
-
Output new images:
- New rawGray (province ID map)
- New province masks (1.png - 43.png)
- New B&W base map (derived from boundaries)
Implementation Options
Option A: Python Script (Recommended)
- Use numpy, scipy, PIL/Pillow
- Can run offline, generate assets once
- Easier to iterate and debug
- Output: New image files to replace existing
Option B: Unity Editor Script
- C# with Unity's Texture2D
- Integrated into build process
- Slower, harder to debug
Tool Location
tools/map_generator/ or scripts/generate_map.py
Part 2: Dynamic Province Name Rendering
Current State
- Province names are baked into
map_bw_labels.png - Not visible when zoomed out, too small when zoomed in
SetUpCenterText()in MapController shows selected/hovered province name in a fixed UI panel
New Approach
-
Create province label GameObjects:
- One TextMeshPro label per province
- Position at province centroid
- Child of map content (moves with zoom/pan)
-
Dynamic scaling:
- Scale inversely with zoom level
- At zoom 1.0: Show major provinces only (or none)
- At zoom 2.0+: Show all province names
- Font size adjusts to fit province area
-
Implementation:
public class ProvinceLabelsController : MonoBehaviour { public MapPinchZoomHandler zoomHandler; public TextMeshProUGUI labelPrefab; private Dictionary<int, TextMeshProUGUI> _labels; void Update() { float zoom = zoomHandler.CurrentZoom; foreach (var label in _labels.Values) { label.transform.localScale = Vector3.one / zoom; label.gameObject.SetActive(zoom >= 1.5f); } } } -
Province centroid data:
- Add
centroid_x,centroid_ycolumns toprovince_map.tsv - Or calculate at runtime from rawGray
- Add
Files to Create/Modify
New Files
| File | Purpose |
|---|---|
tools/map_generator/generate_map.py |
Python script to generate new map images |
tools/map_generator/requirements.txt |
Python dependencies |
Assets/Eagle/ProvinceLabelsController.cs |
Dynamic province name rendering |
Modified Files
| File | Changes |
|---|---|
Assets/Eagle/rawGray.gz.bytes |
Replaced with equalized version |
Assets/Eagle/Materials/*.png |
Replaced province masks |
Assets/Eagle/map_bw_labels.png |
Either: regenerated, or removed if using dynamic labels |
province_map.tsv |
Add centroid columns |
Assets/Scenes/Eagle.unity |
Add ProvinceLabelsController, label prefab instances |
Verification
-
Visual inspection:
- Compare old vs new province sizes
- Verify small provinces (Shumal, Kojaria, Usvol) are larger
- Verify neighbor relationships preserved
-
Functional testing:
- Click on each province at various zoom levels
- Verify correct province is selected
- Verify province colors/weather still work
-
Label testing:
- Zoom in/out, verify labels scale appropriately
- Pan around, verify labels move with map
- Verify labels don't overlap excessively
Design Decisions
-
Equalization approach: Reduce disparity only
- Make small provinces (Shumal, Kojaria, Usvol, etc.) 2-3x larger
- Minimal changes to large provinces
- Not targeting perfectly equal areas
-
Coastline: Allow simplification
- Coastline can be smoothed/simplified as part of generation
- Voronoi edges are acceptable
-
Map style: Solid fills with borders
- Clean, simple look
- Easier to generate programmatically
- Province boundaries rendered as dark lines
Implementation Steps
Step 1: Python Map Generator Tool
tools/map_generator/
├── generate_map.py # Main script
├── requirements.txt # numpy, scipy, Pillow
└── README.md # Usage instructions
Algorithm:
- Load current rawGray.gz.bytes, decompress
- Calculate each province's centroid and area
- Identify land mask (non-ocean pixels)
- Run constrained Voronoi relaxation:
- Small provinces push neighbors away
- Large provinces pull neighbors in
- Stop when min province is >= 50% of average
- Generate weighted Voronoi from relaxed centroids
- Output:
rawGray_new.bytes(province ID map)1.png-43.png(province masks)map_bw.png(solid fill + borders)centroids.json(for label positioning)
Step 2: Dynamic Province Labels (Unity)
- Create
ProvinceLabelsController.cs - Load centroids from JSON or calculate from rawGray
- Spawn TextMeshPro labels at each centroid
- Update label scale/visibility based on zoom
Step 3: Integration
- Replace asset files with generated versions
- Update
MapControllerto use new assets - Add
ProvinceLabelsControllerto scene - Remove baked label image dependency