Skip to content

Latest commit

 

History

64 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DimEngineZ

Warning

DimEngineZ is a work in progress. APIs and architecture are likely to change as the project evolves. It is not meant to be production-ready.

DimEngineZ (pronounced dimensions-E) is a small, experimental game engine built on top of Raylib.

It is a personal project for exploring how game-engine systems can be designed and composed in C++. Note that DimEngineZ is not meant to be complete or production-ready: it is a place to experiment with the building blocks behind a simple game. My goal is to keep those systems somewhat lightweight and composable. You can work directly with individual engine objects when you need control, or combine them into higher-level objects when that makes more sense.

What it currently provides

DimEngineZ currently supports three main object types:

  • DrawObject: handles drawing the object.
  • MovementObject: handles movement-related functionality.
  • PhysicsObject: combines the previous two shapes with physics simulation.

The physics system provides basic operations such as:

  • applyAcceleration()
  • applyImpulse()
  • applyForce()
  • velocity and movement handling
  • static objects
  • ground detection

The engine also provides a built-in application loop with a fixed update interval ("fixed delta"), allowing engine systems such as physics and rendering to be updated automatically.

Example

The following creates a cube, places it above a ground plane, and gives it simple gravity and jumping:

#include "../include/DimEngineZ.h"
#include "raylib.h"
#include <iostream>

int main() {
    namespace dez = DimEngineZ;

    dez::manager::initWindow(1000, 800, "3D Cube Renderer");

    dez::Camera camera({0.0f, 15.0f, 10.0f},
                       dez::CameraOptions{
                           .fovy = 90.0f,
                           .direction = {0.0f, -1.0f, -1.0f}
                       },
                       MAIN_CAMERA);

    camera.setTarget(Vector3{0.0f, 0.0f, 0.0f});

    // Create the player cube.
    Mesh mesh = GenMeshCube(2.0f, 2.0f, 2.0f);
    auto draw = dez::DrawObject(mesh, dez::Transform(), GREEN);
    auto object = dez::PhysicsObject(std::move(draw), 0.5f);

    object.transform.position = Vector3{0.0f, 5.0f, 0.0f};

    // Create a static ground plane.
    mesh = GenMeshCube(20.0f, 1.0f, 20.0f);
    draw = dez::DrawObject(
        mesh,
        dez::Transform({0.0f, -0.5f, 0.0f}),
        BROWN
    );

    auto ground = dez::PhysicsObject(std::move(draw));
    ground.is_static = true;

    return dez::manager::main(60, [&](float delta) {
        constexpr float LAUNCH_FORCE = 50.0f;
        constexpr float GRAVITY = 9.81f;

        if (IsKeyPressed(KEY_SPACE) && object.is_on_ground) {
            object.core.applyImpulse(
                Vector3{0.0f, LAUNCH_FORCE, 0.0f}
            );
        }

        object.core.applyAcceleration(
            Vector3{0.0f, -GRAVITY, 0.0f},
            delta
        );

        if (IsKeyPressed(KEY_Q)) {
            return false;
        }

        camera.setTarget(object.transform.position);

        dez::manager::tick(delta);

        return true;
    });
}

The object model

DimEngineZ is built around composing smaller pieces of functionality rather than putting everything into one large game-object abstraction. This is because I wanted to try out composition instead of inheritance, which I heard was better.

At the simplest level, a DrawObject can have a mesh, transform, and color:

auto draw = dez::DrawObject(
    mesh,
    dez::Transform(),
    GREEN
);

A PhysicsObject can then be constructed from that DrawObject, taking its position:

auto object = dez::PhysicsObject(
    std::move(draw),
    0.5f
);

This gives the object both its visual representation and physics-related state. The intention is that these systems remain useful independently while still being easy to combine when a game object needs multiple capabilities.

Physics

Physics objects expose basic operations for manipulating their motion. For example, acceleration can be applied over a time step:

object.core.applyAcceleration(
    Vector3{0.0f, -9.81f, 0.0f},
    delta
);

An impulse can be used for an instantaneous change in motion:

object.core.applyImpulse(
    Vector3{0.0f, 50.0f, 0.0f}
);

This makes simple behaviors such as gravity and jumping straightforward to implement without requiring a large physics API. Static objects can also be created for things that should participate in the simulation without being moved by it:

ground.is_static = true;

The engine loop

DimEngineZ provides its own application loop through manager::main().

A typical application supplies a target update rate and a callback:

return dez::manager::main(60, [&](float delta) {
    // Game logic

    dez::manager::tick(delta);

    return true;
});

60 here is the target frame rate, which also calculates the fixed delta, which the callback receives as delta, allowing game logic to operate using the elapsed timestep. manager::tick(delta) then advances the engine's managed systems, including physics and drawing. The main loop can provide a predictable update order and timing rather than requiring every application to build its own loop and timing infrastructure.

Cameras

DimEngineZ also provides a camera abstraction around Raylib's 3D camera functionality.

dez::Camera camera(
    {0.0f, 15.0f, 10.0f},
    dez::CameraOptions{
        .fovy = 90.0f,
        .direction = {0.0f, -1.0f, -1.0f}
    },
    MAIN_CAMERA
);

Cameras can then be updated as part of the game loop. For example, the camera in the example follows the physics object:

camera.setTarget(object.transform.position);

Or by changing its direction. Note that transform.position should not be updated manually; it is preferred to use move, moveX, etc. or goTo, goToX, etc. to move, as those update the camera's direction.

About

An experimental 3D game engine/Raylib wrapper.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages