Integration Guide

Add Render Engine to your project

Contents

Project Setup

1. Create Game Class

package com.example.game

import org.lwjgl.glfw.GLFW.*
import ua.terra.renderengine.RenderEngineCore

class Game : RenderEngineCore(
    windowName = "My Game",
    windowX = -1,           // -1 = centered
    windowY = -1,
    windowWidth = 1280,
    windowHeight = 720,
    tickRate = 60
) {
    override fun onEnable() {
        // Load resources, setup input
        keyboard.onKeyPress(GLFW_KEY_ESCAPE) { window.close() }
    }

    override fun tick() {
        // Game logic (60 times/sec)
    }

    override fun onRender() {
        // Rendering
        renderEngine.flush()
    }
}

2. Create Entry Point

package com.example.game

import org.lwjgl.glfw.GLFW.glfwInit

fun main() {
    check(glfwInit()) { "Failed to initialize GLFW" }
    Game().enable()
}

3. Organize Resources

src/main/resources/
├── textures/
│   ├── player.png
│   └── tiles/
│       └── grass.png
├── fonts/
│   └── main.ttf
└── shaders/
    ├── custom.vert
    └── custom.frag

Keyboard

// Single press (fires once)
keyboard.onKeyPress(GLFW_KEY_SPACE) {
    player.jump()
}

// Held down (fires every frame)
keyboard.onKeyPressed(GLFW_KEY_W) {
    player.moveForward()
}

// Released
keyboard.onKeyRelease(GLFW_KEY_SPACE) {
    player.endJump()
}

// Text input
keyboard.onCharInput { char ->
    textField.append(char)
}

// Check state directly
if (keyboard.isKeyPressed(GLFW_KEY_LEFT_SHIFT)) {
    player.run()
}

Mouse

// Click (fires once)
mouse.onMouseClick(GLFW_MOUSE_BUTTON_LEFT) { x, y ->
    shoot(x, y)
}

// Held (fires every frame)
mouse.onMousePressed(GLFW_MOUSE_BUTTON_RIGHT) { x, y, lastX, lastY ->
    camera.pan(lastX - x, lastY - y)
}

// Scroll
mouse.onMouseScroll { offset ->
    if (offset > 0) camera.zoomIn()
    else camera.zoomOut()
}

// Movement
mouse.onMouseMove { x, y, lastX, lastY ->
    cursor.moveTo(x, y)
}

// Current position
val mx = mouse.x
val my = mouse.y

Camera

// Make player followable
class Player : CameraTarget {
    var x = 0f
    var y = 0f
    override fun getCameraPoint() = Point(x, y)
}

// Setup
val player = Player()
camera.initialize(player)
camera.bounds = CameraBounds(0f, 0f, worldWidth, worldHeight)
camera.minZoom = 0.5f
camera.maxZoom = 4f

// In tick()
override fun tick() {
    camera.tick()
    player.update()
}

// In onRender()
override fun onRender() {
    // Convert screen to world coordinates
    val worldX = camera.screenToSceneX(mouse.x)
    val worldY = camera.screenToSceneY(mouse.y)

    // Camera offset for rendering
    val offset = camera.getOffset()

    renderEngine.flush()
}

Textures

// In onEnable()
override fun onEnable() {
    // Register textures for atlas
    listOf(
        "textures/player.png",
        "textures/enemy.png",
        "textures/tiles/grass.png"
    ).forEach { path ->
        val fullPath = ResourcePackManager.getResourcePath(path)
        textureRegistry.registerForAtlas(fullPath)
    }

    // Build atlas (combines into one texture)
    textureRegistry.buildAtlas()
}

// In onRender()
override fun onRender() {
    val tex = textureRegistry.getFromAtlas("textures/player.png")

    renderEngine.spriteRenderer.renderSprite(
        x = player.x,
        y = player.y,
        width = 64f,
        height = 64f,
        texture = tex
    )

    renderEngine.flush()
}

Fonts

// In onEnable()
override fun onEnable() {
    fontRegistry.register("ui", "fonts/Inter.ttf", 18)
    fontRegistry.register("title", "fonts/Inter.ttf", 36)
    fontRegistry.initialize()
}

// In onRender()
override fun onRender() {
    val uiFont = fontRegistry.get("ui")
    val titleFont = fontRegistry.get("title")

    renderEngine.textRenderer.renderText(
        text = "My Game",
        x = 50f,
        y = 50f,
        font = titleFont,
        color = 0xFFFFFFFF.toInt()
    )

    renderEngine.textRenderer.renderText(
        text = "Score: ${score}",
        x = 50f,
        y = 100f,
        font = uiFont
    )

    renderEngine.flush()
}

Resource Packs

Structure

game_folder/
├── resourcepacks/
│   ├── MyPack/
│   │   ├── pack.json
│   │   └── textures/
│   │       └── player.png
│   └── AnotherPack/
│       └── ...
└── resourcepacks.json

pack.json

{
    "name": "My Resource Pack",
    "version": "1.0",
    "description": "Custom textures"
}

Usage

// Get resource (checks packs first, then JAR)
val path = ResourcePackManager.getResourcePath("textures/player.png")

// Pack management
ResourcePackManager.enablePack("MyPack")
ResourcePackManager.disablePack("MyPack")
ResourcePackManager.movePackUp("MyPack")
ResourcePackManager.movePackDown("MyPack")

// Get lists
val available = ResourcePackManager.getAvailablePacks()
val active = ResourcePackManager.getActivePacks()

// Rescan for new packs
ResourcePackManager.rescan()