- #212: Add GRID_MAX (8192) validation to Grid, ColorLayer, TileLayer
- #213: Validate color components are in 0-255 range
- #214: Add null pointer checks before HeightMap operations
- #216: Change entities_in_radius(x, y, radius) to (pos, radius)
- #217: Fix Entity __repr__ to show actual draw_pos float values
Closes#212, closes#213, closes#214, closes#216, closes#217
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
TileLayer (closes#200):
- apply_threshold(source, range, tile): Set tile index where heightmap value is in range
- apply_ranges(source, ranges): Apply multiple tile assignments in one pass
ColorLayer (closes#201):
- apply_threshold(source, range, color): Set fixed color where value is in range
- apply_gradient(source, range, color_low, color_high): Interpolate colors based on value
- apply_ranges(source, ranges): Apply multiple color assignments (fixed or gradient)
All methods return self for chaining. HeightMap size must match layer dimensions.
Later ranges override earlier ones if overlapping. Cells not matching any range are unchanged.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
ColorLayer enhancements:
- fill_rect(x, y, w, h, color): Fill rectangular region
- draw_fov(source, radius, fov, visible, discovered, unknown): One-time FOV draw
- apply_perspective(entity, visible, discovered, unknown): Bind layer to entity
- update_perspective(): Refresh layer from bound entity's gridstate
- clear_perspective(): Remove entity binding
New demo: tests/demo/perspective_patrol_demo.py
- Entity patrols around 10x10 central obstacle
- FOV layer shows visible/discovered/unknown states
- [R] to reset vision, [Space] to pause, [Q] to quit
- Demonstrates fog of war memory system
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement per-layer dirty tracking and RenderTexture caching for
ColorLayer and TileLayer. Each layer now maintains its own cached
texture and only re-renders when content changes.
Key changes:
- Add dirty flag, cached_texture, and cached_sprite to GridLayer base
- Implement renderToTexture() for both ColorLayer and TileLayer
- Mark layers dirty on: set(), fill(), resize(), texture change
- Viewport changes (center/zoom) just blit cached texture portion
- Fallback to direct rendering if texture creation fails
- Add regression test with performance benchmarks
Expected performance improvement: Static layers render once, then
viewport panning/zooming only requires texture blitting instead of
re-rendering all cells.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements ColorLayer and TileLayer classes with z_index ordering:
- ColorLayer: stores RGBA color per cell for overlays, fog of war, etc.
- TileLayer: stores sprite index per cell with optional texture
- z_index < 0: renders below entities
- z_index >= 0: renders above entities
Python API:
- grid.add_layer(type, z_index, texture) - create layer
- grid.remove_layer(layer) - remove layer
- grid.layers - list of layers sorted by z_index
- grid.layer(z_index) - get layer by z_index
- layer.at(x,y) / layer.set(x,y,value) - cell access
- layer.fill(value) - fill entire layer
Layers are allocated separately from UIGridPoint, reducing memory
for grids that don't need all features. Base grid retains walkable/
transparent arrays for TCOD pathfinding.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>