‹›
Introduction

Basic Physics Loop

Shows the recommended order for initialization, input, simulation, synchronization, contacts, rendering, and cleanup.

The managed runtime owns a fixed-step accumulator inside jolt_update(). GameMaker continues to run normal events; your controller calls the physics lifecycle functions at deliberate points.

Lifecycle overview#

GameMaker eventPhysics work
CreateCall jolt_start(), create layers and persistent bodies.
Begin Step / Step before updateApply input, forces, impulses, and Kinematic targets.
StepCall jolt_update() exactly once for the managed world.
Step after updateRead transforms, sync instances, process contacts and raycasts.
DrawRender game assets; optionally call jolt_debug_draw().
CleanupCall jolt_stop() from the single world owner.

Complete controller example#

GML
// CREATE
jolt_start();
floor_body = jolt_box_create_static(0, 0, -0.5, 20, 20, 1);
player_instance = instance_find(obj_player, 0);
player_body = jolt_box_create_dynamic_for_instance(player_instance, 0.8, 0.8, 1.8, {mass: 80});

// STEP: apply input before simulation
if (keyboard_check(vk_right)) {
    player_body.add_force(300, 0, 0);
}

var physics_steps = jolt_update();
if (physics_steps >= 0) {
    player_body.sync();

    var contacts = player_body.get_collisions();
    for (var i = 0; i < array_length(contacts); ++i) {
        if (contacts[i].type == JOLT_COLLISION_ENTER) {
            show_debug_message("Contact began");
        }
    }
}

// CLEANUP
jolt_stop();

Ordering rules#

  • Start physics before creating layers, bodies, shapes, constraints, characters, or cloth.
  • Apply forces before jolt_update() when they should affect the current frame's simulation.
  • Call jolt_update() once per rendered frame from one authoritative controller.
  • Read and synchronize transforms after the update.
  • Read collision arrays after the update because contact queues are drained at its end.
  • Do not step the same managed default world from multiple objects.
  • Stop only after gameplay objects no longer need their physics resources.

Variable frame rate#

With no argument, jolt_update() reads GameMaker delta_time in microseconds and feeds a bounded fixed-step accumulator. It may return 0, 1, or several steps. The default fixed timestep is 1/60 second, the frame contribution is capped at 0.25 second, and one update processes at most 8 steps.

Errors#

GML
var steps = jolt_update();
if (steps < 0 || jolt_has_error()) {
    var error = jolt_get_error();
    show_debug_message(error.context + ": " + error.message);
}

High-level operations clear and replace the current managed error state as they run. Handle failure near the operation that can produce it rather than assuming an old error remains indefinitely.

Rendering and interpolation#

Rendering remains separate from simulation. The current high-level runtime retains the fractional accumulator internally but does not expose a public interpolation alpha. Render the latest transform or implement a game-side previous/current transform policy if smooth interpolation is required.