engine.py

LunaEngine Main Engine - Core Game Loop and Management System

LOCATION: lunaengine/core/engine.py

DESCRIPTION:
The central engine class that orchestrates the entire game lifecycle. Manages
scene transitions, rendering pipeline, event handling, performance monitoring,
and UI system integration. This is the primary interface for game developers.

KEY RESPONSIBILITIES:
- Game loop execution with fixed timestep
- Scene management and lifecycle control
- Event distribution to scenes and UI elements
- Performance monitoring and optimization
- Theme management across the entire application
- Resource initialization and cleanup
- Atlas-based resource catalog for asset management
- Resource bundle loading (optional, with progress bar)

LIBRARIES USED:
- pygame: Window management, event handling, timing, and surface operations
- numpy: Mathematical operations for game calculations
- threading: Background task management for bundle loading
- typing: Type hints for better code documentation

DEPENDENCIES:
- ..backend.pygame_backend: Default rendering backend
- ..ui.elements: UI component system
- ..utils.performance: Performance monitoring utilities
- .scene: Scene management base class
- ..misc.atlas: Resource catalog system

class LunaEngine

Description

Main game engine class for LunaEngine.

This class manages the entire game lifecycle including initialization,
scene management, event handling, rendering, and shutdown.

Attributes:
   title (str): Window title
   width (int): Window width
   height (int): Window height
   fullscreen (bool): Whether to start in fullscreen mode
   running (bool): Whether the engine is running
   clock (pygame.time.Clock): Game clock for FPS control
   scenes (Dict[str, Scene]): Registered scenes
   current_scene (Scene): Currently active scene
   atlas (Atlas): Resource catalog for all assets
   bundle_path (Optional[Path]): Path to resource bundle (.res) if any

Attributes
updateRatio: Any = update_ratio
getLogoSurface: Any = get_logo_surface
setTitle: Any = set_title
setIcon: Any = set_icon
addScene: Any = add_scene
setScene: Any = set_scene
getFpsStats: Any = get_fps_stats
getHardwareInfo: Any = get_hardware_info
getControllers: Any = get_controllers
getController: Any = get_controller
Methods
def __init__(self: Any, title: str = 'LunaEngine Game', width: int = 800, height: int = 600, fullscreen: bool = False, icon: Optional[Union[str, pygame.Surface, None]] = None, **kwargs: dict) -> Any
Initialize the LunaEngine.

Args:
   title (str): The title of the game window (default: "LunaEngine Game")
   width (int): The width of the game window (default: 800)
   height (int): The height of the game window (default: 600)
   fullscreen (bool): Start in fullscreen mode (default: False)
   icon (str|pygame.Surface): Window icon
   **kwargs: Additional options:
       - show_splash (bool): Show splash screen (default: True)
       - splash_logo (pygame.Surface): Custom logo surface
       - splash_logo_size (int): Logo size for splash (default: 64)
       - debug (bool): Enable debug mode (default: False)
       - enable_performance_profiling (bool): Enable profiling (default: True)
       - atlas_root (str|Path): Root path for the atlas (default: current directory)
       - bundle_path (str|Path): Path to resource bundle (.res file) (default: auto-detect "game.res")
       - bundle_key (str): Obfuscation key for the bundle (if encrypted)
