Skip to content
Karn Kaul edited this page Nov 4, 2019 · 4 revisions

About LittleEngine

Introduction

LittleEngine uses two core threads: the main thread loops at tickRate, updating objects using delta time (also fixed time slice integration, eg, for physics), and a render thread attempts to run as fast as possible (capped at the display refresh rate via VSYNC and frame-limited to twice that) and interpolates between render states to draw entities on screen, though async rendering can be disabled via GameConfig. Depending on CPU availability, there will be a file logging thread as well, and a number of job workers for gameplay code to delegate tasks without blocking the main thread. As an example of long-running tasks, asset manifests are loaded entirely via the job system's JobCatalog (collection of tasks with an optional main-thread callback); whereas Quads and PSEmitter objects exploit the Jobs::ForEach() API to distribute the updation of thousands of quads / particles among all the available workers within the time of a single render / game frame.

Note: There must be at least one worker for the engine to start (without async rendering); thus LittleEngine cannot be run on single-threaded machines.

The Engine offers multiple build configurations for debugging / authoring content / public redistribution. It uses an Entity/Component architecture for organising gameplay objects, where either can be subclassed. All Entities and Components are spawned and owned at game-time by GameManager, and destroyed on the active World's deactivation - which can be changed at any time, and any number of Worlds can be added to the Engine before running it. Assets are expected to be cooked into a zip archive and will be loaded in-memory at game-time; Debug andDevelop builds will first attempt to directly load assets from the filesystem as an authoring convenience (you needn't cook assets you are actively working on).

Asset Management

Before activating World 0, the Engine first loads assets into memory.

When FILESYSTEM_ASSETS are enabled, the Engine can and will prefer to load assets into memory directly through the filesystem. It is recommended to set a root directory such as GameAssets and store all assets hierarchically there. In SHIPPING builds (Release), the Engine will only load assets through a compressed archive named GameAssets.cooked, which should be a zip archive of the root assets directory.

Expect warning logs for loading assets not present in GameAssets.cooked (they will fail to load on SHIPPING builds).

The Engine needs AssetManifest serialised GData objects to locate relevant bytes within the cooked archive, and expects them to be in the root directory of the archive, named *.amf. Assets in Manifest.amf will be loaded before anything else, and will remain in memory throughout the session. Each World also checks for the presence of an asset manifest of its namesake, and if found, loads/unloads those assets before/after activation/deactivation. Runtime/Utils/asset_cooker.py can be used to automate populating and generating GameAssets.cooked via all the assets listed in all the manifests. The expected workflow is to ensure all assets referenced by the game are in the global/world manifests (not both!), and then to simply run the tool, which will backup the cooked archive if it already exists before creating a new one.

Expect warning logs and potential hitches on calling Load<T> for assets not in LERepository's memory (ie, not in global / current World's manifests).

Using LittleEngine

  1. Create a new directory with a CMakeLists.txt and an executable target.
  2. Enter the root directory and add LittleEngine as a git submodule using git submodule add https://github.com/karnkaul/LittleEngine.
  3. Add the project to the top-level CMakeLists.txt by using add_subdirectory(LittleEngine).
  4. Use Test/CMakeLists.txt as a template to build an executable linked to LittleEngine with the correct RPATH etc.
  5. In main() (or a function called through it):
    1. Call OS::Env()->SetVars(argc, argv) to initialise the environment.
    2. Modify default globals in GameLoop if required.
    3. If GameLoop::Init() returns true, return GameLoop::Run() to the OS.
  6. Add at least one world via WorldStateMachine::CreateWorld<T> / WorldStateMachine::CreateWorlds<T...>.

Note: Make sure the working directory for the application project (LEApp) is set to Runtime, when debugging/running from the IDE.

An active World will always have an instance of GameManager available through g_pGameManager, which is capable of spawning new Entitys and its subclasses, as well as new AComponent subclasses, attached to existing Entitys. All the base gameplay classes have a Super typedef. The Engine will call World::Tick(Time dt) at a fixed time slice, set in GameConfig. World will then call Entity::Tick() and AComponent::Tick() on all active objects. Derived Worlds can execute code on either side of their call to World::Tick() / Super::Tick() in their PreTick() / PostTick() overrides.

GameManager owns an instance of UIManager, which manages a stack of UIContext objects. Each UIContext can contain numerous UIElements (base UI object) UIWidgets (navigatable and interactable UIElements). GameManager also provides pointers to Input, UI, Renderer, Context,WorldCamera, and Physics services.

At the end of each gameplay frame, FinishFrame() will cause the game state of all primitives to be copied into their corresponding render states for the renderer to interpolate between until the next swap.

There are several existing Entities, Components, UI Widgets and UI Contexts ready for use in Framework.

Misc

Backlog / Changelog

  • Custom 2D coordinate system
  • Primitive Render States
  • Dynamic game Entities
  • Dynamic game Components
  • Collision Detection
  • Sounds & Music
  • Engine Repository (for asset management)
  • In-game Console (when DEBUGGING)
  • Player-modifiable game-settings file
  • Debug-only engine-settings file
  • In-memory Asset Loads (through a cooked/compressed archive)
  • UI Framework
  • Gameplay UI classes
  • Gameplay Camera (root Transform for all Entitys)
  • Runtime configurable/recreatable Render Window
  • Options Menu
  • Vertex-Array particle systems
  • Asset Cooker tool
  • Application Packager tool
  • Containerised UI layout via files
  • Matrix transformations
  • Joystick and mouse support
  • CMake IDE project generation
  • Visual Studio CMake / Ninja integration
  • CMake Linux and OSX integration
  • Travis CI Integration
  • Animation system
  • Collision Resolution

Clone this wiki locally