███╗   ███╗██╗███╗   ██╗██╗ ██████╗ ██████╗ ██╗  ██╗
████╗ ████║██║████╗  ██║██║██╔════╝ ██╔══██╗╚██╗██╔╝
██╔████╔██║██║██╔██╗ ██║██║██║  ███╗██║  ██║ ╚███╔╝
██║╚██╔╝██║██║██║╚██╗██║██║██║   ██║██║  ██║ ██╔██╗
██║ ╚═╝ ██║██║██║ ╚████║██║╚██████╔╝██████╔╝██╔╝ ██╗
╚═╝     ╚═╝╚═╝╚═╝  ╚═══╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝  ╚═╝

MiniGDX is a minimalist 3D Game engine based on Kotlin/Multiplatform. A game can be created in Kotlin and deployed in a browser, on a desktop or on Android.

Overview

Before creating your first game, check the showcase web site and the MiniGDX code repository.

You found a typo? a sentence is not clear? You can edit this documentation

Quick Start

  • Open MiniGDX Template Repository

  • Hit the button "Use This Template"

  • Clone your new project locally

  • Run the command ./gradlew runJvm (to run on desktop) or ./gradlew runJs (to run in your browser)

  • This example bellow should be displayed

Let’s take a look to the game’s code:

class CubeGame(override val gameContext: GameContext) : Game {

    private val scene by gameContext.fileHandler.get<GraphScene>("cube.protobuf") (1)

    override fun createEntities(entityFactory: EntityFactory) {
        // Create all entities needed at startup
        // The scene is the node graph that can be updated in Blender
        scene.nodes.forEach { node ->
            // Create an entity using all information from this node (model, position, camera, ...)
            (2)
            val entity = entityFactory.createFromNode(node)

            // The node is the cube from the Blender file
            if (node.type == ObjectType.MODEL) {
                // Mark this entity as being a cube
                entity.add(Cube())
            }
        }
    }

    override fun createSystems(engine: Engine): List<System> {
        // Create all systems used by the game
        (3)
        return listOf(RotatingCubeSystem())
    }
}
1 Load the scene of the game;
2 Create an entity from a object of the scene;
3 Create a system.
The source code of this quick start can be browsed online

MiniGDX is an entity component based game engine. Those entities are created, in this example, from objects of the scene. The scene is loaded from a protobuf file. This file is created using a gradle plugin using a gltf as source. More information about this process are available in the Scene Creation paragraph.

Just keep in mind: this example load models from a file containing all 3D models. Then it create all entities from this file: the camera, the light and the cube. The component Cube is added only to this 3D model. See this component as a "tag" so the RotatingCubeSystem do know which entities to manipulate.

Once all entities of the game are creating, the RotatingCubeSystem will manage the behaviours of all entities with the component Cube.

/**
 * Rotate entities with [Cube] component by 90 degrees per second.
 */
class
RotatingCubeSystem : System(EntityQuery.of(Cube::class)) {

    override fun update(delta: Seconds, entity: Entity) {
        val component = entity.get(Cube::class)
        // If the key SPACE is pressed one time,
        // then set the duration of the component to 2 seconds.
        if(input.isKeyJustPressed(Key.SPACE)) { (1)
            component.duration = 2f
        }

        // If there is a duration, the cube can be scaled
        if(component.duration > 0f) { (2)
            component.duration -= delta
            // Compute the scale regarding the remaining duration using a cosine function
            // and keep the absolute value so the scale is always positive.
            val scale = abs(cos(component.duration))

            // Set the scale of the cube.
            entity.position.setLocalScale(
                x = scale,
                y = scale,
                z = scale
            )
        }

        // Rotate the cube of 90 degrees per second.
        entity.position.addLocalRotation(y = 90f, delta = delta) (3)
    }
}
1 React to the user input. If the space bar has been pressed, then start a timer;
2 If the timer is started, then alter the scale of the current entity (here, the cube);
3 Rotate the cube in all cases.
Tweak the cube animation by changing the speed of the rotation then restart the game using ./gradlew runJvm

Game Creation Workflow

3D model creation

MiniGDX can load 3D model from GLTF files. But not all 3D model nor all features from GLTF are supported. To use your model, the model needs to have a texture attached.

Only emissive Texture or BSDF Texture are supported for the moment.

You don’t want to use texture but only color? Create or download a texture on lospec. This texture will act like a palette: use a pixel as color for one face for example.
Safari doesn’t support WebGL 2 for the moment. If your game needs to run under safari, you have to create a texture with a pow2 size. This issue should be fixed with Safari 15. More information on the related issue.

To be loaded in MiniGDX, the GLTF file needs to be converted in a protobuf file that can be read by MiniGDX. This conversion is performed at the build time by gradle using a plugin. By default, all gltf files in the src/commonMain/assetsSource are converted as protobuf files.

Use the 3D model

The FileHandler is responsible to load resources. When loaded at the creation of the game (1), the resource will be fully loaded when the game will be started (2)

class CameraTypeGame(override val gameContext: GameContext) : Game {

    private val scene by gameContext.fileHandler.get<GraphScene>("cube.protobuf") (1)

    override fun createEntities(entityFactory: EntityFactory) { (2)
        scene.nodes.forEach { node ->
            val entity = entityFactory.createFromNode(node)

            if (node.type == ObjectType.MODEL) {
                entity.add(Cube())
            }
        }
    }

    override fun createSystems(engine: Engine): List<System> {
        return listOf(CameraTypeSystem(gameContext.gameScreen), CameraGUI())
    }
}

Create game systems

Lorem Ipsum is simply dummy text of the printing and typesetting industry.Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Scene Creation

Lorem Ipsum is simply dummy text of the printing and typesetting industry.Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

MiniGDX API

Systems

Lorem Ipsum is simply dummy text of the printing and typesetting industry.Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Entity graph

Lorem Ipsum is simply dummy text of the printing and typesetting industry.Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Default systems and components

Lorem Ipsum is simply dummy text of the printing and typesetting industry.Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Position

Lorem Ipsum is simply dummy text of the printing and typesetting industry.Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Camera

MiniGDX provide two camera type:

  • Perspective: Project objects on the scream like a camera would do: An object close to the camera will be tall while the same object far in the background look small.

  • Orthographic: The object will lock the same no mater if it’s close or not of the camera. Ideal for a 2D game

You can switch between the two in the example bellow.

Rigged Model Animations

Lorem Ipsum is simply dummy text of the printing and typesetting industry.Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

How to

Create a 2D game

Lorem Ipsum is simply dummy text of the printing and typesetting industry.Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Deployment

Share to the world your creation on twitter with the hashtag #minigdx!

Deploy a Desktop Game

./gradle bundle-jar

Deploy a Web Game

./gradle bundle-js