Fix #161: Update Grid, GridPoint, GridPointState stubs to match current API
- Grid: Update constructor (pos, size, grid_size, texture, ...) and add all current properties (zoom, center, layers, FOV, cell events, etc.) - Grid: Add all methods (find_path, compute_fov, add_layer, entities_in_radius, etc.) - GridPoint: Replace incorrect properties (texture_index, solid, color) with actual API (walkable, transparent, entities, grid_pos) - GridPointState: Replace incorrect properties with actual API (visible, discovered, point) - Add missing types: ColorLayer, TileLayer, FOV, AStarPath, DijkstraMap, HeightMap, NoiseSource, BSP Closes #161 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
165db91b8d
commit
4be2502a10
3 changed files with 1120 additions and 111 deletions
|
|
@ -6,7 +6,7 @@ Core game engine interface for creating roguelike games with Python.
|
||||||
from typing import Any, List, Dict, Tuple, Optional, Callable, Union, overload
|
from typing import Any, List, Dict, Tuple, Optional, Callable, Union, overload
|
||||||
|
|
||||||
# Type aliases
|
# Type aliases
|
||||||
UIElement = Union['Frame', 'Caption', 'Sprite', 'Grid']
|
UIElement = Union['Frame', 'Caption', 'Sprite', 'Grid', 'Line', 'Circle', 'Arc']
|
||||||
Transition = Union[str, None]
|
Transition = Union[str, None]
|
||||||
|
|
||||||
# Classes
|
# Classes
|
||||||
|
|
@ -75,131 +75,514 @@ class Font:
|
||||||
|
|
||||||
class Drawable:
|
class Drawable:
|
||||||
"""Base class for all drawable UI elements."""
|
"""Base class for all drawable UI elements."""
|
||||||
|
|
||||||
x: float
|
x: float
|
||||||
y: float
|
y: float
|
||||||
visible: bool
|
visible: bool
|
||||||
z_index: int
|
z_index: int
|
||||||
name: str
|
name: str
|
||||||
pos: Vector
|
pos: Vector
|
||||||
|
|
||||||
|
# Mouse event callbacks (#140, #141)
|
||||||
|
on_click: Optional[Callable[[float, float, int, str], None]]
|
||||||
|
on_enter: Optional[Callable[[float, float, int, str], None]]
|
||||||
|
on_exit: Optional[Callable[[float, float, int, str], None]]
|
||||||
|
on_move: Optional[Callable[[float, float, int, str], None]]
|
||||||
|
|
||||||
|
# Read-only hover state (#140)
|
||||||
|
hovered: bool
|
||||||
|
|
||||||
def get_bounds(self) -> Tuple[float, float, float, float]:
|
def get_bounds(self) -> Tuple[float, float, float, float]:
|
||||||
"""Get bounding box as (x, y, width, height)."""
|
"""Get bounding box as (x, y, width, height)."""
|
||||||
...
|
...
|
||||||
|
|
||||||
def move(self, dx: float, dy: float) -> None:
|
def move(self, dx: float, dy: float) -> None:
|
||||||
"""Move by relative offset (dx, dy)."""
|
"""Move by relative offset (dx, dy)."""
|
||||||
...
|
...
|
||||||
|
|
||||||
def resize(self, width: float, height: float) -> None:
|
def resize(self, width: float, height: float) -> None:
|
||||||
"""Resize to new dimensions (width, height)."""
|
"""Resize to new dimensions (width, height)."""
|
||||||
...
|
...
|
||||||
|
|
||||||
class Frame(Drawable):
|
class Frame(Drawable):
|
||||||
"""Frame(x=0, y=0, w=0, h=0, fill_color=None, outline_color=None, outline=0, click=None, children=None)
|
"""Frame(x=0, y=0, w=0, h=0, fill_color=None, outline_color=None, outline=0, on_click=None, children=None)
|
||||||
|
|
||||||
A rectangular frame UI element that can contain other drawable elements.
|
A rectangular frame UI element that can contain other drawable elements.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __init__(self) -> None: ...
|
def __init__(self) -> None: ...
|
||||||
@overload
|
@overload
|
||||||
def __init__(self, x: float = 0, y: float = 0, w: float = 0, h: float = 0,
|
def __init__(self, x: float = 0, y: float = 0, w: float = 0, h: float = 0,
|
||||||
fill_color: Optional[Color] = None, outline_color: Optional[Color] = None,
|
fill_color: Optional[Color] = None, outline_color: Optional[Color] = None,
|
||||||
outline: float = 0, click: Optional[Callable] = None,
|
outline: float = 0, on_click: Optional[Callable] = None,
|
||||||
children: Optional[List[UIElement]] = None) -> None: ...
|
children: Optional[List[UIElement]] = None) -> None: ...
|
||||||
|
|
||||||
w: float
|
w: float
|
||||||
h: float
|
h: float
|
||||||
fill_color: Color
|
fill_color: Color
|
||||||
outline_color: Color
|
outline_color: Color
|
||||||
outline: float
|
outline: float
|
||||||
click: Optional[Callable[[float, float, int], None]]
|
on_click: Optional[Callable[[float, float, int], None]]
|
||||||
children: 'UICollection'
|
children: 'UICollection'
|
||||||
clip_children: bool
|
clip_children: bool
|
||||||
|
|
||||||
class Caption(Drawable):
|
class Caption(Drawable):
|
||||||
"""Caption(text='', x=0, y=0, font=None, fill_color=None, outline_color=None, outline=0, click=None)
|
"""Caption(text='', x=0, y=0, font=None, fill_color=None, outline_color=None, outline=0, on_click=None)
|
||||||
|
|
||||||
A text display UI element with customizable font and styling.
|
A text display UI element with customizable font and styling.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __init__(self) -> None: ...
|
def __init__(self) -> None: ...
|
||||||
@overload
|
@overload
|
||||||
def __init__(self, text: str = '', x: float = 0, y: float = 0,
|
def __init__(self, text: str = '', x: float = 0, y: float = 0,
|
||||||
font: Optional[Font] = None, fill_color: Optional[Color] = None,
|
font: Optional[Font] = None, fill_color: Optional[Color] = None,
|
||||||
outline_color: Optional[Color] = None, outline: float = 0,
|
outline_color: Optional[Color] = None, outline: float = 0,
|
||||||
click: Optional[Callable] = None) -> None: ...
|
on_click: Optional[Callable] = None) -> None: ...
|
||||||
|
|
||||||
text: str
|
text: str
|
||||||
font: Font
|
font: Font
|
||||||
fill_color: Color
|
fill_color: Color
|
||||||
outline_color: Color
|
outline_color: Color
|
||||||
outline: float
|
outline: float
|
||||||
click: Optional[Callable[[float, float, int], None]]
|
on_click: Optional[Callable[[float, float, int], None]]
|
||||||
w: float # Read-only, computed from text
|
w: float # Read-only, computed from text
|
||||||
h: float # Read-only, computed from text
|
h: float # Read-only, computed from text
|
||||||
|
|
||||||
class Sprite(Drawable):
|
class Sprite(Drawable):
|
||||||
"""Sprite(x=0, y=0, texture=None, sprite_index=0, scale=1.0, click=None)
|
"""Sprite(x=0, y=0, texture=None, sprite_index=0, scale=1.0, on_click=None)
|
||||||
|
|
||||||
A sprite UI element that displays a texture or portion of a texture atlas.
|
A sprite UI element that displays a texture or portion of a texture atlas.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __init__(self) -> None: ...
|
def __init__(self) -> None: ...
|
||||||
@overload
|
@overload
|
||||||
def __init__(self, x: float = 0, y: float = 0, texture: Optional[Texture] = None,
|
def __init__(self, x: float = 0, y: float = 0, texture: Optional[Texture] = None,
|
||||||
sprite_index: int = 0, scale: float = 1.0,
|
sprite_index: int = 0, scale: float = 1.0,
|
||||||
click: Optional[Callable] = None) -> None: ...
|
on_click: Optional[Callable] = None) -> None: ...
|
||||||
|
|
||||||
texture: Texture
|
texture: Texture
|
||||||
sprite_index: int
|
sprite_index: int
|
||||||
scale: float
|
scale: float
|
||||||
click: Optional[Callable[[float, float, int], None]]
|
on_click: Optional[Callable[[float, float, int], None]]
|
||||||
w: float # Read-only, computed from texture
|
w: float # Read-only, computed from texture
|
||||||
h: float # Read-only, computed from texture
|
h: float # Read-only, computed from texture
|
||||||
|
|
||||||
class Grid(Drawable):
|
class Grid(Drawable):
|
||||||
"""Grid(x=0, y=0, grid_size=(20, 20), texture=None, tile_width=16, tile_height=16, scale=1.0, click=None)
|
"""Grid(pos=(0,0), size=(0,0), grid_size=(2,2), texture=None, ...)
|
||||||
|
|
||||||
A grid-based tilemap UI element for rendering tile-based levels and game worlds.
|
A grid-based tilemap UI element for rendering tile-based levels and game worlds.
|
||||||
|
Supports layers, FOV, pathfinding, and entity management.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __init__(self) -> None: ...
|
def __init__(self) -> None: ...
|
||||||
@overload
|
@overload
|
||||||
def __init__(self, x: float = 0, y: float = 0, grid_size: Tuple[int, int] = (20, 20),
|
def __init__(self, pos: Tuple[float, float] = (0, 0),
|
||||||
texture: Optional[Texture] = None, tile_width: int = 16, tile_height: int = 16,
|
size: Tuple[float, float] = (0, 0),
|
||||||
scale: float = 1.0, click: Optional[Callable] = None) -> None: ...
|
grid_size: Tuple[int, int] = (2, 2),
|
||||||
|
texture: Optional[Texture] = None,
|
||||||
grid_size: Tuple[int, int]
|
fill_color: Optional[Color] = None,
|
||||||
tile_width: int
|
on_click: Optional[Callable] = None,
|
||||||
tile_height: int
|
center_x: float = 0, center_y: float = 0, zoom: float = 1.0,
|
||||||
texture: Texture
|
visible: bool = True, opacity: float = 1.0,
|
||||||
scale: float
|
z_index: int = 0, name: str = '') -> None: ...
|
||||||
points: List[List['GridPoint']]
|
|
||||||
entities: 'EntityCollection'
|
# Dimensions
|
||||||
background_color: Color
|
grid_size: Tuple[int, int] # Read-only (grid_w, grid_h)
|
||||||
click: Optional[Callable[[int, int, int], None]]
|
grid_w: int # Read-only
|
||||||
|
grid_h: int # Read-only
|
||||||
|
|
||||||
|
# Position and size
|
||||||
|
position: Tuple[float, float]
|
||||||
|
size: Vector
|
||||||
|
w: float
|
||||||
|
h: float
|
||||||
|
|
||||||
|
# Camera/viewport
|
||||||
|
center: Vector # Viewport center point (pan position)
|
||||||
|
center_x: float
|
||||||
|
center_y: float
|
||||||
|
zoom: float # Scale factor for rendering
|
||||||
|
|
||||||
|
# Collections
|
||||||
|
entities: 'EntityCollection' # Entities on this grid
|
||||||
|
children: 'UICollection' # UI overlays (speech bubbles, effects)
|
||||||
|
layers: List[Union['ColorLayer', 'TileLayer']] # Grid layers sorted by z_index
|
||||||
|
|
||||||
|
# Appearance
|
||||||
|
texture: Texture # Read-only
|
||||||
|
fill_color: Color # Background fill color
|
||||||
|
|
||||||
|
# Perspective/FOV
|
||||||
|
perspective: Optional['Entity'] # Entity for FOV rendering (None = omniscient)
|
||||||
|
perspective_enabled: bool # Whether to use perspective-based FOV
|
||||||
|
fov: 'FOV' # FOV algorithm enum
|
||||||
|
fov_radius: int # Default FOV radius
|
||||||
|
|
||||||
|
# Cell-level mouse events
|
||||||
|
on_cell_enter: Optional[Callable[['Vector'], None]]
|
||||||
|
on_cell_exit: Optional[Callable[['Vector'], None]]
|
||||||
|
on_cell_click: Optional[Callable[['Vector'], None]]
|
||||||
|
hovered_cell: Optional[Tuple[int, int]] # Read-only
|
||||||
|
|
||||||
def at(self, x: int, y: int) -> 'GridPoint':
|
def at(self, x: int, y: int) -> 'GridPoint':
|
||||||
"""Get grid point at tile coordinates."""
|
"""Get grid point at tile coordinates."""
|
||||||
...
|
...
|
||||||
|
|
||||||
class GridPoint:
|
def center_camera(self, pos: Optional[Tuple[float, float]] = None) -> None:
|
||||||
"""Grid point representing a single tile."""
|
"""Center the camera on a tile coordinate."""
|
||||||
|
...
|
||||||
texture_index: int
|
|
||||||
solid: bool
|
# FOV methods
|
||||||
|
def compute_fov(self, pos: Tuple[int, int], radius: int = 0,
|
||||||
|
light_walls: bool = True, algorithm: Optional['FOV'] = None) -> None:
|
||||||
|
"""Compute field of view from a position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def is_in_fov(self, pos: Tuple[int, int]) -> bool:
|
||||||
|
"""Check if a cell is in the field of view."""
|
||||||
|
...
|
||||||
|
|
||||||
|
# Pathfinding methods
|
||||||
|
def find_path(self, start: Union[Tuple[int, int], 'Vector', 'Entity'],
|
||||||
|
end: Union[Tuple[int, int], 'Vector', 'Entity'],
|
||||||
|
diagonal_cost: float = 1.41) -> Optional['AStarPath']:
|
||||||
|
"""Compute A* path between two points."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_dijkstra_map(self, root: Union[Tuple[int, int], 'Vector', 'Entity'],
|
||||||
|
diagonal_cost: float = 1.41) -> 'DijkstraMap':
|
||||||
|
"""Get or create a Dijkstra distance map for a root position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def clear_dijkstra_maps(self) -> None:
|
||||||
|
"""Clear all cached Dijkstra maps."""
|
||||||
|
...
|
||||||
|
|
||||||
|
# Layer methods
|
||||||
|
def add_layer(self, type: str, z_index: int = -1,
|
||||||
|
texture: Optional[Texture] = None) -> Union['ColorLayer', 'TileLayer']:
|
||||||
|
"""Add a new layer to the grid."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def remove_layer(self, layer: Union['ColorLayer', 'TileLayer']) -> None:
|
||||||
|
"""Remove a layer from the grid."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def layer(self, z_index: int) -> Optional[Union['ColorLayer', 'TileLayer']]:
|
||||||
|
"""Get layer by z_index."""
|
||||||
|
...
|
||||||
|
|
||||||
|
# Spatial queries
|
||||||
|
def entities_in_radius(self, pos: Union[Tuple[float, float], 'Vector'],
|
||||||
|
radius: float) -> List['Entity']:
|
||||||
|
"""Query entities within radius using spatial hash."""
|
||||||
|
...
|
||||||
|
|
||||||
|
# HeightMap application
|
||||||
|
def apply_threshold(self, source: 'HeightMap', range: Tuple[float, float],
|
||||||
|
walkable: Optional[bool] = None,
|
||||||
|
transparent: Optional[bool] = None) -> 'Grid':
|
||||||
|
"""Apply walkable/transparent properties where heightmap values are in range."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def apply_ranges(self, source: 'HeightMap',
|
||||||
|
ranges: List[Tuple[Tuple[float, float], Dict[str, bool]]]) -> 'Grid':
|
||||||
|
"""Apply multiple thresholds in a single pass."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class Line(Drawable):
|
||||||
|
"""Line(start=None, end=None, thickness=1.0, color=None, on_click=None, **kwargs)
|
||||||
|
|
||||||
|
A line UI element for drawing straight lines between two points.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def __init__(self) -> None: ...
|
||||||
|
@overload
|
||||||
|
def __init__(self, start: Optional[Tuple[float, float]] = None,
|
||||||
|
end: Optional[Tuple[float, float]] = None,
|
||||||
|
thickness: float = 1.0, color: Optional[Color] = None,
|
||||||
|
on_click: Optional[Callable] = None) -> None: ...
|
||||||
|
|
||||||
|
start: Vector
|
||||||
|
end: Vector
|
||||||
|
thickness: float
|
||||||
color: Color
|
color: Color
|
||||||
|
on_click: Optional[Callable[[float, float, int], None]]
|
||||||
|
|
||||||
|
class Circle(Drawable):
|
||||||
|
"""Circle(radius=0, center=None, fill_color=None, outline_color=None, outline=0, on_click=None, **kwargs)
|
||||||
|
|
||||||
|
A circle UI element for drawing filled or outlined circles.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def __init__(self) -> None: ...
|
||||||
|
@overload
|
||||||
|
def __init__(self, radius: float = 0, center: Optional[Tuple[float, float]] = None,
|
||||||
|
fill_color: Optional[Color] = None, outline_color: Optional[Color] = None,
|
||||||
|
outline: float = 0, on_click: Optional[Callable] = None) -> None: ...
|
||||||
|
|
||||||
|
radius: float
|
||||||
|
center: Vector
|
||||||
|
fill_color: Color
|
||||||
|
outline_color: Color
|
||||||
|
outline: float
|
||||||
|
on_click: Optional[Callable[[float, float, int], None]]
|
||||||
|
|
||||||
|
class Arc(Drawable):
|
||||||
|
"""Arc(center=None, radius=0, start_angle=0, end_angle=90, color=None, thickness=1, on_click=None, **kwargs)
|
||||||
|
|
||||||
|
An arc UI element for drawing curved line segments.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def __init__(self) -> None: ...
|
||||||
|
@overload
|
||||||
|
def __init__(self, center: Optional[Tuple[float, float]] = None, radius: float = 0,
|
||||||
|
start_angle: float = 0, end_angle: float = 90,
|
||||||
|
color: Optional[Color] = None, thickness: float = 1.0,
|
||||||
|
on_click: Optional[Callable] = None) -> None: ...
|
||||||
|
|
||||||
|
center: Vector
|
||||||
|
radius: float
|
||||||
|
start_angle: float
|
||||||
|
end_angle: float
|
||||||
|
color: Color
|
||||||
|
thickness: float
|
||||||
|
on_click: Optional[Callable[[float, float, int], None]]
|
||||||
|
|
||||||
|
class GridPoint:
|
||||||
|
"""Grid point representing a single tile's properties.
|
||||||
|
|
||||||
|
Accessed via Grid.at(x, y). Controls walkability and transparency
|
||||||
|
for pathfinding and FOV calculations.
|
||||||
|
"""
|
||||||
|
|
||||||
|
walkable: bool # Whether entities can walk through this cell
|
||||||
|
transparent: bool # Whether light/sight passes through this cell
|
||||||
|
entities: List['Entity'] # Read-only list of entities at this cell
|
||||||
|
grid_pos: Tuple[int, int] # Read-only (x, y) position in grid
|
||||||
|
|
||||||
class GridPointState:
|
class GridPointState:
|
||||||
"""State information for a grid point."""
|
"""Per-entity visibility state for a grid cell.
|
||||||
|
|
||||||
texture_index: int
|
Tracks what an entity has seen/discovered. Accessed via entity perspective system.
|
||||||
color: Color
|
"""
|
||||||
|
|
||||||
|
visible: bool # Currently visible in FOV
|
||||||
|
discovered: bool # Has been seen at least once
|
||||||
|
point: Optional['GridPoint'] # The GridPoint at this position (None if not discovered)
|
||||||
|
|
||||||
|
class ColorLayer:
|
||||||
|
"""A color overlay layer for Grid.
|
||||||
|
|
||||||
|
Provides per-cell color values for tinting, fog of war, etc.
|
||||||
|
"""
|
||||||
|
|
||||||
|
z_index: int
|
||||||
|
grid: 'Grid' # Read-only parent grid
|
||||||
|
|
||||||
|
def fill(self, color: Color) -> None:
|
||||||
|
"""Fill entire layer with a single color."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def set_color(self, pos: Tuple[int, int], color: Color) -> None:
|
||||||
|
"""Set color at a specific cell."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_color(self, pos: Tuple[int, int]) -> Color:
|
||||||
|
"""Get color at a specific cell."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class TileLayer:
|
||||||
|
"""A tile sprite layer for Grid.
|
||||||
|
|
||||||
|
Provides per-cell tile indices for multi-layer tile rendering.
|
||||||
|
"""
|
||||||
|
|
||||||
|
z_index: int
|
||||||
|
grid: 'Grid' # Read-only parent grid
|
||||||
|
texture: Optional[Texture]
|
||||||
|
|
||||||
|
def fill(self, tile_index: int) -> None:
|
||||||
|
"""Fill entire layer with a single tile index."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def set_tile(self, pos: Tuple[int, int], tile_index: int) -> None:
|
||||||
|
"""Set tile index at a specific cell."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_tile(self, pos: Tuple[int, int]) -> int:
|
||||||
|
"""Get tile index at a specific cell."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class FOV:
|
||||||
|
"""Field of view algorithm enum.
|
||||||
|
|
||||||
|
Available algorithms:
|
||||||
|
- FOV.BASIC: Simple raycasting
|
||||||
|
- FOV.DIAMOND: Diamond-shaped FOV
|
||||||
|
- FOV.SHADOW: Shadow casting (recommended)
|
||||||
|
- FOV.PERMISSIVE_0 through FOV.PERMISSIVE_8: Permissive algorithms
|
||||||
|
- FOV.RESTRICTIVE: Restrictive precise angle shadowcasting
|
||||||
|
"""
|
||||||
|
|
||||||
|
BASIC: 'FOV'
|
||||||
|
DIAMOND: 'FOV'
|
||||||
|
SHADOW: 'FOV'
|
||||||
|
PERMISSIVE_0: 'FOV'
|
||||||
|
PERMISSIVE_1: 'FOV'
|
||||||
|
PERMISSIVE_2: 'FOV'
|
||||||
|
PERMISSIVE_3: 'FOV'
|
||||||
|
PERMISSIVE_4: 'FOV'
|
||||||
|
PERMISSIVE_5: 'FOV'
|
||||||
|
PERMISSIVE_6: 'FOV'
|
||||||
|
PERMISSIVE_7: 'FOV'
|
||||||
|
PERMISSIVE_8: 'FOV'
|
||||||
|
RESTRICTIVE: 'FOV'
|
||||||
|
|
||||||
|
class AStarPath:
|
||||||
|
"""A* pathfinding result.
|
||||||
|
|
||||||
|
Returned by Grid.find_path(). Can be iterated or walked step-by-step.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __iter__(self) -> Any: ...
|
||||||
|
def __len__(self) -> int: ...
|
||||||
|
|
||||||
|
def walk(self) -> Optional[Tuple[int, int]]:
|
||||||
|
"""Get next step in path, or None if complete."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def reverse(self) -> 'AStarPath':
|
||||||
|
"""Return a reversed copy of the path."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class DijkstraMap:
|
||||||
|
"""Dijkstra distance map for pathfinding.
|
||||||
|
|
||||||
|
Created by Grid.get_dijkstra_map(). Provides distance queries
|
||||||
|
and path finding from the root position.
|
||||||
|
"""
|
||||||
|
|
||||||
|
root: Tuple[int, int] # Read-only root position
|
||||||
|
|
||||||
|
def get_distance(self, pos: Tuple[int, int]) -> float:
|
||||||
|
"""Get distance from root to position (-1 if unreachable)."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_path(self, pos: Tuple[int, int]) -> Optional[List[Tuple[int, int]]]:
|
||||||
|
"""Get path from position to root."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class HeightMap:
|
||||||
|
"""2D height field for terrain generation.
|
||||||
|
|
||||||
|
Used for procedural generation and applying terrain to grids.
|
||||||
|
"""
|
||||||
|
|
||||||
|
width: int # Read-only
|
||||||
|
height: int # Read-only
|
||||||
|
|
||||||
|
def __init__(self, width: int, height: int) -> None: ...
|
||||||
|
|
||||||
|
def get(self, x: int, y: int) -> float:
|
||||||
|
"""Get height value at position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def set(self, x: int, y: int, value: float) -> None:
|
||||||
|
"""Set height value at position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def fill(self, value: float) -> 'HeightMap':
|
||||||
|
"""Fill entire heightmap with a value."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def clear(self) -> 'HeightMap':
|
||||||
|
"""Clear heightmap to 0."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def normalize(self, min_val: float = 0.0, max_val: float = 1.0) -> 'HeightMap':
|
||||||
|
"""Normalize values to range."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def add_hill(self, center: Tuple[float, float], radius: float, height: float) -> 'HeightMap':
|
||||||
|
"""Add a hill at position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def add_fbm(self, noise: 'NoiseSource', mulx: float = 1.0, muly: float = 1.0,
|
||||||
|
addx: float = 0.0, addy: float = 0.0, octaves: int = 4,
|
||||||
|
delta: float = 1.0, scale: float = 1.0) -> 'HeightMap':
|
||||||
|
"""Add fractal Brownian motion noise."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def scale(self, factor: float) -> 'HeightMap':
|
||||||
|
"""Scale all values by factor."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def clamp(self, min_val: float, max_val: float) -> 'HeightMap':
|
||||||
|
"""Clamp values to range."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class NoiseSource:
|
||||||
|
"""Coherent noise generator for procedural generation.
|
||||||
|
|
||||||
|
Supports various noise types: PERLIN, SIMPLEX, WAVELET, etc.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, type: str = 'SIMPLEX', seed: Optional[int] = None) -> None: ...
|
||||||
|
|
||||||
|
def get(self, x: float, y: float, z: float = 0.0) -> float:
|
||||||
|
"""Get noise value at position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class BSP:
|
||||||
|
"""Binary space partitioning for dungeon generation.
|
||||||
|
|
||||||
|
Recursively subdivides a rectangle into rooms.
|
||||||
|
"""
|
||||||
|
|
||||||
|
x: int
|
||||||
|
y: int
|
||||||
|
width: int
|
||||||
|
height: int
|
||||||
|
level: int
|
||||||
|
horizontal: bool
|
||||||
|
position: int
|
||||||
|
|
||||||
|
def __init__(self, x: int, y: int, width: int, height: int) -> None: ...
|
||||||
|
|
||||||
|
def split_recursive(self, randomizer: Optional[Any] = None, nb: int = 8,
|
||||||
|
minHSize: int = 4, minVSize: int = 4,
|
||||||
|
maxHRatio: float = 1.5, maxVRatio: float = 1.5) -> None:
|
||||||
|
"""Recursively split the BSP tree."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def traverse(self, callback: Callable[['BSP'], bool],
|
||||||
|
order: str = 'PRE_ORDER') -> None:
|
||||||
|
"""Traverse BSP tree calling callback for each node."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def is_leaf(self) -> bool:
|
||||||
|
"""Check if this is a leaf node (no children)."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def contains(self, x: int, y: int) -> bool:
|
||||||
|
"""Check if point is within this node's bounds."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_left(self) -> Optional['BSP']:
|
||||||
|
"""Get left child node."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_right(self) -> Optional['BSP']:
|
||||||
|
"""Get right child node."""
|
||||||
|
...
|
||||||
|
|
||||||
class Entity(Drawable):
|
class Entity(Drawable):
|
||||||
"""Entity(grid_x=0, grid_y=0, texture=None, sprite_index=0, name='')
|
"""Entity(grid_x=0, grid_y=0, texture=None, sprite_index=0, name='')
|
||||||
|
|
@ -232,7 +615,7 @@ class Entity(Drawable):
|
||||||
...
|
...
|
||||||
|
|
||||||
class UICollection:
|
class UICollection:
|
||||||
"""Collection of UI drawable elements (Frame, Caption, Sprite, Grid)."""
|
"""Collection of UI drawable elements (Frame, Caption, Sprite, Grid, Line, Circle, Arc)."""
|
||||||
|
|
||||||
def __len__(self) -> int: ...
|
def __len__(self) -> int: ...
|
||||||
def __getitem__(self, index: int) -> UIElement: ...
|
def __getitem__(self, index: int) -> UIElement: ...
|
||||||
|
|
@ -269,45 +652,47 @@ class EntityCollection:
|
||||||
|
|
||||||
class Scene:
|
class Scene:
|
||||||
"""Base class for object-oriented scenes."""
|
"""Base class for object-oriented scenes."""
|
||||||
|
|
||||||
name: str
|
name: str
|
||||||
|
children: UICollection # #151: UI elements collection (read-only alias for get_ui())
|
||||||
|
on_key: Optional[Callable[[str, str], None]] # Keyboard handler (key, action)
|
||||||
|
|
||||||
def __init__(self, name: str) -> None: ...
|
def __init__(self, name: str) -> None: ...
|
||||||
|
|
||||||
def activate(self) -> None:
|
def activate(self) -> None:
|
||||||
"""Called when scene becomes active."""
|
"""Called when scene becomes active."""
|
||||||
...
|
...
|
||||||
|
|
||||||
def deactivate(self) -> None:
|
def deactivate(self) -> None:
|
||||||
"""Called when scene becomes inactive."""
|
"""Called when scene becomes inactive."""
|
||||||
...
|
...
|
||||||
|
|
||||||
def get_ui(self) -> UICollection:
|
def get_ui(self) -> UICollection:
|
||||||
"""Get UI elements collection."""
|
"""Get UI elements collection."""
|
||||||
...
|
...
|
||||||
|
|
||||||
def on_keypress(self, key: str, pressed: bool) -> None:
|
def on_keypress(self, key: str, pressed: bool) -> None:
|
||||||
"""Handle keyboard events."""
|
"""Handle keyboard events (override in subclass)."""
|
||||||
...
|
...
|
||||||
|
|
||||||
def on_click(self, x: float, y: float, button: int) -> None:
|
def on_click(self, x: float, y: float, button: int) -> None:
|
||||||
"""Handle mouse clicks."""
|
"""Handle mouse clicks (override in subclass)."""
|
||||||
...
|
...
|
||||||
|
|
||||||
def on_enter(self) -> None:
|
def on_enter(self) -> None:
|
||||||
"""Called when entering the scene."""
|
"""Called when entering the scene (override in subclass)."""
|
||||||
...
|
...
|
||||||
|
|
||||||
def on_exit(self) -> None:
|
def on_exit(self) -> None:
|
||||||
"""Called when leaving the scene."""
|
"""Called when leaving the scene (override in subclass)."""
|
||||||
...
|
...
|
||||||
|
|
||||||
def on_resize(self, width: int, height: int) -> None:
|
def on_resize(self, width: int, height: int) -> None:
|
||||||
"""Handle window resize events."""
|
"""Handle window resize events (override in subclass)."""
|
||||||
...
|
...
|
||||||
|
|
||||||
def update(self, dt: float) -> None:
|
def update(self, dt: float) -> None:
|
||||||
"""Update scene logic."""
|
"""Update scene logic (override in subclass)."""
|
||||||
...
|
...
|
||||||
|
|
||||||
class Timer:
|
class Timer:
|
||||||
|
|
|
||||||
356
stubs/mcrfpy.pyi
356
stubs/mcrfpy.pyi
|
|
@ -171,32 +171,129 @@ class Sprite(Drawable):
|
||||||
h: float # Read-only, computed from texture
|
h: float # Read-only, computed from texture
|
||||||
|
|
||||||
class Grid(Drawable):
|
class Grid(Drawable):
|
||||||
"""Grid(x=0, y=0, grid_size=(20, 20), texture=None, tile_width=16, tile_height=16, scale=1.0, on_click=None)
|
"""Grid(pos=(0,0), size=(0,0), grid_size=(2,2), texture=None, ...)
|
||||||
|
|
||||||
A grid-based tilemap UI element for rendering tile-based levels and game worlds.
|
A grid-based tilemap UI element for rendering tile-based levels and game worlds.
|
||||||
|
Supports layers, FOV, pathfinding, and entity management.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __init__(self) -> None: ...
|
def __init__(self) -> None: ...
|
||||||
@overload
|
@overload
|
||||||
def __init__(self, x: float = 0, y: float = 0, grid_size: Tuple[int, int] = (20, 20),
|
def __init__(self, pos: Tuple[float, float] = (0, 0),
|
||||||
texture: Optional[Texture] = None, tile_width: int = 16, tile_height: int = 16,
|
size: Tuple[float, float] = (0, 0),
|
||||||
scale: float = 1.0, on_click: Optional[Callable] = None) -> None: ...
|
grid_size: Tuple[int, int] = (2, 2),
|
||||||
|
texture: Optional[Texture] = None,
|
||||||
|
fill_color: Optional[Color] = None,
|
||||||
|
on_click: Optional[Callable] = None,
|
||||||
|
center_x: float = 0, center_y: float = 0, zoom: float = 1.0,
|
||||||
|
visible: bool = True, opacity: float = 1.0,
|
||||||
|
z_index: int = 0, name: str = '') -> None: ...
|
||||||
|
|
||||||
grid_size: Tuple[int, int]
|
# Dimensions
|
||||||
tile_width: int
|
grid_size: Tuple[int, int] # Read-only (grid_w, grid_h)
|
||||||
tile_height: int
|
grid_w: int # Read-only
|
||||||
texture: Texture
|
grid_h: int # Read-only
|
||||||
scale: float
|
|
||||||
points: List[List['GridPoint']]
|
# Position and size
|
||||||
entities: 'EntityCollection'
|
position: Tuple[float, float]
|
||||||
background_color: Color
|
size: Vector
|
||||||
on_click: Optional[Callable[[int, int, int], None]]
|
w: float
|
||||||
|
h: float
|
||||||
|
|
||||||
|
# Camera/viewport
|
||||||
|
center: Vector # Viewport center point (pan position)
|
||||||
|
center_x: float
|
||||||
|
center_y: float
|
||||||
|
zoom: float # Scale factor for rendering
|
||||||
|
|
||||||
|
# Collections
|
||||||
|
entities: 'EntityCollection' # Entities on this grid
|
||||||
|
children: 'UICollection' # UI overlays (speech bubbles, effects)
|
||||||
|
layers: List[Union['ColorLayer', 'TileLayer']] # Grid layers sorted by z_index
|
||||||
|
|
||||||
|
# Appearance
|
||||||
|
texture: Texture # Read-only
|
||||||
|
fill_color: Color # Background fill color
|
||||||
|
|
||||||
|
# Perspective/FOV
|
||||||
|
perspective: Optional['Entity'] # Entity for FOV rendering (None = omniscient)
|
||||||
|
perspective_enabled: bool # Whether to use perspective-based FOV
|
||||||
|
fov: 'FOV' # FOV algorithm enum
|
||||||
|
fov_radius: int # Default FOV radius
|
||||||
|
|
||||||
|
# Cell-level mouse events
|
||||||
|
on_cell_enter: Optional[Callable[['Vector'], None]]
|
||||||
|
on_cell_exit: Optional[Callable[['Vector'], None]]
|
||||||
|
on_cell_click: Optional[Callable[['Vector'], None]]
|
||||||
|
hovered_cell: Optional[Tuple[int, int]] # Read-only
|
||||||
|
|
||||||
def at(self, x: int, y: int) -> 'GridPoint':
|
def at(self, x: int, y: int) -> 'GridPoint':
|
||||||
"""Get grid point at tile coordinates."""
|
"""Get grid point at tile coordinates."""
|
||||||
...
|
...
|
||||||
|
|
||||||
|
def center_camera(self, pos: Optional[Tuple[float, float]] = None) -> None:
|
||||||
|
"""Center the camera on a tile coordinate."""
|
||||||
|
...
|
||||||
|
|
||||||
|
# FOV methods
|
||||||
|
def compute_fov(self, pos: Tuple[int, int], radius: int = 0,
|
||||||
|
light_walls: bool = True, algorithm: Optional['FOV'] = None) -> None:
|
||||||
|
"""Compute field of view from a position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def is_in_fov(self, pos: Tuple[int, int]) -> bool:
|
||||||
|
"""Check if a cell is in the field of view."""
|
||||||
|
...
|
||||||
|
|
||||||
|
# Pathfinding methods
|
||||||
|
def find_path(self, start: Union[Tuple[int, int], 'Vector', 'Entity'],
|
||||||
|
end: Union[Tuple[int, int], 'Vector', 'Entity'],
|
||||||
|
diagonal_cost: float = 1.41) -> Optional['AStarPath']:
|
||||||
|
"""Compute A* path between two points."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_dijkstra_map(self, root: Union[Tuple[int, int], 'Vector', 'Entity'],
|
||||||
|
diagonal_cost: float = 1.41) -> 'DijkstraMap':
|
||||||
|
"""Get or create a Dijkstra distance map for a root position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def clear_dijkstra_maps(self) -> None:
|
||||||
|
"""Clear all cached Dijkstra maps."""
|
||||||
|
...
|
||||||
|
|
||||||
|
# Layer methods
|
||||||
|
def add_layer(self, type: str, z_index: int = -1,
|
||||||
|
texture: Optional[Texture] = None) -> Union['ColorLayer', 'TileLayer']:
|
||||||
|
"""Add a new layer to the grid."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def remove_layer(self, layer: Union['ColorLayer', 'TileLayer']) -> None:
|
||||||
|
"""Remove a layer from the grid."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def layer(self, z_index: int) -> Optional[Union['ColorLayer', 'TileLayer']]:
|
||||||
|
"""Get layer by z_index."""
|
||||||
|
...
|
||||||
|
|
||||||
|
# Spatial queries
|
||||||
|
def entities_in_radius(self, pos: Union[Tuple[float, float], 'Vector'],
|
||||||
|
radius: float) -> List['Entity']:
|
||||||
|
"""Query entities within radius using spatial hash."""
|
||||||
|
...
|
||||||
|
|
||||||
|
# HeightMap application
|
||||||
|
def apply_threshold(self, source: 'HeightMap', range: Tuple[float, float],
|
||||||
|
walkable: Optional[bool] = None,
|
||||||
|
transparent: Optional[bool] = None) -> 'Grid':
|
||||||
|
"""Apply walkable/transparent properties where heightmap values are in range."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def apply_ranges(self, source: 'HeightMap',
|
||||||
|
ranges: List[Tuple[Tuple[float, float], Dict[str, bool]]]) -> 'Grid':
|
||||||
|
"""Apply multiple thresholds in a single pass."""
|
||||||
|
...
|
||||||
|
|
||||||
class Line(Drawable):
|
class Line(Drawable):
|
||||||
"""Line(start=None, end=None, thickness=1.0, color=None, on_click=None, **kwargs)
|
"""Line(start=None, end=None, thickness=1.0, color=None, on_click=None, **kwargs)
|
||||||
|
|
||||||
|
|
@ -260,17 +357,232 @@ class Arc(Drawable):
|
||||||
on_click: Optional[Callable[[float, float, int], None]]
|
on_click: Optional[Callable[[float, float, int], None]]
|
||||||
|
|
||||||
class GridPoint:
|
class GridPoint:
|
||||||
"""Grid point representing a single tile."""
|
"""Grid point representing a single tile's properties.
|
||||||
|
|
||||||
texture_index: int
|
Accessed via Grid.at(x, y). Controls walkability and transparency
|
||||||
solid: bool
|
for pathfinding and FOV calculations.
|
||||||
color: Color
|
"""
|
||||||
|
|
||||||
|
walkable: bool # Whether entities can walk through this cell
|
||||||
|
transparent: bool # Whether light/sight passes through this cell
|
||||||
|
entities: List['Entity'] # Read-only list of entities at this cell
|
||||||
|
grid_pos: Tuple[int, int] # Read-only (x, y) position in grid
|
||||||
|
|
||||||
class GridPointState:
|
class GridPointState:
|
||||||
"""State information for a grid point."""
|
"""Per-entity visibility state for a grid cell.
|
||||||
|
|
||||||
texture_index: int
|
Tracks what an entity has seen/discovered. Accessed via entity perspective system.
|
||||||
color: Color
|
"""
|
||||||
|
|
||||||
|
visible: bool # Currently visible in FOV
|
||||||
|
discovered: bool # Has been seen at least once
|
||||||
|
point: Optional['GridPoint'] # The GridPoint at this position (None if not discovered)
|
||||||
|
|
||||||
|
class ColorLayer:
|
||||||
|
"""A color overlay layer for Grid.
|
||||||
|
|
||||||
|
Provides per-cell color values for tinting, fog of war, etc.
|
||||||
|
"""
|
||||||
|
|
||||||
|
z_index: int
|
||||||
|
grid: 'Grid' # Read-only parent grid
|
||||||
|
|
||||||
|
def fill(self, color: Color) -> None:
|
||||||
|
"""Fill entire layer with a single color."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def set_color(self, pos: Tuple[int, int], color: Color) -> None:
|
||||||
|
"""Set color at a specific cell."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_color(self, pos: Tuple[int, int]) -> Color:
|
||||||
|
"""Get color at a specific cell."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class TileLayer:
|
||||||
|
"""A tile sprite layer for Grid.
|
||||||
|
|
||||||
|
Provides per-cell tile indices for multi-layer tile rendering.
|
||||||
|
"""
|
||||||
|
|
||||||
|
z_index: int
|
||||||
|
grid: 'Grid' # Read-only parent grid
|
||||||
|
texture: Optional[Texture]
|
||||||
|
|
||||||
|
def fill(self, tile_index: int) -> None:
|
||||||
|
"""Fill entire layer with a single tile index."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def set_tile(self, pos: Tuple[int, int], tile_index: int) -> None:
|
||||||
|
"""Set tile index at a specific cell."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_tile(self, pos: Tuple[int, int]) -> int:
|
||||||
|
"""Get tile index at a specific cell."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class FOV:
|
||||||
|
"""Field of view algorithm enum.
|
||||||
|
|
||||||
|
Available algorithms:
|
||||||
|
- FOV.BASIC: Simple raycasting
|
||||||
|
- FOV.DIAMOND: Diamond-shaped FOV
|
||||||
|
- FOV.SHADOW: Shadow casting (recommended)
|
||||||
|
- FOV.PERMISSIVE_0 through FOV.PERMISSIVE_8: Permissive algorithms
|
||||||
|
- FOV.RESTRICTIVE: Restrictive precise angle shadowcasting
|
||||||
|
"""
|
||||||
|
|
||||||
|
BASIC: 'FOV'
|
||||||
|
DIAMOND: 'FOV'
|
||||||
|
SHADOW: 'FOV'
|
||||||
|
PERMISSIVE_0: 'FOV'
|
||||||
|
PERMISSIVE_1: 'FOV'
|
||||||
|
PERMISSIVE_2: 'FOV'
|
||||||
|
PERMISSIVE_3: 'FOV'
|
||||||
|
PERMISSIVE_4: 'FOV'
|
||||||
|
PERMISSIVE_5: 'FOV'
|
||||||
|
PERMISSIVE_6: 'FOV'
|
||||||
|
PERMISSIVE_7: 'FOV'
|
||||||
|
PERMISSIVE_8: 'FOV'
|
||||||
|
RESTRICTIVE: 'FOV'
|
||||||
|
|
||||||
|
class AStarPath:
|
||||||
|
"""A* pathfinding result.
|
||||||
|
|
||||||
|
Returned by Grid.find_path(). Can be iterated or walked step-by-step.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __iter__(self) -> Any: ...
|
||||||
|
def __len__(self) -> int: ...
|
||||||
|
|
||||||
|
def walk(self) -> Optional[Tuple[int, int]]:
|
||||||
|
"""Get next step in path, or None if complete."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def reverse(self) -> 'AStarPath':
|
||||||
|
"""Return a reversed copy of the path."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class DijkstraMap:
|
||||||
|
"""Dijkstra distance map for pathfinding.
|
||||||
|
|
||||||
|
Created by Grid.get_dijkstra_map(). Provides distance queries
|
||||||
|
and path finding from the root position.
|
||||||
|
"""
|
||||||
|
|
||||||
|
root: Tuple[int, int] # Read-only root position
|
||||||
|
|
||||||
|
def get_distance(self, pos: Tuple[int, int]) -> float:
|
||||||
|
"""Get distance from root to position (-1 if unreachable)."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_path(self, pos: Tuple[int, int]) -> Optional[List[Tuple[int, int]]]:
|
||||||
|
"""Get path from position to root."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class HeightMap:
|
||||||
|
"""2D height field for terrain generation.
|
||||||
|
|
||||||
|
Used for procedural generation and applying terrain to grids.
|
||||||
|
"""
|
||||||
|
|
||||||
|
width: int # Read-only
|
||||||
|
height: int # Read-only
|
||||||
|
|
||||||
|
def __init__(self, width: int, height: int) -> None: ...
|
||||||
|
|
||||||
|
def get(self, x: int, y: int) -> float:
|
||||||
|
"""Get height value at position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def set(self, x: int, y: int, value: float) -> None:
|
||||||
|
"""Set height value at position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def fill(self, value: float) -> 'HeightMap':
|
||||||
|
"""Fill entire heightmap with a value."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def clear(self) -> 'HeightMap':
|
||||||
|
"""Clear heightmap to 0."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def normalize(self, min_val: float = 0.0, max_val: float = 1.0) -> 'HeightMap':
|
||||||
|
"""Normalize values to range."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def add_hill(self, center: Tuple[float, float], radius: float, height: float) -> 'HeightMap':
|
||||||
|
"""Add a hill at position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def add_fbm(self, noise: 'NoiseSource', mulx: float = 1.0, muly: float = 1.0,
|
||||||
|
addx: float = 0.0, addy: float = 0.0, octaves: int = 4,
|
||||||
|
delta: float = 1.0, scale: float = 1.0) -> 'HeightMap':
|
||||||
|
"""Add fractal Brownian motion noise."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def scale(self, factor: float) -> 'HeightMap':
|
||||||
|
"""Scale all values by factor."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def clamp(self, min_val: float, max_val: float) -> 'HeightMap':
|
||||||
|
"""Clamp values to range."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class NoiseSource:
|
||||||
|
"""Coherent noise generator for procedural generation.
|
||||||
|
|
||||||
|
Supports various noise types: PERLIN, SIMPLEX, WAVELET, etc.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, type: str = 'SIMPLEX', seed: Optional[int] = None) -> None: ...
|
||||||
|
|
||||||
|
def get(self, x: float, y: float, z: float = 0.0) -> float:
|
||||||
|
"""Get noise value at position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class BSP:
|
||||||
|
"""Binary space partitioning for dungeon generation.
|
||||||
|
|
||||||
|
Recursively subdivides a rectangle into rooms.
|
||||||
|
"""
|
||||||
|
|
||||||
|
x: int
|
||||||
|
y: int
|
||||||
|
width: int
|
||||||
|
height: int
|
||||||
|
level: int
|
||||||
|
horizontal: bool
|
||||||
|
position: int
|
||||||
|
|
||||||
|
def __init__(self, x: int, y: int, width: int, height: int) -> None: ...
|
||||||
|
|
||||||
|
def split_recursive(self, randomizer: Optional[Any] = None, nb: int = 8,
|
||||||
|
minHSize: int = 4, minVSize: int = 4,
|
||||||
|
maxHRatio: float = 1.5, maxVRatio: float = 1.5) -> None:
|
||||||
|
"""Recursively split the BSP tree."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def traverse(self, callback: Callable[['BSP'], bool],
|
||||||
|
order: str = 'PRE_ORDER') -> None:
|
||||||
|
"""Traverse BSP tree calling callback for each node."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def is_leaf(self) -> bool:
|
||||||
|
"""Check if this is a leaf node (no children)."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def contains(self, x: int, y: int) -> bool:
|
||||||
|
"""Check if point is within this node's bounds."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_left(self) -> Optional['BSP']:
|
||||||
|
"""Get left child node."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_right(self) -> Optional['BSP']:
|
||||||
|
"""Get right child node."""
|
||||||
|
...
|
||||||
|
|
||||||
class Entity(Drawable):
|
class Entity(Drawable):
|
||||||
"""Entity(grid_x=0, grid_y=0, texture=None, sprite_index=0, name='')
|
"""Entity(grid_x=0, grid_y=0, texture=None, sprite_index=0, name='')
|
||||||
|
|
|
||||||
|
|
@ -183,32 +183,129 @@ class Sprite(Drawable):
|
||||||
h: float # Read-only, computed from texture
|
h: float # Read-only, computed from texture
|
||||||
|
|
||||||
class Grid(Drawable):
|
class Grid(Drawable):
|
||||||
"""Grid(x=0, y=0, grid_size=(20, 20), texture=None, tile_width=16, tile_height=16, scale=1.0, on_click=None)
|
"""Grid(pos=(0,0), size=(0,0), grid_size=(2,2), texture=None, ...)
|
||||||
|
|
||||||
A grid-based tilemap UI element for rendering tile-based levels and game worlds.
|
A grid-based tilemap UI element for rendering tile-based levels and game worlds.
|
||||||
|
Supports layers, FOV, pathfinding, and entity management.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __init__(self) -> None: ...
|
def __init__(self) -> None: ...
|
||||||
@overload
|
@overload
|
||||||
def __init__(self, x: float = 0, y: float = 0, grid_size: Tuple[int, int] = (20, 20),
|
def __init__(self, pos: Tuple[float, float] = (0, 0),
|
||||||
texture: Optional[Texture] = None, tile_width: int = 16, tile_height: int = 16,
|
size: Tuple[float, float] = (0, 0),
|
||||||
scale: float = 1.0, on_click: Optional[Callable] = None) -> None: ...
|
grid_size: Tuple[int, int] = (2, 2),
|
||||||
|
texture: Optional[Texture] = None,
|
||||||
|
fill_color: Optional[Color] = None,
|
||||||
|
on_click: Optional[Callable] = None,
|
||||||
|
center_x: float = 0, center_y: float = 0, zoom: float = 1.0,
|
||||||
|
visible: bool = True, opacity: float = 1.0,
|
||||||
|
z_index: int = 0, name: str = '') -> None: ...
|
||||||
|
|
||||||
grid_size: Tuple[int, int]
|
# Dimensions
|
||||||
tile_width: int
|
grid_size: Tuple[int, int] # Read-only (grid_w, grid_h)
|
||||||
tile_height: int
|
grid_w: int # Read-only
|
||||||
texture: Texture
|
grid_h: int # Read-only
|
||||||
scale: float
|
|
||||||
points: List[List['GridPoint']]
|
# Position and size
|
||||||
entities: 'EntityCollection'
|
position: Tuple[float, float]
|
||||||
background_color: Color
|
size: Vector
|
||||||
on_click: Optional[Callable[[int, int, int], None]]
|
w: float
|
||||||
|
h: float
|
||||||
|
|
||||||
|
# Camera/viewport
|
||||||
|
center: Vector # Viewport center point (pan position)
|
||||||
|
center_x: float
|
||||||
|
center_y: float
|
||||||
|
zoom: float # Scale factor for rendering
|
||||||
|
|
||||||
|
# Collections
|
||||||
|
entities: 'EntityCollection' # Entities on this grid
|
||||||
|
children: 'UICollection' # UI overlays (speech bubbles, effects)
|
||||||
|
layers: List[Union['ColorLayer', 'TileLayer']] # Grid layers sorted by z_index
|
||||||
|
|
||||||
|
# Appearance
|
||||||
|
texture: Texture # Read-only
|
||||||
|
fill_color: Color # Background fill color
|
||||||
|
|
||||||
|
# Perspective/FOV
|
||||||
|
perspective: Optional['Entity'] # Entity for FOV rendering (None = omniscient)
|
||||||
|
perspective_enabled: bool # Whether to use perspective-based FOV
|
||||||
|
fov: 'FOV' # FOV algorithm enum
|
||||||
|
fov_radius: int # Default FOV radius
|
||||||
|
|
||||||
|
# Cell-level mouse events
|
||||||
|
on_cell_enter: Optional[Callable[['Vector'], None]]
|
||||||
|
on_cell_exit: Optional[Callable[['Vector'], None]]
|
||||||
|
on_cell_click: Optional[Callable[['Vector'], None]]
|
||||||
|
hovered_cell: Optional[Tuple[int, int]] # Read-only
|
||||||
|
|
||||||
def at(self, x: int, y: int) -> 'GridPoint':
|
def at(self, x: int, y: int) -> 'GridPoint':
|
||||||
"""Get grid point at tile coordinates."""
|
"""Get grid point at tile coordinates."""
|
||||||
...
|
...
|
||||||
|
|
||||||
|
def center_camera(self, pos: Optional[Tuple[float, float]] = None) -> None:
|
||||||
|
"""Center the camera on a tile coordinate."""
|
||||||
|
...
|
||||||
|
|
||||||
|
# FOV methods
|
||||||
|
def compute_fov(self, pos: Tuple[int, int], radius: int = 0,
|
||||||
|
light_walls: bool = True, algorithm: Optional['FOV'] = None) -> None:
|
||||||
|
"""Compute field of view from a position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def is_in_fov(self, pos: Tuple[int, int]) -> bool:
|
||||||
|
"""Check if a cell is in the field of view."""
|
||||||
|
...
|
||||||
|
|
||||||
|
# Pathfinding methods
|
||||||
|
def find_path(self, start: Union[Tuple[int, int], 'Vector', 'Entity'],
|
||||||
|
end: Union[Tuple[int, int], 'Vector', 'Entity'],
|
||||||
|
diagonal_cost: float = 1.41) -> Optional['AStarPath']:
|
||||||
|
"""Compute A* path between two points."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_dijkstra_map(self, root: Union[Tuple[int, int], 'Vector', 'Entity'],
|
||||||
|
diagonal_cost: float = 1.41) -> 'DijkstraMap':
|
||||||
|
"""Get or create a Dijkstra distance map for a root position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def clear_dijkstra_maps(self) -> None:
|
||||||
|
"""Clear all cached Dijkstra maps."""
|
||||||
|
...
|
||||||
|
|
||||||
|
# Layer methods
|
||||||
|
def add_layer(self, type: str, z_index: int = -1,
|
||||||
|
texture: Optional[Texture] = None) -> Union['ColorLayer', 'TileLayer']:
|
||||||
|
"""Add a new layer to the grid."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def remove_layer(self, layer: Union['ColorLayer', 'TileLayer']) -> None:
|
||||||
|
"""Remove a layer from the grid."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def layer(self, z_index: int) -> Optional[Union['ColorLayer', 'TileLayer']]:
|
||||||
|
"""Get layer by z_index."""
|
||||||
|
...
|
||||||
|
|
||||||
|
# Spatial queries
|
||||||
|
def entities_in_radius(self, pos: Union[Tuple[float, float], 'Vector'],
|
||||||
|
radius: float) -> List['Entity']:
|
||||||
|
"""Query entities within radius using spatial hash."""
|
||||||
|
...
|
||||||
|
|
||||||
|
# HeightMap application
|
||||||
|
def apply_threshold(self, source: 'HeightMap', range: Tuple[float, float],
|
||||||
|
walkable: Optional[bool] = None,
|
||||||
|
transparent: Optional[bool] = None) -> 'Grid':
|
||||||
|
"""Apply walkable/transparent properties where heightmap values are in range."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def apply_ranges(self, source: 'HeightMap',
|
||||||
|
ranges: List[Tuple[Tuple[float, float], Dict[str, bool]]]) -> 'Grid':
|
||||||
|
"""Apply multiple thresholds in a single pass."""
|
||||||
|
...
|
||||||
|
|
||||||
class Line(Drawable):
|
class Line(Drawable):
|
||||||
"""Line(start=None, end=None, thickness=1.0, color=None, on_click=None, **kwargs)
|
"""Line(start=None, end=None, thickness=1.0, color=None, on_click=None, **kwargs)
|
||||||
|
|
||||||
|
|
@ -272,17 +369,232 @@ class Arc(Drawable):
|
||||||
on_click: Optional[Callable[[float, float, int], None]]
|
on_click: Optional[Callable[[float, float, int], None]]
|
||||||
|
|
||||||
class GridPoint:
|
class GridPoint:
|
||||||
"""Grid point representing a single tile."""
|
"""Grid point representing a single tile's properties.
|
||||||
|
|
||||||
texture_index: int
|
Accessed via Grid.at(x, y). Controls walkability and transparency
|
||||||
solid: bool
|
for pathfinding and FOV calculations.
|
||||||
color: Color
|
"""
|
||||||
|
|
||||||
|
walkable: bool # Whether entities can walk through this cell
|
||||||
|
transparent: bool # Whether light/sight passes through this cell
|
||||||
|
entities: List['Entity'] # Read-only list of entities at this cell
|
||||||
|
grid_pos: Tuple[int, int] # Read-only (x, y) position in grid
|
||||||
|
|
||||||
class GridPointState:
|
class GridPointState:
|
||||||
"""State information for a grid point."""
|
"""Per-entity visibility state for a grid cell.
|
||||||
|
|
||||||
texture_index: int
|
Tracks what an entity has seen/discovered. Accessed via entity perspective system.
|
||||||
color: Color
|
"""
|
||||||
|
|
||||||
|
visible: bool # Currently visible in FOV
|
||||||
|
discovered: bool # Has been seen at least once
|
||||||
|
point: Optional['GridPoint'] # The GridPoint at this position (None if not discovered)
|
||||||
|
|
||||||
|
class ColorLayer:
|
||||||
|
"""A color overlay layer for Grid.
|
||||||
|
|
||||||
|
Provides per-cell color values for tinting, fog of war, etc.
|
||||||
|
"""
|
||||||
|
|
||||||
|
z_index: int
|
||||||
|
grid: 'Grid' # Read-only parent grid
|
||||||
|
|
||||||
|
def fill(self, color: Color) -> None:
|
||||||
|
"""Fill entire layer with a single color."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def set_color(self, pos: Tuple[int, int], color: Color) -> None:
|
||||||
|
"""Set color at a specific cell."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_color(self, pos: Tuple[int, int]) -> Color:
|
||||||
|
"""Get color at a specific cell."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class TileLayer:
|
||||||
|
"""A tile sprite layer for Grid.
|
||||||
|
|
||||||
|
Provides per-cell tile indices for multi-layer tile rendering.
|
||||||
|
"""
|
||||||
|
|
||||||
|
z_index: int
|
||||||
|
grid: 'Grid' # Read-only parent grid
|
||||||
|
texture: Optional[Texture]
|
||||||
|
|
||||||
|
def fill(self, tile_index: int) -> None:
|
||||||
|
"""Fill entire layer with a single tile index."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def set_tile(self, pos: Tuple[int, int], tile_index: int) -> None:
|
||||||
|
"""Set tile index at a specific cell."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_tile(self, pos: Tuple[int, int]) -> int:
|
||||||
|
"""Get tile index at a specific cell."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class FOV:
|
||||||
|
"""Field of view algorithm enum.
|
||||||
|
|
||||||
|
Available algorithms:
|
||||||
|
- FOV.BASIC: Simple raycasting
|
||||||
|
- FOV.DIAMOND: Diamond-shaped FOV
|
||||||
|
- FOV.SHADOW: Shadow casting (recommended)
|
||||||
|
- FOV.PERMISSIVE_0 through FOV.PERMISSIVE_8: Permissive algorithms
|
||||||
|
- FOV.RESTRICTIVE: Restrictive precise angle shadowcasting
|
||||||
|
"""
|
||||||
|
|
||||||
|
BASIC: 'FOV'
|
||||||
|
DIAMOND: 'FOV'
|
||||||
|
SHADOW: 'FOV'
|
||||||
|
PERMISSIVE_0: 'FOV'
|
||||||
|
PERMISSIVE_1: 'FOV'
|
||||||
|
PERMISSIVE_2: 'FOV'
|
||||||
|
PERMISSIVE_3: 'FOV'
|
||||||
|
PERMISSIVE_4: 'FOV'
|
||||||
|
PERMISSIVE_5: 'FOV'
|
||||||
|
PERMISSIVE_6: 'FOV'
|
||||||
|
PERMISSIVE_7: 'FOV'
|
||||||
|
PERMISSIVE_8: 'FOV'
|
||||||
|
RESTRICTIVE: 'FOV'
|
||||||
|
|
||||||
|
class AStarPath:
|
||||||
|
"""A* pathfinding result.
|
||||||
|
|
||||||
|
Returned by Grid.find_path(). Can be iterated or walked step-by-step.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __iter__(self) -> Any: ...
|
||||||
|
def __len__(self) -> int: ...
|
||||||
|
|
||||||
|
def walk(self) -> Optional[Tuple[int, int]]:
|
||||||
|
"""Get next step in path, or None if complete."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def reverse(self) -> 'AStarPath':
|
||||||
|
"""Return a reversed copy of the path."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class DijkstraMap:
|
||||||
|
"""Dijkstra distance map for pathfinding.
|
||||||
|
|
||||||
|
Created by Grid.get_dijkstra_map(). Provides distance queries
|
||||||
|
and path finding from the root position.
|
||||||
|
"""
|
||||||
|
|
||||||
|
root: Tuple[int, int] # Read-only root position
|
||||||
|
|
||||||
|
def get_distance(self, pos: Tuple[int, int]) -> float:
|
||||||
|
"""Get distance from root to position (-1 if unreachable)."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_path(self, pos: Tuple[int, int]) -> Optional[List[Tuple[int, int]]]:
|
||||||
|
"""Get path from position to root."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class HeightMap:
|
||||||
|
"""2D height field for terrain generation.
|
||||||
|
|
||||||
|
Used for procedural generation and applying terrain to grids.
|
||||||
|
"""
|
||||||
|
|
||||||
|
width: int # Read-only
|
||||||
|
height: int # Read-only
|
||||||
|
|
||||||
|
def __init__(self, width: int, height: int) -> None: ...
|
||||||
|
|
||||||
|
def get(self, x: int, y: int) -> float:
|
||||||
|
"""Get height value at position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def set(self, x: int, y: int, value: float) -> None:
|
||||||
|
"""Set height value at position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def fill(self, value: float) -> 'HeightMap':
|
||||||
|
"""Fill entire heightmap with a value."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def clear(self) -> 'HeightMap':
|
||||||
|
"""Clear heightmap to 0."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def normalize(self, min_val: float = 0.0, max_val: float = 1.0) -> 'HeightMap':
|
||||||
|
"""Normalize values to range."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def add_hill(self, center: Tuple[float, float], radius: float, height: float) -> 'HeightMap':
|
||||||
|
"""Add a hill at position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def add_fbm(self, noise: 'NoiseSource', mulx: float = 1.0, muly: float = 1.0,
|
||||||
|
addx: float = 0.0, addy: float = 0.0, octaves: int = 4,
|
||||||
|
delta: float = 1.0, scale: float = 1.0) -> 'HeightMap':
|
||||||
|
"""Add fractal Brownian motion noise."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def scale(self, factor: float) -> 'HeightMap':
|
||||||
|
"""Scale all values by factor."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def clamp(self, min_val: float, max_val: float) -> 'HeightMap':
|
||||||
|
"""Clamp values to range."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class NoiseSource:
|
||||||
|
"""Coherent noise generator for procedural generation.
|
||||||
|
|
||||||
|
Supports various noise types: PERLIN, SIMPLEX, WAVELET, etc.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, type: str = 'SIMPLEX', seed: Optional[int] = None) -> None: ...
|
||||||
|
|
||||||
|
def get(self, x: float, y: float, z: float = 0.0) -> float:
|
||||||
|
"""Get noise value at position."""
|
||||||
|
...
|
||||||
|
|
||||||
|
class BSP:
|
||||||
|
"""Binary space partitioning for dungeon generation.
|
||||||
|
|
||||||
|
Recursively subdivides a rectangle into rooms.
|
||||||
|
"""
|
||||||
|
|
||||||
|
x: int
|
||||||
|
y: int
|
||||||
|
width: int
|
||||||
|
height: int
|
||||||
|
level: int
|
||||||
|
horizontal: bool
|
||||||
|
position: int
|
||||||
|
|
||||||
|
def __init__(self, x: int, y: int, width: int, height: int) -> None: ...
|
||||||
|
|
||||||
|
def split_recursive(self, randomizer: Optional[Any] = None, nb: int = 8,
|
||||||
|
minHSize: int = 4, minVSize: int = 4,
|
||||||
|
maxHRatio: float = 1.5, maxVRatio: float = 1.5) -> None:
|
||||||
|
"""Recursively split the BSP tree."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def traverse(self, callback: Callable[['BSP'], bool],
|
||||||
|
order: str = 'PRE_ORDER') -> None:
|
||||||
|
"""Traverse BSP tree calling callback for each node."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def is_leaf(self) -> bool:
|
||||||
|
"""Check if this is a leaf node (no children)."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def contains(self, x: int, y: int) -> bool:
|
||||||
|
"""Check if point is within this node's bounds."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_left(self) -> Optional['BSP']:
|
||||||
|
"""Get left child node."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def get_right(self) -> Optional['BSP']:
|
||||||
|
"""Get right child node."""
|
||||||
|
...
|
||||||
|
|
||||||
class Entity(Drawable):
|
class Entity(Drawable):
|
||||||
"""Entity(grid_x=0, grid_y=0, texture=None, sprite_index=0, name='')
|
"""Entity(grid_x=0, grid_y=0, texture=None, sprite_index=0, name='')
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue