Skip to content

Latest commit

 

History

History
278 lines (233 loc) · 7.54 KB

README.md

File metadata and controls

278 lines (233 loc) · 7.54 KB

kilo-engine

A Simple 3D Game Engine

Installation

Warning: snpashot versions are a subject to constant, breaking changes, without a version number change. For that reason, a dependency refresh might break your code if you use a snapshot version of the engine. It is recommended to users of snapshot versions (currently there are no public release versions) to keep track of this README page and this respository's commit history.

Gradle Kotlin
// build.gradle.kts

repositories {
    mavenCentral()
    maven("https://maven.jemnetworks.com/releases")
    maven("https://maven.jemnetworks.com/snapshots")
    maven("https://maven.quiltmc.org/repository/release")
    maven("https://jitpack.io")
}

dependencies {
    implementation("io.github.gaming32:kilo-engine:0.1-SNAPSHOT")
}
Gradle Groovy
// build.gradle

repositories {
    mavenCentral()
    maven { url = "https://maven.jemnetworks.com/releases" }
    maven { url = "https://maven.jemnetworks.com/snapshots" }
    maven { url = "https://maven.quiltmc.org/repository/release" }
    maven { url = "https://jitpack.io" }
}

dependencies {
    implementation "io.github.gaming32:kilo-engine:0.1-SNAPSHOT"
}
Maven
<!-- pom.xml -->

<repositories>
  <repository>
    <id>gaming32</id>
    <name>Gaming32</name>
    <url>https://maven.jemnetworks.com/releases</url>
  </repository>
  <repository>
    <id>gaming32-snapshots</id>
    <name>Gaming32 Snapshots</name>
    <url>https://maven.jemnetworks.com/snapshots</url>
  </repository>
  <repository>
    <id>quiltmc</id>
    <name>QuiltMC</name>
    <url>https://maven.quiltmc.org/repository/release</url>
  </repository>
  <repository>
    <id>jitpack.io</id>
    <name>Jitpack</name>
    <url>https://jitpack.io</url>
  </repository>
</repositories>

<dependencies>
  <dependency>
    <groupId>io.github.gaming32</groupId>
    <artifactId>kilo-engine</artifactId>
    <version>0.1-SNAPSHOT</version>
  </dependency>
</dependencies>

Basic example

Kotlin
fun main() = object : KiloEngineGame {
    init {
        Resources.resourceGetter += javaClass::getResourceAsStream
    }

    override val title get() = "My Game"

    override fun loadInitScene() {
        sceneLoader.loadScene("/my_game/my_scene.scene.json5", scene)
    }
}.main()
Java
public class MyGame extends KiloEngineGame {
    public static void main(String[] args) {
        Resources.addResourceGetter(MyGame.class::getResourceAsStream);
        new MyGame().main();
    }

    @Override
    @NotNull
    public String getTitle() {
        return "My Game";
    }

    @Override
    public void loadInitScene() {
        getSceneLoader().loadScene("/my_game/my_scene.scene.json5", getScene());
    }
}

Scenes

A game in Kilo Engine is made up of "scenes" (well actually just one at this point). A scene is a collection of entities that make up the game, as well as various other minor things.

Scenes can be constructed purely through using code, but it is preferred to specify the initial data of scenes through .scene.json5 files. You can load scenes from Json5 files using sceneLoader#loadScene.

Scene Json5 syntax is simple. Here's a brief example:

Sample Json5 scene
{
  entities: [
    // What's a level without some entities, eh?
    // More details on entity Json5 syntax below in the "Entities" section.
    {
      kinematic: true,
      components: [
        {
          type: "mesh",
          mesh: "/example/example.obj"
        },
        "meshRenderer",
        {
          type: "meshCollider",
          collision: {
            Brick_Antique_01: "wall",
            Brick_Basket: "floor",
            Death_Plane: "death"
          }
        }
      ]
    },
    {
      position: [0, 1.4, -5],
      components: [
        {
          type: "capsuleCollider",
          radius: 0.4,
          length: 1
        },
        "player",
        {
          type: "camera",
          offset: [0, 0.7, 0],
          skybox: { // A cubemap skybox
            base: "/example/skybox", // *Optional* base path for the paths in this object
            down: "down.png", // Because `base` is specified, this will load from `/example/skybox/down.png`.
            up: "up.png",
            negativeZ: "negativeZ.png",
            positiveZ: "positiveZ.png",
            negativeX: "negativeX.png",
            positiveX: "positiveX.png"
          },
          skybox: [0.75, 0.25, 0.25], // A light red solid color skybox
        }
      ]
    }
  ]
}

So you want to see how this is done in code? Well here you go:

The above example, but in Kotlin
Entity(scene, DVector3()).apply {
    body.setKinematic()
    val model = MeshComponent(this, sceneLoader.loadObj("/example/example.obj")).model
    MeshRendererComponent(this)
    MeshColliderComponent(this, CollisionModel(model, mapOf(
        model.materials["Brick_Antique_01"]!! to CollisionTypes.WALL,
        model.materials["Brick_Basket"]!! to CollisionTypes.FLOOR,
        model.materials["Death_Plane"]!! to CollisionTypes.DEATH
    )))
}
Entity(scene, DVector3(0.0, 1.4, -5.0)).apply {
    CapsuleColliderComponent(this, 0.4, 1.0)
    PlayerComponent(this, Vector2f())
    CameraComponent(
        this, 
        offset = DVector3(0.0, 0.7, 0.0),
        skybox = Skybox.Cubemap.relative(
            "/example/skybox",
            "down.png",
            "up.png",
            "negativeZ.png",
            "positiveZ.png",
            "negativeX.png",
            "positiveX.png"
        )
        // skybox = Skybox.SolidColor(0.75f, 0.25f, 0.25f)
    )
}
The above example, but in Java
final Scene scene = getScene();

final Entity levelMesh = new Entity(scene, new DVector3());
levelMesh.getBody().setKinematic();
final Model model = new MeshComponent(
    levelMesh, getSceneLoader().loadObj("/example/example.obj")
).getModel();
new MeshRendererComponent(levelMesh);
new MeshColliderComponent(levelMesh, new CollisionModel(model, Map.of(
    model.getMaterials().get("Brick_Antique_01"), CollisionTypes.WALL,
    model.getMaterials().get("Brick_Basket"), CollisionTypes.FLOOR,
    model.getMaterials().get("Death_Plane"), CollisionTypes.DEATH
)));

final Entity player = new Entity(scene, new DVector3(0, 1.4, -5));
new CapsuleColliderComponent(player, 0.4, 1);
new PlayerComponent(player, new Vector2f());
new CameraComponent(
    player, 
    new DVector3(0.0, 0.7, 0.0),
    Skybox.Cubemap.relative(
        "/example/skybox",
        "down.png",
        "up.png",
        "negativeZ.png",
        "positiveZ.png",
        "negativeX.png",
        "positiveX.png"
    )
    // new Skybox.SolidColor(0.75f, 0.25f, 0.25f)
);