# Engine Overview Welcome to the Lisa Engine documentation. This guide covers the architecture and inner workings of the engine that powers games like CoolFox and NeonSignal. ## Overview Lisa Engine is a 2D platformer engine built on the libGDX framework. It implements a custom Entity-Component System (ECS) and ships as a Gradle library — consuming games add their own platform launchers (desktop, Android, iOS, …), player implementation, and game-specific entity factory. ### What Lisa Engine provides - An ECS runtime with a spatial grid for collision - A library of ~50 platformer components (movement, hazards, switches, enemies, particles, …) - Level loading from Tiled TMX maps - A unified input abstraction across keyboard, touch, and gamepad - A set of menu / cutscene / dialog / settings screens - A JSON-based script system for cutscenes and abilities - Resource managers for textures, sounds, fonts, animations, levels, paths, secrets ### What the consuming game provides - Platform launchers (desktop/android/ios/…) - A subclass of `EngineConfig` with the game's name, resources, and physics constants - A subclass of `EntityFactory` with game-specific `createX()` methods (typically including the player) - The `PlayerComponent` (or equivalent) and any other game-specific components - Tiled maps, textures, sounds, scripts, fonts ## Engine Architecture ### The Big Picture ``` Game's Application entry point (e.g. DesktopLauncher) ↓ Engine (Lisa Engine core orchestrator) ├─ Resource Managers (Textures, Sounds, Fonts, Levels, …) ├─ Input System (Keyboard, Touch, Gamepad) ├─ Screen Manager (Game, Menu, Pause, …) └─ Entity-Component System ├─ GameScene (world container) ├─ EntityManager (lifecycle & spatial grid) └─ Entities (composed of components) ``` ### Core Classes **`Engine`** (`core/src/net/dynart/lisa/core/Engine.java`) - The orchestrator that owns the asset manager, input multiplexer, screen lifecycle, and resource managers - Initialized by the consuming game with an `EngineConfig` **`EngineConfig`** (`core/src/net/dynart/lisa/core/EngineConfig.java`) - Base configuration class. The consuming game subclasses it and supplies the game's name, the `EntityFactory`, the `FadeRenderer`, and JSON-driven settings (physics, input, display). **`EntityFactory`** (`core/src/net/dynart/lisa/core/EntityFactory.java`) - Base factory with `createX()` methods for the engine's built-in entity types - Consuming games subclass it to add their own (player, custom enemies, etc.) - Uses reflection: when the level loader sees an object of type `"player"`, it calls `createPlayer()`. **`GameScene`** / **`EntityManager`** - `GameScene` is the per-level world container. - `EntityManager` owns entity lifecycle and a spatial grid (160px cells) for collision queries; it also organizes entities by draw layer. ### Entity-Component System Game objects (entities) are built by composing reusable components. - **`Entity`** — a container that holds components and supports parent/child hierarchy for relative positioning. Components live in a `HashMap` for fast lookup. - **`Component`** — abstract base with lifecycle methods `preUpdate()`, `update()`, `postUpdate()`. Components can subscribe to messages via the `MessageHandler` for event-driven behavior. ### Component Library Lisa Engine ships ~50 platformer components, organized roughly by role: #### Physics & collision `BodyComponent`, `VelocityComponent`, `GridCollisionComponent`, `EntityCollisionComponent`, `WaterCollisionComponent`, `ColliderComponent`, `PlatformComponent`, `BlockComponent`, `DisappearingBlockComponent`, `EnemyBlockComponent` #### Health & damage `HealthComponent`, `MiniBarComponent`, `OxygenComponent`, `OverlapAttackComponent`, `OverlapAttackableComponent`, `ReviveComponent` #### Enemies `EnemyComponent`, `WalkerComponent`, `JumperComponent`, `FrogComponent`, `RushComponent` #### Hazards `SpikeComponent`, `ElectricSpikeComponent`, `CrushComponent`, `FallingComponent`, `StartFallingInDistanceComponent`, `StartFallingOnMountComponent` #### Switches & interactives `ButtonComponent`, `SwitchComponent`, `SwitchableComponent`, `KillSwitchComponent`, `KnifeSwitchComponent` #### Movables & transport `MovableComponent`, `BoxComponent`, `PusherComponent`, `MountableComponent`, `ConveyorComponent`, `TramComponent`, `SpringboardComponent`, `RailEndComponent` #### Bullets `BulletComponent`, `BulletSpawnerComponent` #### Rendering & effects `ViewComponent`, `ParticleComponent`, `ParticleEmitterComponent`, `SplashComponent`, `ActionComponent` #### Collectibles, exits, scene triggers `ItemComponent`, `SecretComponent`, `ExitComponent`, `ActivateOnScreenComponent`, `CameraLimitTriggerComponent`, `SceneWarpComponent` > **Note:** The player itself is **not** an engine component — each game implements its own player on top of these primitives. ### Level Loading **`GameSceneLoader`** (`core/src/net/dynart/lisa/core/GameSceneLoader.java`) - Loads Tiled TMX maps - Parses background, main, and foreground layers - Creates entities from object layers via the `EntityFactory` - Sets up music, camera limits, and player abilities for the scene - Handles layer separation for parallax effects Levels are TMX files designed in [Tiled](https://www.mapeditor.org/), stored in the consuming game's `assets/data/levels/` and registered in `resources.json`. ### Input System A unified abstraction across keyboard, touch, and gamepad. - **`GameController`** (`core/src/net/dynart/lisa/core/controller/GameController.java`) — central input hub with a logical button set: LEFT, RIGHT, UP, DOWN, A, B, X, Y, MENU. - **`KeyboardListener`** — desktop keyboard input. - **`TouchListener`** — mobile touch with on-screen buttons. - **`GamepadListener`** — console-style gamepad / joystick. Bindings are user-customizable via the engine's customize-controls screens. ### Screens The engine ships 16 screens for common game states: **Core gameplay:** `GameScreen`, `GameFadeInScreen`, `PauseScreen`, `GameOverScreen` **Menus:** `MenuScreen`, `SettingsScreen` **Customization:** `CustomizeButtonsScreen`, `CustomizeKeyboardScreen`, `CustomizeGamepadScreen`, `CustomizeTouchScreen` **Narrative:** `CutsceneScreen`, `DialogScreen` **System:** `LoadingScreen`, `LogoScreen`, `EmptyScreen` `GameStage` provides the in-game HUD overlay (score, health, pause button) on top of `GameScreen`. ### Script System A JSON-based command system used for cutscenes and special abilities. - **Command pattern** — each command implements `act(delta)` and returns `true` when finished. - **Composition:** `SequenceCommand`, `ParallelCommand`, `SkippableCommand` - **Dialog & timing:** `SayCommand` (via DialogStage), `DelayCommand` - **Movement:** `WalkToCommand`, `WalkToExitCommand`, `SetMovementActive` - **Animation:** `SetAnimationCommand`, `SetVisibleCommand` - **Camera:** `MoveCameraToCommand`, `SetCameraTargetCommand`, `SetCameraLimitCommand` - **Game logic:** `TriggerCommand`, `PlayMusicCommand`, `SetParentCommand` Scripts are stored as JSON in the consuming game's `assets/data/scripts/` and loaded via `ScriptLoader`. ### Resource Management Resource managers, owned by `Engine`: - `TextureManager` — texture atlases and individual textures - `SoundManager` — sound effects and music with volume control - `FontManager` — bitmap fonts - `SpriteAnimationManager` — animation caching - `LevelManager` — level registration and retrieval - `PathManager` — movement paths for entities - `SecretManager` — secret-collectible tracking #### Configuration files (provided by the consuming game) - `config.json` — physics constants, input mappings, platform-specific overrides - `resources.json` — asset registry (sounds, music, textures, levels, animations) Platform-specific sections in `config.json` override base values; arrays in platform sections **replace** rather than append. ## Architecture Patterns ### Composition over inheritance Entities are not defined by class hierarchies but by the components they contain. A moving, animated, collectible object is just the right combination of components. ### Spatial grid `EntityManager` divides the world into 160px grid cells. Collision checks only consider entities in nearby cells, keeping detection fast even with many entities on screen. ### Message / event bus Components publish and subscribe to events through `MessageHandler`. This loose coupling lets systems react to events (e.g. a collectible being picked up) without hard-wiring references to each other. ### Reflection-based factory `EntityFactory` uses reflection to dispatch object types from Tiled to `createX()` methods. Add a new entity type by adding a `createMyType()` method to your subclass — no registration code required. ### Pooling Particles and bullets use object pools (`ParticlePool`, `BulletPool`) to reduce GC pressure in tight inner loops. ## Adding a new entity type (in your game) 1. **Define the component** in your game's components package: ```java public class MyComponent extends Component { @Override public void update(float delta) { /* ... */ } } ``` 2. **Add a factory method** to your game's `EntityFactory` subclass: ```java public Entity createMyEntity(Parameters parameters) { Entity entity = new Entity(); entity.addComponent(new BodyComponent()); entity.addComponent(new ViewComponent()); entity.addComponent(new MyComponent()); return entity; } ``` 3. **Place it in Tiled** — set the object type to `"myEntity"` (matches the factory method name, sans `create`); add custom properties as needed. 4. **Define animations** in `resources.json` if needed. ## Key File Reference | Purpose | File Path | |---------|-----------| | Engine core | `core/src/net/dynart/lisa/core/Engine.java` | | Engine config (base) | `core/src/net/dynart/lisa/core/EngineConfig.java` | | Entity factory (base) | `core/src/net/dynart/lisa/core/EntityFactory.java` | | Entity / component | `core/src/net/dynart/lisa/core/Entity.java`, `Component.java` | | Entity manager | `core/src/net/dynart/lisa/core/EntityManager.java` | | Level loader | `core/src/net/dynart/lisa/core/GameSceneLoader.java` | | Script loader | `core/src/net/dynart/lisa/core/script/ScriptLoader.java` | | Game controller | `core/src/net/dynart/lisa/core/controller/GameController.java` | ## Version Current Lisa Engine version: **0.1.0** (libGDX 1.14.0). Defined in the root `build.gradle`.