Multi-tile entities using oversized sprites #236

Open
opened 2026-02-02 16:22:34 +00:00 by john · 0 comments
Owner

Summary

Support entities that visually span multiple grid cells using a single sprite larger than the cell size (e.g., a 2×2 boss enemy, 3×4 dragon).

Parent issue: #233

Use Case

A boss enemy occupies a 2×2 area. The entity has a single 32×32 sprite (on a 16×16 grid) and should:

  • Be visible if ANY of its 4 tiles are in FOV
  • Be returned by position queries for any of its occupied tiles
  • Properly cull only when entirely off-screen

Current Behavior

Entities are treated as single points:

  • FOV checks single tile position
  • Spatial hash stores in single bucket
  • Frustum culling uses 1-cell margin

Proposed Changes

  1. Add to UIEntity:

    int tile_width = 1;   // Width in tiles (default 1)
    int tile_height = 1;  // Height in tiles (default 1)
    
  2. Modify FOV check (src/UIEntity.cpp):

    // Check if ANY occupied tile is visible
    bool isVisible = false;
    for (int dy = 0; dy < tile_height && !isVisible; dy++) {
        for (int dx = 0; dx < tile_width && !isVisible; dx++) {
            if (grid->isInFOV(x + dx, y + dy)) isVisible = true;
        }
    }
    
  3. Modify Spatial Hash:

    • Insert entity into all buckets it overlaps
    • Update removes from old buckets, inserts into new
  4. Modify Frustum Culling:

    if (e->position.x + e->tile_width < left_edge - 1 || 
        e->position.x >= left_edge + width_sq + 1 || ...)
    
  5. Python API:

    boss = mcrfpy.Entity(grid_pos=(5, 5), texture=boss_tex, sprite_index=0)
    boss.tile_size = (2, 2)  # or
    boss.tile_width = 2
    boss.tile_height = 2
    

Performance Impact

  • FOV: O(w×h) per multi-tile entity vs O(1)
  • Spatial Hash: O(w×h) insert/update vs O(1)
  • For typical 2×2 to 4×4 entities, impact is minimal

Files Affected

  • src/UIEntity.h/cpp - Add tile_width/height, modify FOV
  • src/UIGrid.cpp - Modify frustum culling
  • src/SpatialHash.h/cpp - Handle multi-tile insertion
## Summary Support entities that visually span multiple grid cells using a single sprite larger than the cell size (e.g., a 2×2 boss enemy, 3×4 dragon). **Parent issue**: #233 ## Use Case A boss enemy occupies a 2×2 area. The entity has a single 32×32 sprite (on a 16×16 grid) and should: - Be visible if ANY of its 4 tiles are in FOV - Be returned by position queries for any of its occupied tiles - Properly cull only when entirely off-screen ## Current Behavior Entities are treated as single points: - FOV checks single tile position - Spatial hash stores in single bucket - Frustum culling uses 1-cell margin ## Proposed Changes 1. **Add to UIEntity**: ```cpp int tile_width = 1; // Width in tiles (default 1) int tile_height = 1; // Height in tiles (default 1) ``` 2. **Modify FOV check** (src/UIEntity.cpp): ```cpp // Check if ANY occupied tile is visible bool isVisible = false; for (int dy = 0; dy < tile_height && !isVisible; dy++) { for (int dx = 0; dx < tile_width && !isVisible; dx++) { if (grid->isInFOV(x + dx, y + dy)) isVisible = true; } } ``` 3. **Modify Spatial Hash**: - Insert entity into all buckets it overlaps - Update removes from old buckets, inserts into new 4. **Modify Frustum Culling**: ```cpp if (e->position.x + e->tile_width < left_edge - 1 || e->position.x >= left_edge + width_sq + 1 || ...) ``` 5. **Python API**: ```python boss = mcrfpy.Entity(grid_pos=(5, 5), texture=boss_tex, sprite_index=0) boss.tile_size = (2, 2) # or boss.tile_width = 2 boss.tile_height = 2 ``` ## Performance Impact - FOV: O(w×h) per multi-tile entity vs O(1) - Spatial Hash: O(w×h) insert/update vs O(1) - For typical 2×2 to 4×4 entities, impact is minimal ## Files Affected - `src/UIEntity.h/cpp` - Add tile_width/height, modify FOV - `src/UIGrid.cpp` - Modify frustum culling - `src/SpatialHash.h/cpp` - Handle multi-tile insertion
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
john/McRogueFace#236
No description provided.