A modular native C++ game engine built for fast workflows, integrated tooling, and hot-compiled ModuCPP scripting.





Modularity compiles for baseline x86-64, no AVX required, so it runs on low-power hardware most engines have dropped. On weaker machines it will offer to tune graphical effects, but only if you agree first.
Minimum to Play
Minimum to Develop
Recommended
Platform Support
All four options can drive the same 2D movement test. The difference is how much engine plumbing each layer exposes to the script author.
High-level gameplay scripting with built-in helpers.
| 1 | add ModuCPP; |
| 2 | add ModuInput; |
| 3 | add ModuEngine; |
| 4 | |
| 5 | public class Movement2DTest : ModuNode |
| 6 | { |
| 7 | public float walkSpeed = 4.0f; |
| 8 | public float runSpeed = 7.0f; |
| 9 | public float acceleration = 18.0f; |
| 10 | public float drag = 8.0f; |
| 11 | |
| 12 | void TickUpdate() |
| 13 | { |
| 14 | Vector2 move = input.WASDNormalized(); |
| 15 | bool running = input.sprint(); |
| 16 | float speed = running ? runSpeed : walkSpeed; |
| 17 | |
| 18 | TryMoveRigidbody2D(ctx, move * speed, acceleration, drag, dt); |
| 19 | obj.UILabel = "ModuCPP 2D Speed: " + IntR(speed); |
| 20 | } |
| 21 | } |
| 1 | #include "ModuCPP" |
| 2 | #include <cmath> |
| 3 | #include <string> |
| 4 | |
| 5 | namespace { |
| 6 | float walkSpeed = 4.0f; |
| 7 | float runSpeed = 7.0f; |
| 8 | } |
| 9 | |
| 10 | void TickUpdate(ScriptContext& ctx, float dt) |
| 11 | { |
| 12 | if (!ctx.object || dt <= 0.0f || !ctx.HasRigidbody2D()) return; |
| 13 | |
| 14 | glm::vec3 move3 = ctx.GetMoveInputWASD(0.0f, 0.0f); |
| 15 | glm::vec2 move(move3.x, move3.z); |
| 16 | |
| 17 | const float len = glm::length(move); |
| 18 | if (len > 0.0001f) { |
| 19 | move /= len; |
| 20 | } |
| 21 | |
| 22 | const float speed = ctx.IsSprintDown() ? runSpeed : walkSpeed; |
| 23 | ctx.SetRigidbody2DVelocity(move * speed); |
| 24 | ctx.SetUILabel(std::string("Native C++ 2D Speed: ") + ModuCPP::IntR(speed)); |
| 25 | } |
| 1 | using ModuMAKO; |
| 2 | using ModuEngine; |
| 3 | script "MovementThingy" : ModuNode; |
| 4 | Begin() { |
| 5 | EnsureRigidbody(true, false); |
| 6 | EnsureCapsuleCollider(1.8, 0.4); |
| 7 | settings = StandaloneMovementSettings(); |
| 8 | state = StandaloneMovementState(); |
| 9 | debug = StandaloneMovementDebug(); |
| 10 | |
| 11 | # Gravity stuff |
| 12 | for i in range(120) {TickStandaloneMovement(state, settings, 1 / 60, debug); } |
| 13 | AddLog("settled at y=" + obj.position.y, Type.Info); |
| 14 | assert(debug.grounded, "character reports grounded once settled"); |
| 15 | |
| 16 | # Movement stuff |
| 17 | start_x = obj.position.x; |
| 18 | state.localVelocity = Vector3(1, 0, 0) * settings.moveTuning.walkSpeed; |
| 19 | for i in range(60) {TickStandaloneMovement(state, settings, 1 / 60, debug);} |
| 20 | AddLog("moved to x=" + obj.position.x, Type.Info); |
| 21 | |
| 22 | # Jumping stuff |
| 23 | jumped = AddRigidbodyImpulse(Vector3(0, settings.locomotionTuning.jumpImpulse, 0)); |
| 24 | assert(jumped, "jump succeeds while grounded"); |
| 25 | TickStandaloneMovement(state, settings, 1 / 60, debug); |
| 26 | assert(debug.velocity.y > 0, "jump gives positive vertical velocity"); |
| 27 | assert(!debug.grounded, "character leaves the ground immediately after a jump"); |
| 28 | } |
| 1 | #include "ScriptRuntimeCAPI.h" |
| 2 | #include <math.h> |
| 3 | |
| 4 | static float g_walkSpeed = 4.0f; |
| 5 | static float g_runSpeed = 7.0f; |
| 6 | |
| 7 | void Modu_Begin(ModuScriptContext* ctx) { |
| 8 | if (!ctx) return; |
| 9 | Modu_AddConsoleMessage(ctx, "C bridge 2D movement test ready.", MODU_CONSOLE_INFO); |
| 10 | } |
| 11 | |
| 12 | void Modu_TickUpdate(ModuScriptContext* ctx, float dt) { |
| 13 | if (!ctx || dt <= 0.0f) return; |
| 14 | |
| 15 | ModuVec3 move = Modu_GetMoveInputWASD(ctx, 0.0f, 0.0f); |
| 16 | float len = sqrtf((move.x * move.x) + (move.z * move.z)); |
| 17 | if (len > 0.0001f) { |
| 18 | move.x /= len; |
| 19 | move.z /= len; |
| 20 | } else { |
| 21 | move.x = 0.0f; |
| 22 | move.z = 0.0f; |
| 23 | } |
| 24 | |
| 25 | float speed = Modu_IsSprintDown(ctx) ? g_runSpeed : g_walkSpeed; |
| 26 | ModuVec3 pos = Modu_GetPosition(ctx); |
| 27 | pos.x += move.x * speed * dt; |
| 28 | pos.z += move.z * speed * dt; |
| 29 | Modu_SetPosition(ctx, pos); |
| 30 | } |