Getting Started

Nova Physics is a lightweight 2D rigid body physics engine. It is designed with game development in mind. It is written in portable C with no dependencies other than the standard library, meaning anyone can easily write a binding for their favored programming language.

Nova Physics is, and always will be, free and open-source.

Hello World

After installing (you can follow installing), you are ready for your first Nova Physics program, where a ball free falls onto a ground and we print its coordinates every step.

 1#include <stdio.h>
 2#include "novaphysics/novaphysics.h"
 3
 4
 5int main() {
 6    // Create an empty simulation space
 7    nvSpace *space = nvSpace_new();
 8
 9
10    /* Create a ground body with a rectangle shape. */
11
12    // The initializer struct is used to set basic properties of a body before creation.
13    // Making the motion type static means the body will never move under simulation.
14    nvRigidBodyInitializer body_init = nvRigidBodyInitializer_default;
15    body_init.type = nvRigidBodyType_STATIC;
16    body_init.position = NV_VECTOR2(0.0, 20.0); // NV_VECTOR2 is a utility macro to quickly initialize vectors.
17    body_init.material = nvMaterial_CONCRETE; // You can initialize a custom material as well.
18    nvRigidBody *ground = nvRigidBody_new(body_init);
19
20    // After creating the rigid body, we have to assign a shape.
21    nvShape *ground_shape = nvBoxShape_new(10.0, 1.0, nvVector2_zero);
22    nvRigidBody_add_shape(ground, ground_shape);
23
24    // We can finally add ground body to space.
25    nvSpace_add_rigidbody(space, ground);
26
27
28    /* Now create a ball that is going to fall and bounce off the ground. */
29
30    // We can use the same initializer struct by changing the necessary fields.
31    // This time the motion type have to by dynamic so the ball can be simulated under physical forces.
32    // We also initialize a custom material with restitution 0.85, so it can bounce
33    body_init.type = nvRigidBodyType_DYNAMIC;
34    body_init.position = NV_VECTOR2(0.0, 0.0);
35    body_init.material = (nvMaterial){.density=1.0, .restitution=0.85, .friction=0.1};
36    nvRigidBody *ball = nvRigidBody_new(body_init);
37
38    // Now we assign a circle shape to our body with radius 1.0
39    nvShape *ball_shape = nvCircleShape(nvVector2_zero, 1.0);
40    nvRigidBody_add_shape(ball, ball_shape);
41
42    nvSpace_add_rigidbody(space, ground);
43
44
45    /* The scene is set up. Now we only have to simulate it! */
46
47    // This is the time step length the engine going to simulate the space in.
48    nv_float dt = 1.0 / 60.0;
49
50    // Let's simulate for 5 seconds.
51    nv_float duration = 5.0;
52
53    for (nv_float t = 0.0; t < duration; t += dt) {
54        nvVector2 position = nvRigidBody_get_position(ball);
55        nvVector2 velocity = nvRigidBody_get_linear_velocity(ball);
56
57        printf(
58            "Ball is at (%.2f, %.2f) with velocity (%.2f, %.2f) at time %.2f.\n",
59            position.x, position.y,
60            velocity.x, velocity.y,
61            t
62        );
63
64        // Advance the simulation.
65        nvSpace_step(space, dt);
66    }
67
68    // Free the space and all resources it used.
69    // Space also manages the bodies, shapes and constraints we add to it.
70    // Unless you removed them manually, in that case you have to free your bodies.
71    nvSpace_free(space);
72}

When the code is run, we can see that the ball bounces on the ground few times and then rests.