Update "Entity-Management"

John McCardle 2025-12-01 21:28:59 +00:00
parent d8eca08a79
commit 0417da11b9
1 changed files with 115 additions and 4 deletions

@ -1,3 +1,6 @@
# Entity Management
*Last modified: 2025-12-01*
# Entity Management
Entities are game objects that implement behavior and live on Grids. While Grids handle rendering and mediate interactions, Entities encapsulate game logic like movement, combat, and AI.
@ -18,6 +21,7 @@ Entities are game objects that implement behavior and live on Grids. While Grids
**Related Issues:**
- [#115](../../issues/115) - SpatialHash for fast queries (Open)
- [#117](../../issues/117) - Memory Pool for entities (Open)
- [#16](../../issues/16) - Entity knowledge contents (Open)
---
@ -28,6 +32,7 @@ Entities are game objects that:
- **Have a sprite** for visual rendering
- **Have grid position** (integer cell coordinates)
- **Implement behavior** (movement, AI, combat, inventory)
- **Track visibility** (which cells they can see / have seen)
**Key distinction:** Entities implement behavior. Grids mediate interaction between entities and render them to screen.
@ -103,6 +108,93 @@ current_grid = entity.grid # Read-only, set by collection operations
---
## Field of View & Visibility
Entities track what they can see via `gridstate` - a per-cell record of visible and discovered states.
### FOV Configuration
```python
# Grid-level FOV settings
grid.fov = mcrfpy.FOV.SHADOW # Algorithm (BASIC, DIAMOND, SHADOW, etc.)
grid.fov_radius = 10 # Default view radius
# Module-level default
mcrfpy.default_fov = mcrfpy.FOV.PERMISSIVE_2
```
### Updating Visibility
```python
# Compute FOV from entity's position and update gridstate
entity.update_visibility()
# This also updates any ColorLayers bound via apply_perspective()
```
### Querying Visible Entities
```python
# Get list of other entities this entity can see
visible_enemies = entity.visible_entities()
# With custom FOV settings
nearby = entity.visible_entities(radius=5)
visible = entity.visible_entities(fov=mcrfpy.FOV.BASIC, radius=8)
```
### Fog of War with ColorLayers
```python
# Create a ColorLayer for fog of war
fov_layer = grid.add_layer('color', z_index=-1)
fov_layer.fill((0, 0, 0, 255)) # Start black (unknown)
# Bind to entity - layer auto-updates when entity.update_visibility() is called
fov_layer.apply_perspective(
entity=player,
visible=(0, 0, 0, 0), # Transparent when visible
discovered=(40, 40, 60, 180), # Dark overlay when discovered
unknown=(0, 0, 0, 255) # Black when never seen
)
# Now whenever player moves:
player.x = new_x
player.y = new_y
player.update_visibility() # Automatically updates the fog layer
```
### One-Time FOV Draw
```python
# Draw FOV without binding (useful for previews, spell ranges, etc.)
fov_layer.draw_fov(
source=(player.x, player.y),
radius=10,
fov=mcrfpy.FOV.SHADOW,
visible=(255, 255, 200, 64),
discovered=(100, 100, 100, 128),
unknown=(0, 0, 0, 255)
)
```
### Gridstate Access
```python
# Entity's per-cell visibility memory
for state in entity.gridstate:
print(f"visible={state.visible}, discovered={state.discovered}")
# Access specific cell state
state = entity.at(x, y)
if state.visible:
print("Entity can currently see this cell")
elif state.discovered:
print("Entity has seen this cell before")
```
---
## EntityCollection
`grid.entities` is an `EntityCollection` with list-like operations:
@ -160,6 +252,9 @@ entity.pos = (new_x, new_y)
# Animated movement
mcrfpy.Animation("x", target_x, 0.3, "easeOutQuad").start(entity)
mcrfpy.Animation("y", target_y, 0.3, "easeOutQuad").start(entity)
# Update visibility after movement
entity.update_visibility()
```
### Removal
@ -188,24 +283,40 @@ def transfer_entity(entity, to_grid, new_pos):
## Common Patterns
### Player Entity
### Player Entity with FOV
```python
class Player:
def __init__(self, grid, start_pos):
self.entity = mcrfpy.Entity(pos=start_pos, sprite_index=0, name="player")
grid.entities.append(self.entity)
# Set up fog of war
self.fov_layer = grid.add_layer('color', z_index=-1)
self.fov_layer.fill((0, 0, 0, 255))
self.fov_layer.apply_perspective(
entity=self.entity,
visible=(0, 0, 0, 0),
discovered=(30, 30, 50, 180),
unknown=(0, 0, 0, 255)
)
self.entity.update_visibility()
def move(self, dx, dy):
new_x = self.entity.x + dx
new_y = self.entity.y + dy
# Check walkability via grid
point = self.entity.grid.at(new_x, new_y)
if point and point.walkable:
self.entity.pos = (new_x, new_y)
self.entity.update_visibility() # Update FOV after move
return True
return False
def get_visible_enemies(self):
"""Get enemies this player can currently see."""
return [e for e in self.entity.visible_entities()
if e.name and e.name.startswith("enemy")]
```
### Enemy Entity
@ -213,7 +324,7 @@ class Player:
```python
class Enemy:
def __init__(self, grid, pos, aggro_range=10):
self.entity = mcrfpy.Entity(pos=pos, sprite_index=1)
self.entity = mcrfpy.Entity(pos=pos, sprite_index=1, name="enemy")
self.aggro_range = aggro_range
self.health = 100
grid.entities.append(self.entity)
@ -312,4 +423,4 @@ See [[Performance-and-Profiling]] for optimization guidance.
---
*Last updated: 2025-11-29*
*Last updated: 2025-12-01*