From 307b2615f405be8cb8f8273c4cdd0c3408abbeed Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sat, 7 Feb 2026 23:43:52 +0000 Subject: [PATCH] Update Proposal: Next Generation Grid & Entity System --- ...-Next-Generation-Grid-%26-Entity-System.md | 806 +++++++++--------- 1 file changed, 403 insertions(+), 403 deletions(-) rename Proposal%253A%2BNext-Generation%2BGrid%2B%2526%2BEntity%2BSystem.-.-.md => Proposal%3A-Next-Generation-Grid-%26-Entity-System.md (97%) diff --git a/Proposal%253A%2BNext-Generation%2BGrid%2B%2526%2BEntity%2BSystem.-.-.md b/Proposal%3A-Next-Generation-Grid-%26-Entity-System.md similarity index 97% rename from Proposal%253A%2BNext-Generation%2BGrid%2B%2526%2BEntity%2BSystem.-.-.md rename to Proposal%3A-Next-Generation-Grid-%26-Entity-System.md index 4713815..dd43c01 100644 --- a/Proposal%253A%2BNext-Generation%2BGrid%2B%2526%2BEntity%2BSystem.-.-.md +++ b/Proposal%3A-Next-Generation-Grid-%26-Entity-System.md @@ -1,404 +1,404 @@ -# Proposal: Next-Generation Grid & Entity System -*Last updated: 2026-02-07* - -# Proposal: Next-Generation Grid & Entity System - -**Status:** Partially Implemented (Phase 1 complete, Phase 4 complete, Phase 2 partial) -**Complexity:** Major architectural overhaul -**Impact:** Grid System, Entity Management, Performance - -**Related Pages:** -- [[Grid-System]] - Current grid architecture -- [[Entity-Management]] - Current entity usage -- [[Grid-Rendering-Pipeline]] - Current rendering architecture (includes Dynamic Layer API) - -**Source Documents:** -- `NEXT_GEN_GRIDS_ENTITIES_SHORTCOMINGS.md` - Analysis of current limitations -- `NEXT_GEN_GRIDS_ENTITIES_PROPOSAL.md` - Detailed technical proposal -- `NEXT_GEN_GRIDS_ENTITIES_IDEATION.md` - Use cases and ideation - -**Related Issues:** -- [#115](../issues/115) - SpatialHash for 10,000+ entities - **CLOSED (completed)** -- [#116](../issues/116) - Dirty flag system - **CLOSED (completed)** -- [#113](../issues/113) - Batch operations - **CLOSED (completed)** -- [#117](../issues/117) - Memory pool - Open (tier3-future) -- [#123](../issues/123) - Subgrid system - **CLOSED (completed)** (Grid now has children collection; see also #132) -- [#124](../issues/124) - Grid Point Animation - Open (tier4-deferred) -- [#122](../issues/122) - Parent-Child UI System - **CLOSED (completed)** -- [#237](../issues/237) - Multi-tile entity support - Open (future) -- [#147](../issues/147), [#148](../issues/148), [#150](../issues/150) - Dynamic Layer System - **CLOSED (completed)** - ---- - -## Implementation Progress - -### Phase 1: Performance Foundation - COMPLETE - -All three Phase 1 items have been implemented and are in production: - -- **SpatialHash** ([#115](../issues/115)): O(1) entity lookup by grid position. Entities are indexed in a spatial hash on the grid, enabling fast queries for 10,000+ entities. -- **Dirty flag system** ([#116](../issues/116)): Grids track dirty state to avoid unnecessary re-rendering. Only modified regions trigger render updates. -- **Batch operations** ([#113](../issues/113)): Bulk entity operations implemented for efficient mass updates. - -### Phase 2: Multi-Tile Support - PARTIAL - -- **Subgrid system** ([#123](../issues/123)): **CLOSED.** Grid now supports a `children` collection (see also [#132](../issues/132)), enabling nested UI elements within grids. -- **Full multi-tile entity support** ([#237](../issues/237)): **Still open (future).** Entity dimensions, occupied tile tracking, and multi-tile pathfinding remain unimplemented. - -### Phase 3: Flexible Content - NOT STARTED - -Grid children ([#132](../issues/132)) enables attaching UIDrawables to grids, which partially addresses this use case. However, the proposed entity content flexibility (replacing hardcoded UISprite with arbitrary UIDrawable content) has not been implemented. - -### Phase 4: Layer System - COMPLETE (implemented differently than proposed) - -The Dynamic Layer System ([#147](../issues/147), [#148](../issues/148), [#150](../issues/150)) has been fully implemented, but with a different API than originally proposed. Instead of a generic `GridLayer` class, the system uses standalone **TileLayer** and **ColorLayer** objects that are created independently and added to grids: - -```python -# Current API (implemented): -layer = mcrfpy.TileLayer(name="terrain", z_index=-1, texture=texture) -grid.add_layer(layer) - -color_layer = mcrfpy.ColorLayer(name="fog", z_index=5) -grid.add_layer(color_layer) - -# Access layers: -grid.layers # returns tuple of all layers -grid.layer("fog") # lookup by name -grid.remove_layer(layer) -layer.visible = False -``` - -See [[Grid-Rendering-Pipeline]] for the complete current layer API documentation. - ---- - -## Executive Summary - -The current UIEntity/UIGrid system has fundamental architectural limitations preventing implementation of modern roguelike features. This proposal outlines a comprehensive redesign supporting: - -- **Flexible entity content** - Entities containing any UIDrawable (Frame, Caption, Grid, Sprite) -- **Multi-tile entities** - 2x2, 3x3, or arbitrary-sized creatures and structures -- **Custom layer system** - Weather effects, particle layers, UI overlays -- **Spatial optimization** - O(1) entity queries via spatial hashing -- **Memory efficiency** - Optional gridstate, chunk-based loading - -**Key Insight:** Maintain entity as grid-specific *container* (no inheritance from UIDrawable), but allow flexible *content* (any UIDrawable). - ---- - -## Current Limitations - -### 1. Entity Type Rigidity - -**Problem:** -- UIEntity hardcoded to contain only UISprite -- Cannot place Frames, Captions, or Grids on grids -- Blocks speech bubbles, nested grids, complex UI - -**Current Code:** -```cpp -class UIEntity { - UISprite sprite; // Hardcoded! - // Should be: std::shared_ptr content; -} -``` - -### 2. Single-Tile Limitation - -**Problem:** -- Entity position is single point -- No concept of dimensions or occupied tiles -- Blocks large enemies (2x2 dragons), multi-tile structures (castle doors) - -**Missing:** -- `width`/`height` properties -- Spatial occupancy tracking -- Collision detection for multi-tile entities - -### 3. ~~Fixed Layer System~~ (RESOLVED) - -**Original Problem:** -- Grid had three hardcoded layers: tiles, entities, visibility -- No custom layers -- Blocked cloud layer, particle effects, weather overlays - -**Resolution:** The Dynamic Layer System (#147, #148, #150) was implemented with TileLayer and ColorLayer objects. Grids now support arbitrary numbers of named layers with z-ordering and visibility control. See [[Grid-Rendering-Pipeline]] for details. - -### 4. ~~Performance Issues~~ (RESOLVED) - -**Original Problem:** -- Linear O(n) iteration through all entities -- No spatial indexing -- Full grid re-render every frame - -**Resolution:** SpatialHash (#115) provides O(1) entity lookup. Dirty flag system (#116) prevents unnecessary re-renders. These optimizations are now in production. - -### 5. Memory Inefficiency - -**Problem:** -- Every entity maintains full gridstate vector (width x height) -- Decorative entities (clouds) waste memory on visibility data -- Cannot unload distant chunks - -**Status:** Memory pool (#117) remains open as tier3-future work. - ---- - -## Proposed Architecture - -### Core Change 1: Flexible Entity Content - -```cpp -class UIEntity { // No inheritance - grid-specific container -private: - std::shared_ptr content; // Any drawable! - sf::Vector2f gridPosition; // Position in grid coords - sf::Vector2i dimensions; // Size in tiles (default 1x1) - std::set occupiedTiles; // Cached occupied positions - std::vector gridstate; // Optional perspective data - -public: - void setContent(std::shared_ptr drawable); - void renderAt(sf::RenderTarget& target, sf::Vector2f pixelPos); - bool occupies(int x, int y) const; -}; -``` - -**Python API:** -```python -# Entity with sprite (backward compatible) -enemy = mcrfpy.Entity(grid_pos=(10, 10), sprite_index=5) - -# Entity with frame (NEW - speech bubble) -speech_frame = mcrfpy.Frame(size=(100, 50)) -speech_caption = mcrfpy.Caption(text="Hello!") -speech_frame.append(speech_caption) -speech_entity = mcrfpy.Entity(grid_pos=(player.x, player.y - 2)) -speech_entity.content = speech_frame - -# Entity with nested grid (NEW - mini-map) -minimap_grid = mcrfpy.Grid(grid_size=(20, 20), pos=(0, 0), size=(100, 100)) -minimap_entity = mcrfpy.Entity(grid_pos=(5, 5)) -minimap_entity.content = minimap_grid -``` - -### Core Change 2: Multi-Tile Entities - -```cpp -class GridOccupancyMap { -private: - std::unordered_map>> spatialHash; - int cellSize = 16; - -public: - void addEntity(std::shared_ptr entity); - void removeEntity(std::shared_ptr entity); - std::vector> getEntitiesAt(int x, int y); // O(1) - std::vector> getEntitiesInRect(sf::IntRect rect); -}; -``` - -**Python API:** -```python -# Large enemy (2x2 tiles) -dragon = mcrfpy.Entity( - grid_pos=(20, 20), - sprite_index=10, - dimensions=(2, 2) # NEW: multi-tile support -) - -# Check what tiles dragon occupies -occupied = dragon.occupied_tiles # [(20, 20), (21, 20), (20, 21), (21, 21)] - -# Collision detection accounts for size -if grid.can_move_to(dragon, new_x, new_y): - dragon.x = new_x - dragon.y = new_y -``` - -### ~~Core Change 3: Flexible Layer System~~ (IMPLEMENTED - see above) - -The layer system has been implemented as standalone TileLayer/ColorLayer objects rather than the generic `GridLayer` class originally proposed. The current implementation provides named layers, z-ordering, visibility control, and per-cell access. See the **Implementation Progress** section above and [[Grid-Rendering-Pipeline]] for the actual API. - -### ~~Core Change 4: Spatial Optimization~~ (IMPLEMENTED) - -SpatialHash is now in production (#115). Entity queries are O(1) average case. The dirty flag system (#116) prevents unnecessary re-renders. - ---- - -## Migration Path - -### Phase 1: Performance Foundation (Issues #115, #116, #113) - COMPLETE - -**Backward compatible improvements:** -1. ~~Add SpatialHash to existing UIGrid~~ **DONE** -2. ~~Implement dirty flag system~~ **DONE** -3. ~~Add batch operations for entities~~ **DONE** - -**No breaking changes to Python API.** - -### Phase 2: Multi-Tile Support (Issues #123, #237) - PARTIAL - -The subgrid system (#123) is complete - Grid now has a children collection. Full multi-tile entity support (#237) remains future work: - -```cpp -// Still proposed (not yet implemented): -// Add to UIEntity class -sf::Vector2i dimensions = {1, 1}; // Default 1x1 (backward compatible) -std::set occupiedTiles; - -void updateOccupiedTiles(); -bool occupies(int x, int y) const; -``` - -**Python API additions:** -```python -# Backward compatible - existing code works unchanged -enemy = mcrfpy.Entity(grid_pos=(10, 10), sprite_index=5) - -# New code can specify dimensions -dragon = mcrfpy.Entity(grid_pos=(20, 20), sprite_index=10, dimensions=(2, 2)) -``` - -### Phase 3: Flexible Content (Issue #124) - NOT STARTED - -**Replace UIEntity::sprite with content:** -```cpp -// Deprecate: UISprite sprite; -// Add: std::shared_ptr content; - -// Backward compatibility shim: -PyObject* get_sprite() { - auto sprite = std::dynamic_pointer_cast(content); - if (!sprite) { - // Legacy: entity still has sprite member - return legacy_sprite_accessor(); - } - return RET_PY_INSTANCE(sprite); -} -``` - -**Migration period:** 1-2 releases with deprecation warnings. - -### Phase 4: Layer System - COMPLETE - -Implemented as TileLayer/ColorLayer standalone objects (#147, #148, #150). See [[Grid-Rendering-Pipeline]] for the current API. The implementation differs from the original proposal (generic `GridLayer` class) but achieves the same goals: named layers, z-ordering, visibility, and per-cell control. - ---- - -## Use Cases Enabled - -### Speech Bubbles (requires Phase 3) -```python -speech = mcrfpy.Frame(size=(100, 40)) -speech.append(mcrfpy.Caption(text="Hello adventurer!")) -bubble = mcrfpy.Entity(grid_pos=(npc.x, npc.y - 1)) -bubble.content = speech -grid.entities.append(bubble) -``` - -### Large Enemies (requires Phase 2) -```python -dragon = mcrfpy.Entity(grid_pos=(25, 25), sprite_index=DRAGON, dimensions=(3, 3)) - -# Pathfinding accounts for size -if grid.can_large_entity_move_to(dragon, new_x, new_y): - dragon.move_to(new_x, new_y) -``` - -### Weather Effects (POSSIBLE NOW with Dynamic Layers) -```python -# Using current TileLayer API: -rain_layer = mcrfpy.TileLayer(name="rain", z_index=200, texture=rain_texture) -grid.add_layer(rain_layer) - -# Set rain tile indices on the layer -for i in range(100): - x, y = random.randint(0, 49), random.randint(0, 49) - rain_layer.set((x, y), RAINDROP_TILE_INDEX) -``` - -### Nested Mini-Map (requires Phase 3) -```python -minimap = mcrfpy.Grid(grid_size=(20, 20), pos=(0, 0), size=(100, 100)) -# ... populate minimap ... - -minimap_entity = mcrfpy.Entity(grid_pos=(0, 0)) -minimap_entity.content = minimap -hud_layer.entities.append(minimap_entity) -``` - ---- - -## Performance Expectations - -### Before Phase 1 (Historical - Pre-Implementation) -- 1,000 entities: 60 FPS -- 10,000 entities: 15 FPS (unacceptable) -- Entity query: O(n) = slow - -### After Phase 1 (Current - SpatialHash + Dirty Flags in Production) -- 1,000 entities: 60 FPS -- 10,000 entities: 60 FPS (with spatial hash + culling) -- Entity query: O(1) average case - -> **Note:** The SpatialHash and dirty flag systems are now in production. The "Before" numbers above reflect historical performance prior to these optimizations. - -### Memory Impact (Projected - for future phases) -- Per-entity overhead: +24 bytes (dimensions, occupied tiles set) -- Spatial hash: ~8KB for 1000 entities (negligible) -- Optional gridstate: Save width x height x sizeof(UIGridPointState) per decorative entity - ---- - -## Open Questions - -1. **Backward Compatibility Timeline** - - How many releases should deprecation period last? - - Support for legacy `entity.sprite` accessor? - -2. ~~**Layer API Design**~~ (RESOLVED - TileLayer/ColorLayer implemented) - -3. **Multi-Tile Pathfinding** (relevant if Phase 2 proceeds) - - Should large entities use separate TCOD maps? - - How to handle partially-blocked paths? - -4. **Content Delegation** (relevant if Phase 3 proceeds) - - Should entity forward all UIDrawable methods to content? - - Or keep explicit `entity.content.method()` pattern? - ---- - -## Implementation Complexity - -**Estimated Effort:** -- ~~Phase 1 (SpatialHash, dirty flags, batch ops): 40-60 hours~~ **COMPLETE** -- Phase 2 (Multi-tile): 20-30 hours - partially done (subgrid complete, multi-tile entities remain) -- Phase 3 (Flexible content): 30-40 hours - not started -- ~~Phase 4 (Layers): 40-50 hours~~ **COMPLETE** (implemented as TileLayer/ColorLayer) - -**Remaining:** ~40-60 hours for Phase 2 completion + Phase 3 (if pursued) - -**Risk Areas:** -- Backward compatibility testing -- Python binding complexity for flexible content -- Performance regression testing -- Documentation updates - ---- - -## Remaining Decisions - -Phase 1 (Performance Foundation) and Phase 4 (Layer System) are **complete and in production**. The remaining question is whether to pursue: - -- **Phase 2 completion** ([#237](../issues/237)): Full multi-tile entity support (dimensions, occupied tiles, multi-tile pathfinding). This enables large enemies, multi-tile structures, and size-aware collision. -- **Phase 3** ([#124](../issues/124)): Flexible entity content (replacing hardcoded UISprite with arbitrary UIDrawable). This enables speech bubbles, nested grids in entities, and complex entity visuals. - -Both remain as future/deferred priorities. The incremental approach has proven effective - the highest-impact items (performance and layers) were completed first. - ---- - -**Navigation:** -- [[Home]] - Documentation hub -- [[Grid-System]] - Current architecture +# Proposal: Next-Generation Grid & Entity System +*Last updated: 2026-02-07* + +# Proposal: Next-Generation Grid & Entity System + +**Status:** Partially Implemented (Phase 1 complete, Phase 4 complete, Phase 2 partial) +**Complexity:** Major architectural overhaul +**Impact:** Grid System, Entity Management, Performance + +**Related Pages:** +- [[Grid-System]] - Current grid architecture +- [[Entity-Management]] - Current entity usage +- [[Grid-Rendering-Pipeline]] - Current rendering architecture (includes Dynamic Layer API) + +**Source Documents:** +- `NEXT_GEN_GRIDS_ENTITIES_SHORTCOMINGS.md` - Analysis of current limitations +- `NEXT_GEN_GRIDS_ENTITIES_PROPOSAL.md` - Detailed technical proposal +- `NEXT_GEN_GRIDS_ENTITIES_IDEATION.md` - Use cases and ideation + +**Related Issues:** +- [#115](../issues/115) - SpatialHash for 10,000+ entities - **CLOSED (completed)** +- [#116](../issues/116) - Dirty flag system - **CLOSED (completed)** +- [#113](../issues/113) - Batch operations - **CLOSED (completed)** +- [#117](../issues/117) - Memory pool - Open (tier3-future) +- [#123](../issues/123) - Subgrid system - **CLOSED (completed)** (Grid now has children collection; see also #132) +- [#124](../issues/124) - Grid Point Animation - Open (tier4-deferred) +- [#122](../issues/122) - Parent-Child UI System - **CLOSED (completed)** +- [#237](../issues/237) - Multi-tile entity support - Open (future) +- [#147](../issues/147), [#148](../issues/148), [#150](../issues/150) - Dynamic Layer System - **CLOSED (completed)** + +--- + +## Implementation Progress + +### Phase 1: Performance Foundation - COMPLETE + +All three Phase 1 items have been implemented and are in production: + +- **SpatialHash** ([#115](../issues/115)): O(1) entity lookup by grid position. Entities are indexed in a spatial hash on the grid, enabling fast queries for 10,000+ entities. +- **Dirty flag system** ([#116](../issues/116)): Grids track dirty state to avoid unnecessary re-rendering. Only modified regions trigger render updates. +- **Batch operations** ([#113](../issues/113)): Bulk entity operations implemented for efficient mass updates. + +### Phase 2: Multi-Tile Support - PARTIAL + +- **Subgrid system** ([#123](../issues/123)): **CLOSED.** Grid now supports a `children` collection (see also [#132](../issues/132)), enabling nested UI elements within grids. +- **Full multi-tile entity support** ([#237](../issues/237)): **Still open (future).** Entity dimensions, occupied tile tracking, and multi-tile pathfinding remain unimplemented. + +### Phase 3: Flexible Content - NOT STARTED + +Grid children ([#132](../issues/132)) enables attaching UIDrawables to grids, which partially addresses this use case. However, the proposed entity content flexibility (replacing hardcoded UISprite with arbitrary UIDrawable content) has not been implemented. + +### Phase 4: Layer System - COMPLETE (implemented differently than proposed) + +The Dynamic Layer System ([#147](../issues/147), [#148](../issues/148), [#150](../issues/150)) has been fully implemented, but with a different API than originally proposed. Instead of a generic `GridLayer` class, the system uses standalone **TileLayer** and **ColorLayer** objects that are created independently and added to grids: + +```python +# Current API (implemented): +layer = mcrfpy.TileLayer(name="terrain", z_index=-1, texture=texture) +grid.add_layer(layer) + +color_layer = mcrfpy.ColorLayer(name="fog", z_index=5) +grid.add_layer(color_layer) + +# Access layers: +grid.layers # returns tuple of all layers +grid.layer("fog") # lookup by name +grid.remove_layer(layer) +layer.visible = False +``` + +See [[Grid-Rendering-Pipeline]] for the complete current layer API documentation. + +--- + +## Executive Summary + +The current UIEntity/UIGrid system has fundamental architectural limitations preventing implementation of modern roguelike features. This proposal outlines a comprehensive redesign supporting: + +- **Flexible entity content** - Entities containing any UIDrawable (Frame, Caption, Grid, Sprite) +- **Multi-tile entities** - 2x2, 3x3, or arbitrary-sized creatures and structures +- **Custom layer system** - Weather effects, particle layers, UI overlays +- **Spatial optimization** - O(1) entity queries via spatial hashing +- **Memory efficiency** - Optional gridstate, chunk-based loading + +**Key Insight:** Maintain entity as grid-specific *container* (no inheritance from UIDrawable), but allow flexible *content* (any UIDrawable). + +--- + +## Current Limitations + +### 1. Entity Type Rigidity + +**Problem:** +- UIEntity hardcoded to contain only UISprite +- Cannot place Frames, Captions, or Grids on grids +- Blocks speech bubbles, nested grids, complex UI + +**Current Code:** +```cpp +class UIEntity { + UISprite sprite; // Hardcoded! + // Should be: std::shared_ptr content; +} +``` + +### 2. Single-Tile Limitation + +**Problem:** +- Entity position is single point +- No concept of dimensions or occupied tiles +- Blocks large enemies (2x2 dragons), multi-tile structures (castle doors) + +**Missing:** +- `width`/`height` properties +- Spatial occupancy tracking +- Collision detection for multi-tile entities + +### 3. ~~Fixed Layer System~~ (RESOLVED) + +**Original Problem:** +- Grid had three hardcoded layers: tiles, entities, visibility +- No custom layers +- Blocked cloud layer, particle effects, weather overlays + +**Resolution:** The Dynamic Layer System (#147, #148, #150) was implemented with TileLayer and ColorLayer objects. Grids now support arbitrary numbers of named layers with z-ordering and visibility control. See [[Grid-Rendering-Pipeline]] for details. + +### 4. ~~Performance Issues~~ (RESOLVED) + +**Original Problem:** +- Linear O(n) iteration through all entities +- No spatial indexing +- Full grid re-render every frame + +**Resolution:** SpatialHash (#115) provides O(1) entity lookup. Dirty flag system (#116) prevents unnecessary re-renders. These optimizations are now in production. + +### 5. Memory Inefficiency + +**Problem:** +- Every entity maintains full gridstate vector (width x height) +- Decorative entities (clouds) waste memory on visibility data +- Cannot unload distant chunks + +**Status:** Memory pool (#117) remains open as tier3-future work. + +--- + +## Proposed Architecture + +### Core Change 1: Flexible Entity Content + +```cpp +class UIEntity { // No inheritance - grid-specific container +private: + std::shared_ptr content; // Any drawable! + sf::Vector2f gridPosition; // Position in grid coords + sf::Vector2i dimensions; // Size in tiles (default 1x1) + std::set occupiedTiles; // Cached occupied positions + std::vector gridstate; // Optional perspective data + +public: + void setContent(std::shared_ptr drawable); + void renderAt(sf::RenderTarget& target, sf::Vector2f pixelPos); + bool occupies(int x, int y) const; +}; +``` + +**Python API:** +```python +# Entity with sprite (backward compatible) +enemy = mcrfpy.Entity(grid_pos=(10, 10), sprite_index=5) + +# Entity with frame (NEW - speech bubble) +speech_frame = mcrfpy.Frame(size=(100, 50)) +speech_caption = mcrfpy.Caption(text="Hello!") +speech_frame.append(speech_caption) +speech_entity = mcrfpy.Entity(grid_pos=(player.x, player.y - 2)) +speech_entity.content = speech_frame + +# Entity with nested grid (NEW - mini-map) +minimap_grid = mcrfpy.Grid(grid_size=(20, 20), pos=(0, 0), size=(100, 100)) +minimap_entity = mcrfpy.Entity(grid_pos=(5, 5)) +minimap_entity.content = minimap_grid +``` + +### Core Change 2: Multi-Tile Entities + +```cpp +class GridOccupancyMap { +private: + std::unordered_map>> spatialHash; + int cellSize = 16; + +public: + void addEntity(std::shared_ptr entity); + void removeEntity(std::shared_ptr entity); + std::vector> getEntitiesAt(int x, int y); // O(1) + std::vector> getEntitiesInRect(sf::IntRect rect); +}; +``` + +**Python API:** +```python +# Large enemy (2x2 tiles) +dragon = mcrfpy.Entity( + grid_pos=(20, 20), + sprite_index=10, + dimensions=(2, 2) # NEW: multi-tile support +) + +# Check what tiles dragon occupies +occupied = dragon.occupied_tiles # [(20, 20), (21, 20), (20, 21), (21, 21)] + +# Collision detection accounts for size +if grid.can_move_to(dragon, new_x, new_y): + dragon.x = new_x + dragon.y = new_y +``` + +### ~~Core Change 3: Flexible Layer System~~ (IMPLEMENTED - see above) + +The layer system has been implemented as standalone TileLayer/ColorLayer objects rather than the generic `GridLayer` class originally proposed. The current implementation provides named layers, z-ordering, visibility control, and per-cell access. See the **Implementation Progress** section above and [[Grid-Rendering-Pipeline]] for the actual API. + +### ~~Core Change 4: Spatial Optimization~~ (IMPLEMENTED) + +SpatialHash is now in production (#115). Entity queries are O(1) average case. The dirty flag system (#116) prevents unnecessary re-renders. + +--- + +## Migration Path + +### Phase 1: Performance Foundation (Issues #115, #116, #113) - COMPLETE + +**Backward compatible improvements:** +1. ~~Add SpatialHash to existing UIGrid~~ **DONE** +2. ~~Implement dirty flag system~~ **DONE** +3. ~~Add batch operations for entities~~ **DONE** + +**No breaking changes to Python API.** + +### Phase 2: Multi-Tile Support (Issues #123, #237) - PARTIAL + +The subgrid system (#123) is complete - Grid now has a children collection. Full multi-tile entity support (#237) remains future work: + +```cpp +// Still proposed (not yet implemented): +// Add to UIEntity class +sf::Vector2i dimensions = {1, 1}; // Default 1x1 (backward compatible) +std::set occupiedTiles; + +void updateOccupiedTiles(); +bool occupies(int x, int y) const; +``` + +**Python API additions:** +```python +# Backward compatible - existing code works unchanged +enemy = mcrfpy.Entity(grid_pos=(10, 10), sprite_index=5) + +# New code can specify dimensions +dragon = mcrfpy.Entity(grid_pos=(20, 20), sprite_index=10, dimensions=(2, 2)) +``` + +### Phase 3: Flexible Content (Issue #124) - NOT STARTED + +**Replace UIEntity::sprite with content:** +```cpp +// Deprecate: UISprite sprite; +// Add: std::shared_ptr content; + +// Backward compatibility shim: +PyObject* get_sprite() { + auto sprite = std::dynamic_pointer_cast(content); + if (!sprite) { + // Legacy: entity still has sprite member + return legacy_sprite_accessor(); + } + return RET_PY_INSTANCE(sprite); +} +``` + +**Migration period:** 1-2 releases with deprecation warnings. + +### Phase 4: Layer System - COMPLETE + +Implemented as TileLayer/ColorLayer standalone objects (#147, #148, #150). See [[Grid-Rendering-Pipeline]] for the current API. The implementation differs from the original proposal (generic `GridLayer` class) but achieves the same goals: named layers, z-ordering, visibility, and per-cell control. + +--- + +## Use Cases Enabled + +### Speech Bubbles (requires Phase 3) +```python +speech = mcrfpy.Frame(size=(100, 40)) +speech.append(mcrfpy.Caption(text="Hello adventurer!")) +bubble = mcrfpy.Entity(grid_pos=(npc.x, npc.y - 1)) +bubble.content = speech +grid.entities.append(bubble) +``` + +### Large Enemies (requires Phase 2) +```python +dragon = mcrfpy.Entity(grid_pos=(25, 25), sprite_index=DRAGON, dimensions=(3, 3)) + +# Pathfinding accounts for size +if grid.can_large_entity_move_to(dragon, new_x, new_y): + dragon.move_to(new_x, new_y) +``` + +### Weather Effects (POSSIBLE NOW with Dynamic Layers) +```python +# Using current TileLayer API: +rain_layer = mcrfpy.TileLayer(name="rain", z_index=200, texture=rain_texture) +grid.add_layer(rain_layer) + +# Set rain tile indices on the layer +for i in range(100): + x, y = random.randint(0, 49), random.randint(0, 49) + rain_layer.set((x, y), RAINDROP_TILE_INDEX) +``` + +### Nested Mini-Map (requires Phase 3) +```python +minimap = mcrfpy.Grid(grid_size=(20, 20), pos=(0, 0), size=(100, 100)) +# ... populate minimap ... + +minimap_entity = mcrfpy.Entity(grid_pos=(0, 0)) +minimap_entity.content = minimap +hud_layer.entities.append(minimap_entity) +``` + +--- + +## Performance Expectations + +### Before Phase 1 (Historical - Pre-Implementation) +- 1,000 entities: 60 FPS +- 10,000 entities: 15 FPS (unacceptable) +- Entity query: O(n) = slow + +### After Phase 1 (Current - SpatialHash + Dirty Flags in Production) +- 1,000 entities: 60 FPS +- 10,000 entities: 60 FPS (with spatial hash + culling) +- Entity query: O(1) average case + +> **Note:** The SpatialHash and dirty flag systems are now in production. The "Before" numbers above reflect historical performance prior to these optimizations. + +### Memory Impact (Projected - for future phases) +- Per-entity overhead: +24 bytes (dimensions, occupied tiles set) +- Spatial hash: ~8KB for 1000 entities (negligible) +- Optional gridstate: Save width x height x sizeof(UIGridPointState) per decorative entity + +--- + +## Open Questions + +1. **Backward Compatibility Timeline** + - How many releases should deprecation period last? + - Support for legacy `entity.sprite` accessor? + +2. ~~**Layer API Design**~~ (RESOLVED - TileLayer/ColorLayer implemented) + +3. **Multi-Tile Pathfinding** (relevant if Phase 2 proceeds) + - Should large entities use separate TCOD maps? + - How to handle partially-blocked paths? + +4. **Content Delegation** (relevant if Phase 3 proceeds) + - Should entity forward all UIDrawable methods to content? + - Or keep explicit `entity.content.method()` pattern? + +--- + +## Implementation Complexity + +**Estimated Effort:** +- ~~Phase 1 (SpatialHash, dirty flags, batch ops): 40-60 hours~~ **COMPLETE** +- Phase 2 (Multi-tile): 20-30 hours - partially done (subgrid complete, multi-tile entities remain) +- Phase 3 (Flexible content): 30-40 hours - not started +- ~~Phase 4 (Layers): 40-50 hours~~ **COMPLETE** (implemented as TileLayer/ColorLayer) + +**Remaining:** ~40-60 hours for Phase 2 completion + Phase 3 (if pursued) + +**Risk Areas:** +- Backward compatibility testing +- Python binding complexity for flexible content +- Performance regression testing +- Documentation updates + +--- + +## Remaining Decisions + +Phase 1 (Performance Foundation) and Phase 4 (Layer System) are **complete and in production**. The remaining question is whether to pursue: + +- **Phase 2 completion** ([#237](../issues/237)): Full multi-tile entity support (dimensions, occupied tiles, multi-tile pathfinding). This enables large enemies, multi-tile structures, and size-aware collision. +- **Phase 3** ([#124](../issues/124)): Flexible entity content (replacing hardcoded UISprite with arbitrary UIDrawable). This enables speech bubbles, nested grids in entities, and complex entity visuals. + +Both remain as future/deferred priorities. The incremental approach has proven effective - the highest-impact items (performance and layers) were completed first. + +--- + +**Navigation:** +- [[Home]] - Documentation hub +- [[Grid-System]] - Current architecture - [[Design-Proposals]] - All design proposals \ No newline at end of file