def _auto_discover_assets(self: Any) -> None
Scan the atlas root for common asset folders and add them automatically.
def update_ratio(self: Any, base_width: int | float, base_height: int | float) -> Any
Update the aspect ratio scaling factor.
def ratio(self: Any) -> Ratio
No documentation
def initialize(self: Any) -> Any
Initialize the engine and create the game window.
def get_logo_surface(self: Any) -> Optional[pygame.Surface]
Return the engine logo surface if available.
def _show_splash(self: Any) -> Any
Display an animated splash screen with logo, title, subtitle, version, and progress bar.
def set_title(self: Any, title: str) -> Any
Set the window title.
def set_icon(self: Any, icon: Optional[Union[str, pygame.Surface, None]]) -> Any
Set the window icon.
def update_camera_renderer(self: Any) -> Any
Update all scene cameras with the current renderer.
def get_focusable_elements(self: Any) -> List[ui.UIElement]
Return all focusable UI elements that are globally visible and enabled.
def move_focus(self: Any, direction: str) -> bool
Move focus to the next/previous element in the focusable list.
Direction: 'up', 'down', 'left', 'right' (uses spatial logic) or 'next', 'prev'.
def update_controller_ui_navigation(self: Any, dt: float) -> Any
Handle all controller-based UI navigation: focus, scrolling, tab switching, and activation.
def _find_tabination_ancestor(self: Any, element: 'ui.UIElement') -> Optional['ui.Tabination']
Traverse parents to find the nearest Tabination container.
def _find_scrollable_ancestor(self: Any, element: 'ui.UIElement') -> Optional['ui.ScrollingFrame']
Traverse parents to find the nearest ScrollingFrame.
def activate_focused_element(self: Any) -> bool
Activate (click/toggle) the currently focused UI element.
Returns True if something was activated.
def add_scene(self: Any, name: str, scene_class: Type[Scene], *args: tuple, **kwargs: dict) -> Any
Add a scene to the engine by class (the engine will instantiate it).

Args:
   name (str): The name of the scene
   scene_class (Type[Scene]): The scene class to instantiate
   *args: Arguments to pass to scene constructor
   **kwargs: Keyword arguments to pass to scene constructor
def set_scene(self: Any, name: str) -> Any
Set the current active scene.

Calls on_exit on the current scene and on_enter on the new scene.

Args:
   name (str): The name of the scene to set as current
def find_event_handlers(self: Any, event: int, rep_id: str) -> bool
No documentation
def on_event(self: Any, event_type: int, rep_id: Optional[str] = None) -> Any
Decorator to register event handlers

Args:
   event_type (int): The Pygame event type to listen for
   rep_id (str, optional): A representative ID for the handler
Returns:
   Callable: The decorator function
def setup_notifications(self: Any, max_concurrent: int = 5, margin: int = 20, spacing: int = 10) -> Any
Setup notification system configuration.

Args:
   max_concurrent: Maximum concurrent notifications to show
   margin: Margin from screen edges
   spacing: Spacing between stacked notifications
def show_notification(self: Any, text: str, notification_type: NotificationType = NotificationType.INFO, duration: Optional[float] = None, position: Any = NotificationPosition.TOP_RIGHT, width: int = 300, height: int = 60, show_close_button: bool = True, auto_close: bool = True, animation_speed: float = 0.3, show_progress_bar: bool = False, on_close: Optional[Callable] = None, on_click: Optional[Callable] = None) -> Any
Show a notification with advanced options.

Args:
   text: Notification text
   notification_type: Type of notification
   duration: Display duration in seconds
   position: Position (NotificationPosition or custom (x, y) tuple)
   width: Width of notification
   height: Height of notification
   show_close_button: Whether to show close button
   auto_close: Whether notification auto-closes
   animation_speed: Speed of slide/fade animations
   show_progress_bar: Whether to show progress bar
   on_close: Callback when notification is closed
   on_click: Callback when notification is clicked
   
Returns:
   The created Notification object
def show_info(self: Any, text: str, duration: Optional[float] = None, position: Any = NotificationPosition.TOP_RIGHT) -> 'Notification'
Show an info notification.
def show_success(self: Any, text: str, duration: Optional[float] = None, position: Any = NotificationPosition.TOP_RIGHT) -> 'Notification'
Show a success notification.
def show_warning(self: Any, text: str, duration: Optional[float] = None, position: Any = NotificationPosition.TOP_RIGHT) -> 'Notification'
Show a warning notification.
def show_error(self: Any, text: str, duration: Optional[float] = None, position: Any = NotificationPosition.TOP_RIGHT) -> 'Notification'
Show an error notification.
def clear_all_notifications(self: Any) -> Any
Clear all notifications.
def get_notification_count(self: Any) -> int
Get current number of active notifications.
def get_notification_queue_length(self: Any) -> int
Get current notification queue length.
def has_notifications(self: Any) -> bool
Check if there are any active notifications.
def has_queued_notifications(self: Any) -> bool
Check if there are any queued notifications.
def get_all_themes(self: Any) -> Dict[str, any]
Get all available themes including user custom ones

