Update "Entity-Management"
parent
d8eca08a79
commit
0417da11b9
|
|
@ -1,3 +1,6 @@
|
||||||
|
# Entity Management
|
||||||
|
*Last modified: 2025-12-01*
|
||||||
|
|
||||||
# Entity Management
|
# 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.
|
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:**
|
**Related Issues:**
|
||||||
- [#115](../../issues/115) - SpatialHash for fast queries (Open)
|
- [#115](../../issues/115) - SpatialHash for fast queries (Open)
|
||||||
- [#117](../../issues/117) - Memory Pool for entities (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 a sprite** for visual rendering
|
||||||
- **Have grid position** (integer cell coordinates)
|
- **Have grid position** (integer cell coordinates)
|
||||||
- **Implement behavior** (movement, AI, combat, inventory)
|
- **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.
|
**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
|
## EntityCollection
|
||||||
|
|
||||||
`grid.entities` is an `EntityCollection` with list-like operations:
|
`grid.entities` is an `EntityCollection` with list-like operations:
|
||||||
|
|
@ -160,6 +252,9 @@ entity.pos = (new_x, new_y)
|
||||||
# Animated movement
|
# Animated movement
|
||||||
mcrfpy.Animation("x", target_x, 0.3, "easeOutQuad").start(entity)
|
mcrfpy.Animation("x", target_x, 0.3, "easeOutQuad").start(entity)
|
||||||
mcrfpy.Animation("y", target_y, 0.3, "easeOutQuad").start(entity)
|
mcrfpy.Animation("y", target_y, 0.3, "easeOutQuad").start(entity)
|
||||||
|
|
||||||
|
# Update visibility after movement
|
||||||
|
entity.update_visibility()
|
||||||
```
|
```
|
||||||
|
|
||||||
### Removal
|
### Removal
|
||||||
|
|
@ -188,7 +283,7 @@ def transfer_entity(entity, to_grid, new_pos):
|
||||||
|
|
||||||
## Common Patterns
|
## Common Patterns
|
||||||
|
|
||||||
### Player Entity
|
### Player Entity with FOV
|
||||||
|
|
||||||
```python
|
```python
|
||||||
class Player:
|
class Player:
|
||||||
|
|
@ -196,16 +291,32 @@ class Player:
|
||||||
self.entity = mcrfpy.Entity(pos=start_pos, sprite_index=0, name="player")
|
self.entity = mcrfpy.Entity(pos=start_pos, sprite_index=0, name="player")
|
||||||
grid.entities.append(self.entity)
|
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):
|
def move(self, dx, dy):
|
||||||
new_x = self.entity.x + dx
|
new_x = self.entity.x + dx
|
||||||
new_y = self.entity.y + dy
|
new_y = self.entity.y + dy
|
||||||
|
|
||||||
# Check walkability via grid
|
|
||||||
point = self.entity.grid.at(new_x, new_y)
|
point = self.entity.grid.at(new_x, new_y)
|
||||||
if point and point.walkable:
|
if point and point.walkable:
|
||||||
self.entity.pos = (new_x, new_y)
|
self.entity.pos = (new_x, new_y)
|
||||||
|
self.entity.update_visibility() # Update FOV after move
|
||||||
return True
|
return True
|
||||||
return False
|
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
|
### Enemy Entity
|
||||||
|
|
@ -213,7 +324,7 @@ class Player:
|
||||||
```python
|
```python
|
||||||
class Enemy:
|
class Enemy:
|
||||||
def __init__(self, grid, pos, aggro_range=10):
|
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.aggro_range = aggro_range
|
||||||
self.health = 100
|
self.health = 100
|
||||||
grid.entities.append(self.entity)
|
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*
|
||||||
Loading…
Reference in New Issue