Module Functions
Top-level functions in the mcrfpy module.
mcrfpy.bresenham(start, end, include_start=True, include_end=True) -> list[tuple[int, int]]
bresenham(start, end, include_start=True, include_end=True) -> list[tuple[int, int]]
Compute grid cells along a line using Bresenham’s algorithm.
Args: start: (x, y) tuple or Vector - starting point end: (x, y) tuple or Vector - ending point include_start: Include the starting point in results (default: True) include_end: Include the ending point in results (default: True)
Returns: list[tuple[int, int]]: List of (x, y) grid coordinates along the line
Note: Useful for line-of-sight checks, projectile paths, and drawing lines on grids. The algorithm ensures minimal grid traversal between two points.
mcrfpy.end_benchmark() -> str
end_benchmark() -> str
Stop benchmark capture and write data to JSON file.
Returns: str: The filename of the written benchmark data
Raises: RuntimeError: If no benchmark is currently running
Note: Returns the auto-generated filename (e.g., ‘benchmark_12345_20250528_143022.json’)
mcrfpy.exit() -> None
exit() -> None
Cleanly shut down the game engine and exit the application.
Returns: None
Note: This immediately closes the window and terminates the program.
mcrfpy.find(name: str, scene: str = None) -> UIDrawable | None
| find(name: str, scene: str = None) -> UIDrawable | None |
Find the first UI element with the specified name.
Args: name: Exact name to search for scene: Scene to search in (default: current scene)
Returns: Frame, Caption, Sprite, Grid, or Entity if found; None otherwise
Note: Searches scene UI elements and entities within grids.
mcrfpy.find_all(pattern: str, scene: str = None) -> list
find_all(pattern: str, scene: str = None) -> list
Find all UI elements matching a name pattern.
Args: pattern: Name pattern with optional wildcards (* matches any characters) scene: Scene to search in (default: current scene)
Returns: list: All matching UI elements and entities
Note: Example: find_all(‘enemy’) finds all elements starting with ‘enemy’, find_all(‘_button’) finds all elements ending with ‘_button’
mcrfpy.get_metrics() -> dict changed 0.2.8-dev
get_metrics() -> dict
Get current performance metrics.
Returns: dict: Performance data with keys: frame_time (last frame duration in MILLISECONDS), avg_frame_time (rolling mean frame time over the last 60 frames, in milliseconds), fps (frames per second, derived from avg_frame_time – a rolling average, not an instantaneous rate), draw_calls (number of draw calls), ui_elements (total UI element count), visible_elements (visible element count), current_frame (frame counter), runtime (total runtime in seconds), grid_render_time (grid rendering time in ms), entity_render_time (entity rendering time in ms), fov_overlay_time (FOV overlay rendering time in ms), python_time (Python script execution time in ms), animation_time (animation processing time in ms), grid_cells_rendered (grid cell draws this frame, counted per layer), entities_rendered (number of entities drawn this frame), total_entities (total entity count across all rendered grids)
Note: All per-frame counters and timing breakdowns describe the last COMPLETED frame. Python callbacks run before the frame is rendered, so the in-progress frame’s values are not available yet; frame_time, fps, runtime and current_frame are live.
mcrfpy.lock() -> _LockContext
lock() -> _LockContext
Get a context manager for thread-safe access to mcrfpy objects from background threads.
Returns: _LockContext: A context manager that blocks until safe to touch engine objects
Note:
Any access to mcrfpy objects from a non-main thread must happen inside with mcrfpy.lock():; behavior outside the lock is undefined. On a worker thread the context manager blocks (GIL released) until the render loop opens a safe window between frames; on the main thread it is a no-op.
See also: Threading Model (docs/threading-model.md)
mcrfpy.log_benchmark(message: str) -> None
log_benchmark(message: str) -> None
Add a log message to the current benchmark frame.
Args: message: Text to associate with the current frame
Returns: None
Raises: RuntimeError: If no benchmark is currently running
Note: Messages appear in the ‘logs’ array of each frame in the output JSON.
mcrfpy.set_dev_console(enabled: bool) -> None
set_dev_console(enabled: bool) -> None
Enable or disable the developer console overlay.
Args: enabled: True to enable the console (default), False to disable
Returns: None
Note: When disabled, the grave/tilde key will not open the console. Use this to ship games without debug features.
mcrfpy.set_scale(multiplier: float) -> None
set_scale(multiplier: float) -> None
Deprecated: use Window.resolution instead. Scale the game window size.
Args: multiplier: Scale factor (e.g., 2.0 for double size)
Returns: None
Note: The internal resolution remains 1024x768, but the window is scaled. This is deprecated - use Window.resolution instead.
mcrfpy.start_benchmark() -> None
start_benchmark() -> None
Start capturing benchmark data to a file.
Returns: None
Raises: RuntimeError: If a benchmark is already running
Note: Benchmark filename is auto-generated from PID and timestamp. Use end_benchmark() to stop and get filename.
mcrfpy.step(dt: float = None) -> float changed 0.2.8-dev
step(dt: float = None) -> float
Run one full simulation frame (headless mode only). Advances the scene update, timers, Python Scene.update() callbacks, animations, and scene transitions (including their completion), records frame-time metrics, and increments the frame counter – everything a windowed frame does except render and input.
Args: dt: Time to advance in seconds. If None, advances to the next scheduled event (timer/animation).
Returns: float: Actual time advanced in seconds. Returns 0.0 in windowed mode.
Note: Rendering is deliberately excluded: it is orthogonal to the clock and costs zero simulation time, so a screenshot draws arbitrary state without time passing. In windowed mode this is a no-op returning 0.0. Timers run on simulation time – explicit, deterministic time is the point of driving a headless test with step().
Note: A headless –exec script must end by calling sys.exit(), because step() is the only headless clock: without it the engine cannot advance itself. Pass –run-forever for a long-lived headless process that drives itself.