Returns:
   Dict[str, any]: Dictionary with theme names as keys and theme objects as values
def get_theme_names(self: Any) -> List[str]
Get list of all available theme names

Returns:
   List[str]: List of theme names
def set_global_theme(self: Any, theme: str, dark: bool = True) -> bool
Set the global theme for the entire engine and update all UI elements

Args:
   theme_name (str): Name of the theme to set
   
Returns:
   bool: True if theme was set successfully, False otherwise
def set_dark_mode(self: Any, dark: bool) -> Any
Set the global dark mode for the engine and update all UI elements

Args:
   dark (bool): True
def get_dark_mode(self: Any) -> bool
Get the global dark mode for the engine

Returns:
   bool: True if dark mode is enabled, False otherwise
def _update_all_ui_themes(self: Any, theme_enum: Any) -> Any
Update all UI elements in the current scene to use the new theme.
def get_fps_stats(self: Any) -> dict
Get comprehensive FPS statistics (optimized)

Returns:
   dict: A dictionary containing FPS statistics
def get_hardware_info(self: Any) -> dict
Get hardware information
def ScaleSize(self: Any, width: float, height: float) -> Tuple[float, float] | Tuple[int, int]
Scale size is a function that will convert scales size to a pixel size

e.g.:
- 1.0, 1.0 = Full Screen
- 0.5, 0.5 = Half Screen
- 0.5, 1.0 = Half Screen Width, Full Screen Height

Args:
   width (float): Width scale
   height (float): Height scale
Returns:
   Tuple[float, float]|Tuple[int, int]: Pixel size
def ScalePos(self: Any, x: float, y: float) -> Tuple[float, float] | Tuple[int, int]
Scale position is a function that will convert scales position to a pixel position

e.g.:
- 1.0, 1.0 = Bottom Right
- 0.0, 0.0 = Top Left
- 0.5, 0.5 = Center

Args:
   x (float): X position
   y (float): Y position
Returns:
   Tuple[float, float]|Tuple[int, int]: Pixel position
