(Demo) Box2D Physics Code Samples

GeeXLab - Box2D Physics demo


The new GeeXLab 0.36.0 comes with the support of Box2D, a 2D physics engine for games. Box2D has a simple and neat API and creating the Box2D plugin for GeeXLab took me only few hours including the GeeXLab demo (50% of the time)!

Currently, the Box2D plugin supports only very basic functions: it can create 2D box and disc shaped objects (I called them actors like in PhysX and Bullet plugins), can run a simulation step and properties like density, friction, damping, velocity can be set. Contacts are also detected. Features like convex polygon shaped actors or joints will be added later. This first version of the Box2D plugin is more a prototype than a full featured plugin. Before going further with Box2D, I wanted to see how this physics engine worked and I must say, it works rather fine.

To play with Box2D, I prepared two demos, available in the OpenGL 2.1 demopack:

Here is a code snippet of the first Box2D demo (d56-box2d/01/) that shows the basic steps to create a 2D physics world with a ground and a falling box like on this screenshot:

This demo is equivalent to the Hello World project available with Box2D.

All Box2D functions are available in the gh_box2d library in Lua and Python.

In the INIT script:

-- Inits the Box2D engine.
-- Creates a scene (a world in Box2D)
b2_world = gh_box2d.world_init()
-- Sets the world gravity
gh_box2d.world_set_gravity(b2_world, 0, -10)
-- A static ground
ground_size = {x=20.0, y=0.5}
local density = 0.0
local friction = 0.6
local restitution = 0.1
b2_ground = gh_box2d.world_create_actor_box(b2_world, 
             0, -ground_size.y/2, 
             ground_size.x/2, ground_size.y/2,  
            "static", density, friction, restitution)
-- A dynamic box
box_size = {x=1.0, y=1.0}
density = 1000.0
friction = 0.4
restitution = 0.05
b2_box = gh_box2d.world_create_actor_box(b2_world, 0, 10,    
          box_size.x/2, box_size.y/2,   
          "dynamic", density, friction, restitution)
gh_box2d.actor_set_damping(b2_box, 0.0, 0.1)
gh_box2d.actor_set_transform(b2_box, 0, 10,   deg2rad(30.0))
gh_box2d.actor_set_linear_velocity(b2_box, 0.0, 0.0)
gh_box2d.actor_set_angular_velocity(b2_box, deg2rad(0.0))
-- Sleeping is not allowed here!!!!
gh_box2d.actor_set_sleeping_allowed(b2_box, 0)

Now the physics simulation and Box2D / GeeXLab synchronization.

In the FRAME script:

local elapsed_time = gh_utils.get_elapsed_time()
local dt = gh_utils.get_time_step()
rendering_scale = 50.0
world_y_offset = -200
-- Run a simulatiuon every 1/60 second (sim_dt == 1/60).
local can_run_simulation = 0
sim_time = sim_time + dt
if (sim_time >= sim_dt) then
  can_run_simulation = 1
  sim_time = 0
if (can_run_simulation == 1) then
  -- Reset the position of all dynamic actors
  if (reset_simulation == 1) then
    reset_simulation = 0
    gh_box2d.actor_set_transform(b2_box, math.random(-2, 2), 10,    deg2rad(0.0))
    gh_box2d.actor_set_linear_velocity(b2_box, 0, -5)
    gh_box2d.actor_set_angular_velocity(b2_box, deg2rad(math.random(10, 120)))
    gh_box2d.actor_set_awake(b2_box, 1)
  -- Perform a step simulation
  local velocity_iterations = 8
  local position_iterations = 4
  gh_box2d.world_step_simulation(b2_world, sim_dt, velocity_iterations, position_iterations)
  -- Synchronization: update the position and orientation (around Z axis only) of GeeXLab objects.
  posx, posy, angle = gh_box2d.actor_get_transform(b2_ground)
  gh_object.set_position(ground, posx*rendering_scale, posy*rendering_scale+world_y_offset, 0)
  gh_object.set_euler_angles(ground, 0, 0, rad2deg(angle))
  posx, posy, angle = gh_box2d.actor_get_transform(b2_box)
  gh_object.set_position(box, posx*rendering_scale, posy*rendering_scale+world_y_offset, 0)
  gh_object.set_euler_angles(box, 0, 0, rad2deg(angle))
-- Now we can render objects.

Two important notes:

1/ Like other physics engines, Box2D does not like variable time step for the simulation. So we run a simulation every 1/60 second and no more. The number of simulations is not linked to the frame rate.

2/ Box2D works in MKS units (Meter / Kilogram / Second). For objects size, one unit is one meter.
Then if you create a quad of 10 x 10 units, you will get a 10×10 meter quad in BoX2D. It’s not a problem for Box2D but it’s a big quad and don’t expect it will move fast like a small object. A big object, like in reality, will move slowly (for example if it is falling from a 100 meters tower). To deal with graphics rendering, we decouple the physics size and 3D/2D rendering size and we use a rendering_scale factor. So a 1×4 meter Box2D obstacle will be rendered with a 10×40 units quad if the rendering_scale=10.

The second Box2D demo (d56-box2d/02/) is a more advanced use of the first demo: more obstacles, more interaction. It’s more or less an embryo of 2D game: you can move a spaceship and shoot bullets on the dynamic obstacles or move a kinematic actor.

GeeXLab - Box2D Physics demo

Leave a Comment

Your email address will not be published. Required fields are marked *