Skip to content

korlibs/korge-fleks

Repository files navigation

Korge-fleks

Build Main MIT license

Korge-fleks is a Game Framework dedicated for building games by strictly separating game object configuration from its implementation. It uses the Fleks Entity Components System (ECS) and integrates it on top of the Korge Game Engine.

Korge-fleks is not just a simple wrapper around Fleks ECS but a specialized implementation containing a lot of additional useful stuff around an ECS for the Korge Game Engine. Korge-fleks is (currently) dedicated to 2D platformer games. It is developed in the open with the hope that it will be useful for others, too.

Together with the korge-fleks-hello-world example it can be used as a starting point for a new game project.

Upstream project for Fleks ECS can be found here: https://github.com/Quillraven/Fleks

Korge-fleks is maintained by @jobe-m

Features

Korge-fleks offers the following features for building a game on top of Korge:

Game state management

  • Entity Component System (ECS) utilizing Fleks
  • Serialization of Entities and Components
  • Snapshot system for saving and restoring the game state
  • Save and load game state (world snapshot) as JSON string
  • Pooling of Components and data class objects used by components to prevent GC (garbage collection) on JVM platforms with tight memory constraints (like Android)

Asset management

  • Loading of pre-processed assets (Graphics, level maps, sounds, etc.) which are generated by a specifically for Korge-fleks written Gradle-plugin in the Korge main repository
  • Generating of Asset clusters via running Gradle tasks to break assets down to be used per game progress (e.g. world chunk or level section)
  • All loaded asset objects are in-game available via a central asset store
  • Hot-reloading of assets for quick prototyping of graphics, level sections, NPC movements, etc.

Game Object configuration

  • Entity configuration objects (blueprints) for easy setup of complex Game Objects
  • Game objects are build via invoking a factory function whose use free-to-define input parameters directly from LDtk level map editor

Rendering systems

  • Game object renderer for sprites, sprite animations, text, 9-patches, tile set objects, etc.
  • Special parallax background renderer
  • Level map renderer using an optimized tile map format (importers for LDtk level map format via Gradle plugin)
  • Fast objects/effects renderer (e.g. explosions, particles)
  • Debug rectangle renderer (texture bounds, collision shapes, etc.)

Level map management

  • Support for building huge worlds of seamlessly connected levels from LDtk level map editor
  • Automatic spawning and despawning of game objects depending on its position in relation to the camera viewport
  • Collision detection system for level maps (static) and game objects (dynamic)

Property animation system

  • Tween-Animation system with Easing functions to animate properties of components
  • Tween-Sequence system to create scripted animations (e.g. for intro or cut scenes)

Sound system

  • Sound system for playing background music and triggering sound effects from entities

Supported Versions

This is a list of versions for all needed modules/addons which are known to work together with Korge-fleks:

- Korge:                v6.0.0
- Fleks:                2.12

Idea and Motivation

The Korge-fleks implementation follows the idea to separate the configuration of Game Objects from their executed behavior.

A game object in an ECS is an Entity and per definition just an index number (in Fleks e.g. Entity(id = 1)). Runtime-configuration for a game object can be defined as an Aspect of an entity. The aspects of an entity are stored in a Component. An entity usually has multiple components assigned. Systems iterate over all active entities of an ECS world and execute the "behavior" for each Entity. To do so systems use the properties from all associated components of an entity.

If I lost you already please step back and read elsewhere a little more about ECS basics. It is important to understand -at least- the basic principles of an ECS system. Moreover, there are various interpretations out there what an ECS is and how it works. But when you read further down you should get the idea of how the Fleks ECS can work within a Korge game.

Per definition Korge-fleks components contain only data which is necessary to fully describe the state of a game object at every point in time. All components are easily serializable with kotlinx.serialization because of its basic nature. This enables the game system to save the state of a game object and to restore its state when needed. This also makes it possible to easily implement a save-game system or to handle transmission of game object states over network for a multiplayer game. Details about implemented property types for components can be found below in section Components.

Korge-fleks can save the state of the game by simply serializing and saving the whole ECS world snapshot as a JSON string to a file (all active entities and components). Loading a saved state of the game is done by deserializing the saved JSON string of a world snapshot.

Korge-fleks implements a couple of useful Systems. Those systems keep track of complex Korge objects and map them to the Entities which needs those objects to implement various behavior like e.g. displaying sprites, playing sounds or reacting to touch input.

Execution time of systems in Fleks is very static and thus predictable. On the other side the core of Korge makes a lot of use of coroutines and asynchronous execution of object's behavior in update functions. Korge-fleks tries to hide this complexity in its systems.

In the end the actual game code outside Korge-fleks is just specialized configuration (Entity config) and individual assets for the final Game Objects.

Implementation of Korge-fleks

This repository contains under korge-fleks/src folder the Korge-fleks addon. The next subsection gives an overview over all provided Components and Systems. Also, Serialization of Entities and its associated components and how to use the AssetStore and entity configuration to build up Game Objects is described.

Components

All provided components in Korge-fleks contain only basic property types like:

  • String
  • Number (Int, Float, Double)
  • Enum class (like Easing from Korge)
  • Entity (Int value class)
  • Identifier (String value class for accessing static entity configuration which is loaded from AssetStore and invoking functions with World, Entity and Identifier parameters)