def _rebuild_ui_layers(self: Any) -> Any
Rebuild the UI layer manager from the current scene's UI elements.
def _find_scrollable_under_mouse(self: Any, elements: Any, mouse_pos: Any) -> Any
Recursively search UI elements (and their children) for the topmost
visible, enabled element that has an 'on_scroll' method and contains the mouse.
def _dispatch_mouse_wheel(self: Any, event: Any) -> Any
Dispatch MOUSEWHEEL event to the topmost scrollable UI element under the mouse.
def run(self: Any) -> Any
Main game loop.
def on_window_resize(self: Any, func: Callable) -> Any
Decorator for window resize event.
def on_window_close(self: Any, func: Callable) -> Any
Decorator for window close event.
def on_window_focus(self: Any, func: Callable) -> Any
Decorator for window focus gained event.
def on_window_blur(self: Any, func: Callable) -> Any
Decorator for window blur (focus lost) event.
def on_window_move(self: Any, func: Callable) -> Any
Decorator for window move event.
def on_window_minimize(self: Any, func: Callable) -> Any
Decorator for window minimize event.
def on_window_maximize(self: Any, func: Callable) -> Any
Decorator for window maximize event.
def on_window_restore(self: Any, func: Callable) -> Any
Decorator for window restore event.
def on_window_enter(self: Any, func: Callable) -> Any
Decorator for mouse entering window event.
def on_window_leave(self: Any, func: Callable) -> Any
Decorator for mouse leaving window event.
def get_window_state(self: Any) -> Dict[str, Any]
Get current window state.
def is_window_focused(self: Any) -> bool
Check if window is focused.
def is_window_minimized(self: Any) -> bool
Check if window is minimized.
def is_window_maximized(self: Any) -> bool
Check if window is maximized.
def get_controllers(self: Any) -> List['Controller']
No documentation
def get_controller(self: Any, index: int) -> Optional['Controller']
No documentation
def is_using_controller(self: Any) -> bool
No documentation
def on_controller_connect(self: Any, callback: Callable[['Controller'], None]) -> Any
Register callback when a controller connects.
def on_controller_disconnect(self: Any, callback: Callable[['Controller'], None]) -> Any
Register callback when a controller disconnects.
def update_mouse(self: Any) -> Any
Update mouse position and button state with proper click detection.
def visibility_change(self: Any, element: ui.UIElement, visible: bool) -> Any
Change visibility of an element or list of elements.
def mouse_pos(self: Any) -> tuple
No documentation
def mouse_pressed(self: Any) -> list
No documentation
def mouse_wheel(self: Any) -> float
No documentation
def _render_focus_rect(self: Any) -> Any
Render a yellow outline around the focused UI element.
def _render(self: Any) -> Any
Rendering with GPU particles and shadows.
def _render_ui_elements(self: Any) -> Any
Render UI elements with individual profiling if enabled.
def _render_particles(self: Any) -> Any
Render particles using OpenGL.
def _update_ui_elements(self: Any, dt: Any) -> Any
Update UI elements with individual profiling and proper click propagation.
def _process_ui_element_tree(self: Any, root_element: Any, dt: Any) -> Any
Process a UI element and all its children with proper event consumption.
def enable_performance_profiling(self: Any, enabled: bool = True) -> Any
Enable/disable detailed performance profiling.
def get_frame_timing_breakdown(self: Any) -> Dict[str, float]
Get the timing breakdown (ms) for the last completed frame.
def get_performance_stats(self: Any) -> Dict[str, Any]
Return both FPS stats and frame timing breakdown.
def get_update_timing_stats(self: Any, category: str = 'all') -> Dict[str, Any]
Get update timing statistics for a specific category.
def get_render_timing_stats(self: Any, category: str = 'all') -> Dict[str, Any]
Get render timing statistics for a specific category.
def get_ui_update_stats(self: Any) -> Dict[str, Any]
Get UI update timing statistics.
def get_ui_render_stats(self: Any) -> Dict[str, Any]
Get UI render timing statistics.
def get_individual_ui_update_stats(self: Any) -> Dict[str, float]
Get individual UI element update timing statistics.
def get_individual_ui_render_stats(self: Any) -> Dict[str, float]
Get individual UI element render timing statistics.
def get_scene_update_stats(self: Any) -> Dict[str, Any]
Get scene update timing statistics.
def get_scene_render_stats(self: Any) -> Dict[str, Any]
Get scene render timing statistics.
def get_total_frame_time(self: Any) -> Dict[str, float]
Get total frame time breakdown.
def add_to_atlas(self: Any, name: str, path: Union[str, Path], category: Optional[Union[str, AtlasCategory]] = None, auto_detect: bool = True, validate: bool = True) -> AtlasItem
Add a file to the atlas.

Args:
   name: Unique name for the resource.
   path: File path (string or Path).
   category: Explicit category (string or AtlasCategory). If None, will be auto-detected.
   auto_detect: If True and category is None, guess from extension.
   validate: If True, enforce extension rules for the category.
   
Returns:
   AtlasItem: The created atlas item.
def get_atlas_item(self: Any, name: str) -> Optional[AtlasItem]
Retrieve an atlas item by its name.
def get_atlas_path(self: Any, name: str, category: Optional[Union[str, AtlasCategory]] = None) -> Optional[Path]
Get the file path of an atlas item, optionally checking its category.

Args:
   name: Resource name.
   category: If provided, only return the path if the item's category matches.
   
Returns:
   Path or None if not found.
def add_texture_to_atlas(self: Any, name: str, path: Union[str, Path]) -> AtlasItem
Shortcut to add a texture (image) to the atlas.
def add_font_to_atlas(self: Any, name: str, path: Union[str, Path]) -> AtlasItem
Shortcut to add a font to the atlas.
def add_audio_to_atlas(self: Any, name: str, path: Union[str, Path]) -> AtlasItem
Shortcut to add an audio file to the atlas.
def shutdown(self: Any) -> Any
Cleanup resources.
Back to Core Module