Collections of above types in Lists and Maps are also supported.

For simplicity all properties are independent of any Korge-specific complex classes. Components do not contain any Korge-related complex objects like Views, Image, Camera, etc.

Hint: Where it makes sense a basic type can be taken over from Korge as it is done with the Easing enum class for the Animation system.

Pooling and Serialization of Entity Components

... to be continued

Systems

... to be continued

Entity Configuration (Game Object Blueprints)

Korge-fleks contains some generic configuration assets which can be used to build up more complex game objects. The existing config objects can be found in korlibs.korge.fleks.entity.config. These object classes contain 4 sections:

  • Config data classes
  • Identifiers for invokable functions
  • The actual (anonymous) configure function as a value object
  • Init block which registers the configure function and its Identifier to the Invokable object store

A configuration for an entity is applied to the entity's components by executing the configure function. The Invokable object stores the relationship between the Identifier and the function. Systems like the SpawnerSystem will invoke the function by looking up the Identifier and executing invoke from the Invokable object class. This is how Korge-fleks can set up new game objects/entities in a very generic and configurable way.

AssetStore

AssetStore implements loading of typical game assets like graphics images, sounds, level maps, game object configs, etc. It uses clusters of loadable sets of asset which can have different lifetime in the game:

  • Common assets (used throughout the life-cycle of the game)
  • World chunk assets (used only in specific sections of a world level map)

Korge-fleks provides basic entity configuration objects and functions to easily setup Game Objects

  • Parallax background
  • Text and image logos
  • Level maps (Tiledmap)
  • Effect objects (like explosions)
  • ... to be continued

Hot-reloading of Assets

...

Fleks World Integration into a Korge Scene

...

Set up a new Game with Korge-fleks

As a clean start the korge-fleks-hello-world repository can be used. It contains the kproject and gradle setup to use Korge, Fleks and Korge-fleks addon in a project.

In detail the project setup looks like that:

build.gradle.kts

This tells gradle that the overall project depends on a project deps in the root directory.

[...]
dependencies {
    add("commonMainApi", project(":deps"))
}

deps.kproject.yml

This is the configuration for kproject to set up a project deps in the root directory. It just contains one dependency to the Korge-fleks addon.

dependencies:
    - https://github.com/korlibs/korge-fleks/tree/0acbfcb5d89eca161c3537a9160143c9a72d2725/korge-fleks
#    or use local copy
#    - ./submodules/korge-fleks/korge-fleks

settings.gradle.kts

Needed settings for gradle to make kproject usable in the project.

pluginManagement {
    repositories { mavenLocal(); mavenCentral(); google(); gradlePluginPortal() }
}

buildscript {
    val libsTomlFile = File(this.sourceFile?.parentFile, "gradle/libs.versions.toml").readText()
    var plugins = false
    var version = ""
    for (line in libsTomlFile.lines().map { it.trim() }) {
        if (line.startsWith("#")) continue
        if (line.startsWith("[plugins]")) plugins = true
        if (plugins && line.startsWith("korge") && Regex("^korge\\s*=.*").containsMatchIn(line)) version = Regex("version\\s*=\\s*\"(.*?)\"").find(line)?.groupValues?.get(1) ?: error("Can't find korge version")
    }
    if (version.isEmpty()) error("Can't find korge version in $libsTomlFile")

    repositories { mavenLocal(); mavenCentral(); google(); gradlePluginPortal() }

    dependencies {
        classpath("com.soywiz.korge.settings:com.soywiz.korge.settings.gradle.plugin:$version")
    }
}

apply(plugin = "com.soywiz.korge.settings")

fleks/kproject.yml

This is the kproject config for including Fleks sources into the Korge project. Since Entity value objects from Fleks need to be serializable for saving the game state the serialization plugin needs to be added.

# Get an external source project from GitHub which does not contain a kproject.yml file
# loading git tag release (or commit) from GitHub repo (https://github.com/Quillraven/Fleks)
src: git::Quillraven/Fleks::/src::2.12

plugins:
    - serialization

korge-fleks/kproject.yml

This is the kproject config for including Korge-fleks sources into the Korge project. Also for Korge-fleks the serialization plugin is needed to save the game state.

plugins:
    - serialization

dependencies:
    - ../fleks
# Or use fleks locally
#  - ../../fleks
#
    - maven::common::com.soywiz.korlibs.korge2:korge

Updating Korge-fleks to newer versions

Korge-fleks depends on specific versions of Korge and Fleks ECS.

The current versions which are working together can be seen at the top of this readme in section "Supported Versions".

Korge and Fleks ECS need to be updated in following places:

Korge Version

Korge version needs to be updated in gradle/libs.versions.toml:

[plugins]
korge = { id = "com.soywiz.korge", version = "6.x.x" }

Fleks Version

Fleks ECS version needs to be updated in the kproject file under fleks/kproject.yml:

[...]
src: git::Quillraven/Fleks::/src::2.x

Examples

History/Legacy

About

Korge-Fleks is a game framework dedicated for 2D platformer games based on KorGE game engine and Fleks Entity Component System. It is developed by its author for building the game "jobe's Legacy" live on Twitch.

Resources

License

Stars

Watchers

Forks

Languages