Lua logo

Preface

This is the reference manual of MoonChipmunk, which is a Lua binding library for Scott Lembcke’s Chipmunk2D physics engine. [1]

It is assumed that the reader is familiar with both Chipmunk2D and the Lua programming language.

For convenience of reference, this document contains external (deep) links to the Lua Reference Manual and the Chipmunk2D Documentation.

Getting and installing

For installation intructions, refer to the README file in the MoonChipmunk official repository on GitHub.

Module organization

The MoonChipmunk module is loaded using Lua’s require() and returns a table containing the functions it provides (as usual with Lua modules). This manual assumes that such table is named cp, i.e. that it is loaded with:

 cp = require("moonchipmunk")

but nothing forbids the use of a different name.

Examples

Complete examples can be found in the examples/ directory of the release package.

License

MoonChipmunk is released under the MIT/X11 license (same as Lua, and with the same only requirement to give proper credits to the original author). The copyright notice is in the LICENSE file in the base directory of the official repository on GitHub.

See also

MoonChipmunk is part of MoonLibs, a collection of Lua libraries for graphics and audio programming.

Introduction

MoonChipmunk is an almost one-to-one Lua binding library to the Chipmunk2D physics engine. This means that by and large, it is intended to be used as described in the Chipmunk2D Manual (apart from coding in Lua, of course).

This section gives a brief overview of the binding library, while the details are given in the sections that follow.

MoonChipmunk binds Chipmunk2D objects (space, body, etc.) to Lua userdata, which are returned by the creating functions (cp.space_new( ), cp.body_new( ), etc) and are then used to refer to objects in Lua in the same way as one would use Chipmunk2D handles in C.

As a general rule, Chipmunk2D functions are bound to MoonChipmunk functions or methods whose names are snake_case versions of the original ones.

The functions related to an object type - with the exception of the creating function - are bounded to methods of that object (e.g. the C function cpSpaceSetGravity(space,…​) becomes the method space:set_gravity(…​) in Lua.

Objects are garbage collected at exit (which includes on error), and automatically deleted at the Chipmunk2D level, so there is no need to explicitly invoke their free( ) methods at exit for cleanup.

Apart from at exit, however, objects are not automatically garbage collected [2] and one must release them explicitly when needed, e.g. to release resources when the application is not exiting and some objects are no longer needed.

Releasing an object causes the automatic (pre) destruction of all its children objects, and the invalidation of any reference to the object and to its children. [3]

If not stated otherwise, on error all MoonChipmunk functions raise a Lua error. If needed, this behaviour can be overridden by wrapping function calls in the standard Lua pcall( ).

Objects

Listed below are the Lua object types in MoonChipmunk, together with the corresponding original types in Chipmunk2D:

Objects:
space (cpSpace, cpHastySpace)
body (cpBody)
shape (cpShape)
├─ circle (cpCircleShape)
├─ segment (cpSegmentShape)
└─ poly (cpPolyShape)
constraint (cpConstraint)
├─ pin_joint (cpPinJoint)
├─ slide_joint (cpSlideJoint)
├─ pivot_joint (cpPivotJoint)
├─ groove_joint (cpGrooveJoint)
├─ damped_spring (cpDampedSpring)
├─ damped_rotary_spring (cpDampedRotarySpring)
├─ rotary_limit_joint (cpRotaryLimitJoint)
├─ ratchet_joint (cpRatchetJoint)
├─ gear_joint (cpGearJoint)
└─ simple_motor (cpSimpleMotor)
Collision handlers (cpCollisionHandler)
Arbiters (cpArbiter)

Spaces

Rfr: cpSpace.

  • space = space_new( )
    space = hasty_space_new( )
    space:free( )
    Create/delete a space.

  • space:set_threads(n)
    n = space:get_threads( )
    For hasty spaces only.

  • space:step(dt)
    space:nstep(dt, n)

  • dt = space:get_current_time_step( )
    dt: float (seconds).
    n: number of steps.

  • boolean = space:is_locked( )

  • space:set_gravity(gravity)
    space:set_damping(damping)
    gravity = space:get_gravity( )
    damping = space:get_damping( )
    gravity: vec (defaults to {0, 0}).
    damping: float (defaults to 1.0).

  • space:set_iterations(n)
    n = space:get_iterations( )

  • space:set_idle_speed_threshold(ist)
    space:set_sleep_time_threshold(stt)
    ist = space:get_idle_speed_threshold( )
    stt = space:get_sleep_time_threshold( )
    ist: float (defaults to 0).
    stt: float (defaults to math.huge).

  • space:set_collision_slop(cs)
    space:set_collision_bias(cb)
    space:set_collision_persistence(cp)
    cs = space:get_collision_slop( )
    cb = space:get_collision_bias( )
    cp = space:get_collision_persistence( )
    cs: float (defaults to 0.1).
    cb: float (defaults to (1 - 0.1)60).
    cp: number of frames (defaults to 3).

  • body = space:get_static_body( )

  • space:reindex_static( )
    space:reindex_shape(shape)
    space:reindex_shapes_for_body(body)
    space:use_spatial_hash(dim, count)

  • space:each_body(func)
    space:each_shape(func)
    space:each_constraint(func)
    Execute func as func(space, object) for each object of the given type.

  • collision_handler = space:add_default_collision_handler( )
    collision_handler = space:add_collision_handler(typea, typeb)
    collision_handler = space:add_wildcard_handler(type)
    See collision_handler.

  • space:add_post_step_callback(func)
    The post-step callback is executed as func(space).

  • pointqueryinfo|nil = space:point_query_nearest(point, maxdist, shapefilter)
    segmentqueryinfo|nil = space:segment_query_first(pstart, pend, radius, shapefilter)
    space:point_query(point, maxdist, shapefilter, func)
    space:segment_query(pstart, pend, radius, shapefilter, func)
    space:bb_query(bb, shapefilter, func)
    space:shape_query(shape, func)
    point, pstart, pend: vec.
    maxdist, radius: float.
    shapefilter: shapefilter.
    The func callbacks are executed for each hit shape, as follows:
    - point query: func(space, shape, point, distance) (point: vec, distance: float).
    - segment query: func(space, shape, point, normal, alpha) (point, normal: vec, alpha: float).
    - bb query: func(space, shape).
    - shape query: func(space, shape, normal, {points}) ( normal: vec, {points}: {contactpoint}).

  • space:debug_draw( )
    space:set_debug_draw_options(draw_circle, draw_segment, …​)
    Arguments for set_debug_draw_options( ):
    arg1: space (implicit argument).
    arg2: draw_circle: a function, executed as func(angle, radius, outlinecolor, fillcolor).
    arg3: draw_segment: a function, executed as func(a, b, color)
    arg4: draw_fat_segment: a function, executed as func(a, b, radius, outlinecolor, fillcolor).
    arg5: draw_polygon: a function, executed as func({verts}, radius, outlinecolor, fillcolor)
    arg6: draw_dot: a function, executed as func(size, pos, color).
    arg7: color_for_shape: a function, executed as color = func(shape)
    arg8: flags: integer (cpSpaceDebugDrawFlags)
    arg9: shape_outline_color: color,
    arg10: constraint_color: color,
    arg11: collision_point_color: color.

Rigid bodies

Rfr: cpBody.

  • body = body_new(mass, moment)
    body = body_new_kinematic( )
    body = body_new_static( )
    body:free( )
    Create/delete a rigid body.

  • space|nil = body:get_space( )

  • body:set_type(type)
    type = body:get_type( )
    type: 'dynamic' |, 'kinematic' | 'static'.

  • body:set_mass(value)
    body:set_moment(value)
    body:set_angle(value)
    body:set_angular_velocity(value)
    body:set_torque(value)
    value = body:get_mass( )
    value = body:get_moment( )
    value = body:get_angle( )
    value = body:get_angular_velocity( )
    value = body:get_torque( )
    value = body:kinetic_energy( )
    value: float.
    Angles are in radians.

  • body:set_position(vec)
    body:set_center_of_gravity(vec)
    body:set_velocity(vec)
    body:set_force(vec)
    vec = body:get_position( )
    vec = body:get_center_of_gravity( )
    vec = body:get_velocity( )
    vec = body:get_force( )
    vec = body:get_rotation( )

  • vec = body:local_to_world(vec)
    vec = body:world_to_local(vec)
    vec = body:get_velocity_at_world_point(vec)
    vec = body:get_velocity_at_local_point(vec)

  • body:apply_force_at_world_point(point, value)
    body:apply_force_at_local_point(point, value)
    body:apply_impulse_at_world_point(point, value)
    body:apply_impulse_at_local_point(point, value)
    point, value: vec.

  • body:update_position(dt)
    body:update_velocity(gravity, damping, dt)
    body:set_position_update_func(func)
    body:set_velocity_update_func(func)
    dt, damping: float.
    gravity: vec.
    The update callbacks are executed as follows:
    - position update: func(body, dt).
    - velocity update: func(body, gravity, damping, dt).

  • body:sleep( )
    body:sleep_with_group([group])
    body:activate( )
    body:activate_static([filter])
    boolean = body:is_sleeping( )
    group: body.
    filter: shape.

  • body:each_shape(func)
    body:each_constraint(func)
    body:each_arbiter(func)
    Execute func as func(body, object) for each object of the given type.

Shapes

Rfr: cpShape.

Constructors and specialized methods are available for the following subtypes:

Common methods:

  • shape:free( )
    Delete shape.

  • shape:set_body(body)
    body = shape:get_body( )
    space = shape:get_space( )

  • bb = shape:update(transform)
    transform: mat.

  • shape:set_mass(value)
    shape:set_density(value)
    shape:set_elasticity(value)
    shape:set_friction(value)
    value = shape:get_mass( )
    value = shape:get_moment( )
    value = shape:get_area( )
    value = shape:get_density( )
    value = shape:get_elasticity( )
    value = shape:get_friction( )
    value: float.

  • shape:set_surface_velocity(vec)
    vec = shape:get_surface_velocity( )
    vec = shape:get_center_of_gravity( )

  • bb = shape:get_bb( )
    bb = shape:cache_bb( )

  • shape:set_sensor(boolean)
    boolean = shape:get_sensor( )

  • shapefilter = shape_filter_new(group, categories, bitmask)
    shapefilter = shape_filter_all( )
    shapefilter = shape_filter_none( )
    Shape filter constructor and built-in shape filters (CP_SHAPE_FILTER_XXX).
    Note that a shape filter is a plain Lua table, and thus may also be manually constructed.

  • shape:set_collision_type(value)
    value = shape:get_collision_type( )
    value: integer.

circle

  • shape = circle_shape_new(body, radius, [offset])
    shape:set_radius(radius) UNSAFE
    shape:set_offset(offset) UNSAFE
    radius = shape:get_radius( )
    offset = shape:get_offset( )
    radius: float.
    offset: vec (defaults to {0, 0}).

segment

  • shape = segment_shape_new(body, a, b, radius)
    shape:set_radius(radius) UNSAFE
    shape:set_endpoints(a, b) UNSAFE
    shape:set_neighbors(prev, next) UNSAFE
    radius = shape:get_radius( )
    a, b = shape:get_endpoints( )
    normal = shape:get_normal( )
    a, b, prev, next, normal: vec.
    radius: float.

poly

  • shape = poly_shape_new(body, {verts}, radius, [transform])
    shape = box_shape_new(body, width, height, radius)
    shape = box_shape_new(body, bb, radius)
    shape:set_radius(radius) UNSAFE
    shape:set_verts({verts}, [transform]) UNSAFE
    radius = shape:get_radius( )
    {verts} = shape:get_verts( )
    nverts = shape:get_count( )
    {verts}: {vec}.
    radius, width, height: float.
    transform: mat (defaults to the identity transform).

Constraints

Rfr: cpConstraint.

Constructors and specialized methods are available for the following subtypes:

Common methods:

  • constraint:free( )
    Delete constraint.

  • space|nil = constraint:get_space( )
    bodya, bodyb = constraint:get_bodies( )
    bodya = constraint:get_body_a( )
    bodyb = constraint:get_body_b( )

  • constraint:set_max_force(value)
    constraint:set_error_bias(value)
    constraint:set_max_bias(value)
    value = constraint:get_max_force( )
    value = constraint:get_error_bias( )
    value = constraint:get_max_bias( )
    value = constraint:get_impulse( )
    value: float.

  • constraint:set_collide_bodies(boolean)
    boolean = constraint:get_collide_bodies( )

  • constraint:set_pre_solve_func([func])
    constraint:set_post_solve_func([func])
    func|nil = constraint:get_pre_solve_func( )
    func|nil = constraint:get_post_solve_func( )
    Both the pre-solve and post-solve functions are executed as func(constraint, space).

  • boolean = constraint:is_pin_joint( )
    boolean = constraint:is_slide_joint( )
    boolean = constraint:is_pivot_joint( )
    boolean = constraint:is_groove_joint( )
    boolean = constraint:is_damped_spring( )
    boolean = constraint:is_damped_rotary_spring( )
    boolean = constraint:is_rotary_limit_joint( )
    boolean = constraint:is_ratchet_joint( )
    boolean = constraint:is_gear_joint( )
    boolean = constraint:is_simple_motor( )

pin_joint

  • constraint = pin_joint_new(bodya, bodyb, anchora, anchorb)
    constraint:set_anchor_a(anchora)
    constraint:set_anchor_b(anchorb)
    constraint:set_dist(dist)
    anchora = constraint:get_anchor_a( )
    anchorb = constraint:get_anchor_b( )
    dist = constraint:get_dist( )
    anchora, anchorb: vec.

slide_joint

  • constraint = slide_joint_new(bodya, bodyb, anchora, anchorb, min, max)
    constraint:set_anchor_a(anchora)
    constraint:set_anchor_b(anchorb)
    constraint:set_min(min)
    constraint:set_max(max)
    anchora = constraint:get_anchor_a( )
    anchorb = constraint:get_anchor_b( )
    min = constraint:get_min( )
    max = constraint:get_max( )
    anchora, anchorb: vec.
    min, max: float.

pivot_joint

  • constraint = pivot_joint_new(bodya, bodyb, pivot)
    constraint = pivot_joint_new(bodya, bodyb, anchora, anchorb)
    constraint:set_anchor_a(anchora)
    constraint:set_anchor_b(anchorb)
    anchora = constraint:get_anchor_a( )
    anchorb = constraint:get_anchor_b( )
    pivot, anchora, anchorb: vec.

groove_joint

  • constraint = groove_joint_new(bodya, bodyb, groovea, grooveb, anchorb)
    constraint:set_groove_a(groovea)
    constraint:set_groove_b(grooveb)
    constraint:set_anchor_b(anchorb)
    groovea = constraint:get_groove_a( )
    grooveb = constraint:get_groove_b( )
    anchorb = constraint:get_anchor_b( )
    groovea, grooveb, anchorb: vec.

damped_spring

  • constraint = damped_spring_new(bodya, bodyb, anchora, anchorb, rest_length, stiffness, damping)
    constraint:set_anchor_a(anchora)
    constraint:set_anchor_b(anchorb)
    constraint:set_rest_length(rest_length)
    constraint:set_stiffness(stiffness)
    constraint:set_damping(damping)
    constraint:set_spring_force_func(func)
    anchora = constraint:get_anchor_a( )
    anchorb = constraint:get_anchor_b( )
    rest_length = constraint:get_rest_length( )
    stiffness = constraint:get_stiffness( )
    damping = constraint:get_damping( )
    func = constraint:get_spring_force_func( )
    anchora, anchorb: vec.
    rest_length, stiffness, damping: float.
    The spring force function is called as force = func(constraint, distance) (force: float).

damped_rotary_spring

  • constraint = damped_rotary_spring_new(bodya, bodyb, rest_angle, stiffness, damping)
    constraint:set_rest_angle(rest_angle)
    constraint:set_stiffness(stiffness)
    constraint:set_damping(damping)
    constraint:set_spring_torque_func(func)
    rest_angle = constraint:get_rest_angle( )
    stiffness = constraint:get_stiffness( )
    damping = constraint:get_damping( )
    func = constraint:get_spring_torque_func( )
    rest_angle, stiffness, damping: float.
    The spring torque function is called as torque = func(constraint, relative_angle) (torque: float).

rotary_limit_joint

  • constraint = rotary_limit_joint_new(bodya, bodyb, min, max)
    constraint:set_min(min)
    constraint:set_max(max)
    min = constraint:get_min( )
    max = constraint:get_max( )
    min, max: float.

ratchet_joint

  • constraint = ratchet_joint_new(bodya, bodyb, phase, ratchet)
    constraint:set_phase(phase)
    constraint:set_ratchet(ratchet)
    constraint:set_angle(angle)
    phase = constraint:get_phase( )
    ratchet = constraint:get_ratchet( )
    angle = constraint:get_angle( )
    phase, ratchet, angle: float.

gear_joint

  • constraint = gear_joint_new(bodya, bodyb, phase, ratio)
    constraint:set_phase(phase)
    constraint:set_ratio(ratio)
    phase = constraint:get_phase( )
    ratio = constraint:get_ratio( )
    phase, ratio: float.

simple_motor

  • constraint = simple_motor_new(bodya, bodyb, rate)
    constraint:set_rate(rate)
    rate = constraint:get_rate( )
    rate: float.

Collision handlers

  • collision_handler = space:add_default_collision_handler( )
    collision_handler = space:add_collision_handler(typea, typeb)
    collision_handler = space:add_wildcard_handler(type)
    type, typea, typeb: integer (cpCollisionType).

  • collision_handler:free( )
    Delete collision_handler.

  • typea, typeb = collision_handler:get_types( )
    collision_handler:set_begin_func(func)
    collision_handler:set_pre_solve_func(func)
    collision_handler:set_post_solve_func(func)
    collision_handler:set_separate_func(func)
    The callbacks are executed as follows:
    - begin: boolean = func(arbiter, space).
    - pre solve: boolean = func(arbiter, space).
    - post solve: func(arbiter, space).
    - separate: func(arbiter, space).

Arbiters

Rfr: cpArbiter.

From the point of view of the Lua scripts, an arbiter object is automatically created when it is received as argument to some callback function, and automatically deleted as soon as the function returns.

  • arbiter:set_restitution(value)
    arbiter:set_friction(value)
    value = arbiter:get_restitution( )
    value = arbiter:get_friction( )
    value = arbiter:total_ke( )
    value: float.

  • arbiter:set_surface_velocity(vec)
    vec = arbiter:get_surface_velocity( )
    vec = arbiter:get_normal( )
    vec = arbiter:total_impulse( )

  • boolean = arbiter:ignore( )
    boolean = arbiter:is_first_contact( )
    boolean = arbiter:is_removal( )

  • arbiter:set_contact_point_set(normal, {points})
    normal, {points} = arbiter:get_contact_point_set( )
    normal: vec.
    {points}: {contactpoint}.

  • npoints = arbiter:get_count( )
    {pointa}, {pointb}, {depth} = arbiter:get_points( )
    {pointa}, {pointb}: {vec}.
    {depth}: {float}.

  • boolean = arbiter:call_wildcard_begin_a(arbiter, space)
    boolean = arbiter:call_wildcard_begin_b(arbiter, space)
    boolean = arbiter:call_wildcard_pre_solve_a(arbiter, space)
    boolean = arbiter:call_wildcard_pre_solve_b(arbiter, space)
    arbiter:call_wildcard_post_solve_a(arbiter, space)
    arbiter:call_wildcard_post_solve_b(arbiter, space)
    arbiter:call_wildcard_separate_a(arbiter, space)
    arbiter:call_wildcard_separate_b(arbiter, space)

  • value = arbiter:get_user_index( )
    arbiter:set_user_index(value)
    Set/get a user-defined integer index associated with the arbiter.
    This is a limited binding to cpArbiterSetUserData( ) and cpArbiterGetUserData( ): it doesn’t allow you to directly associate a generic user data value with the arbiter, but you can store it in a table and associate with the arbiter the corresponding index instead.
    Note that you can’t use the arbiter itself to index the user data table, because the arbiter Lua object is actually a singleton that is reused every time a cpArbiter is passed to a callback. (From the Chipmunk Manual: "[…​] you should never store a reference to an arbiter as you don’t know when they will be freed or reused.").

Miscellanea

Float utilities

  • value = fclamp(f, a, b)
    value = fclamp01(f)
    value = flerp(f1, f2, f)
    value = flerpconst(f1, f2, f)
    value, f, f1, f2, a, b: float.

Vector utilities

Rfr: cpVect.

  • boolean = veql(v1, v2)
    v = vadd(v1, v2)
    v = vsub(v1, v2)
    v = vneg(v1)
    v = vmult(v1, v2)
    value = vdot(v1, v2)
    value = vcross(v1, v2)
    v = vperp(v1)
    v = vrperp(v1)
    v = vproject(v1, v2)
    v = vforangle(angle)
    angle = vtoangle(v)
    v = vrotate(v1, v2)
    v = vunrotate(v1, v2)
    value = vlength(v1)
    value = vlengthsq(v1)
    value = vdist(v1, v2)
    value = vdistsq(v1, v2)
    v = vnormalize(v1)
    v = vclamp(v1, len)
    boolean = vnear(v1, v2, d)
    v = vlerp(v1, v2, d)
    v = vslerp(v1, v2, d)
    v = vlerpconst(v1, v2, d)
    v = vslerpconst(v1, v2, d)
    v, v1, v2: vec.
    value, angle, len, d: float.

Transform utilities

Rfr: cpTransform.

  • m = transform_identity( )
    m = transform_new(a, b, c, d, tx, ty)
    m = transform_new_transpose(a, c, tx, b, d, ty)
    m = transform_inverse(m1)
    m = transform_mult(m1, m2)
    p = transform_point(m, p)
    v = transform_vect(m, v)
    bb = transform_bb(m, bb)
    m = transform_translate(v)
    m = transform_scale(sx, sy)
    m = transform_rotate(angle)
    m = transform_rigid(v, angle)
    m = transform_rigid_inverse(m1)
    m = transform_wrap(mouter, minner)
    m = transform_wrap_inverse(mouter, minner)
    m = transform_ortho(bb)
    m = transform_bone_scale(v1, v2)
    m = transform_axial_scale(axis, pivot, scale)
    m, m1, _m2, mouter, minner: mat.
    p, v, v1, v2, axis, pivot: vec.
    bb: bb.
    a, b, c, d, tx, ty, sx, sy, angle, scale: float.

Bounding box utilities

Rfr: cpBB.

  • bb = bb_new_for_extents(center, halfwidth, halfheight)
    bb = bb_new_for_circle(center, radius)
    boolean = bb_intersects(bb1, bb2)
    boolean = bb_contains_bb(bb1, bb2)
    boolean = bb_contains_vect(bb, v)
    bb = bb_merge(bb1, bb2)
    bb = bb_expand(bb1, v)
    center = bb_center(bb)
    area = bb_area(bb)
    area = bb_merged_area(bb1, bb2)
    f = bb_segment_query(bb, a, b)
    boolean = bb_intersects_segment(bb, a, b)
    v = bb_clamp_vect(bb, v)
    v = bb_wrap_vect(bb, v)
    bb = bb_offset(bb, v)
    bb, bb1, bb2: bb.
    center, v, a, b: vec.
    width, height, area, f: float.

  • march_soft(bb, xsamples, ysamples, threshold, samplefunc, segmentfunc )
    march_hard(bb, xsamples, ysamples, threshold, samplefunc, segmentfunc )
    bb: bb.
    xsamples, ysamples: integer.
    threshold: float.
    The sample function is executed as density = func(p) (density: float, p: vec).
    The segment function is executed as func(a, b) (a, b: vec).

Moments, areas, etc

Rfr:https://chipmunk-physics.net/release/ChipmunkLatest-API-Reference/group__misc.html[cp misc].

  • moment = moment_for_circle(mass, rinner, router, offset)
    moment = moment_for_segment(mass, pointa, pointb, radius)
    moment = moment_for_poly(mass, {verts}, offset, radius)
    moment = moment_for_box(mass, width, height)
    moment = moment_for_box(mass, bb)
    area = area_for_circle(rinner, router)
    area = area_for_segment(pointa, pointb, radius)
    area = area_for_poly({verts}, radius)
    centroid = centroid_for_poly({verts})
    {verts} = convex_hull({verts}, tol)
    moment, area, mass, rinner, router, radius, width, height, tol: float.
    pointa, pointb, offset, centroid: vec.
    {verts}: {vec}.

  • p = closest_point_on_segment(p, a, b)
    Returns the point on the segment (a, b) that is closest to the point p.
    p, a, b: vec.

Data types

In this document, the float and integer types denote Lua numbers, while other types such as boolean, string, etc denote standard Lua types. Note that float here just means 'floating point' as opposed to 'integer', and does not imply single-precision (all numbers are actually represented internally using double-precision).

Angles are always expressed in radians.

Vectors, matrices, bounding boxes, and colors are by default represented as Lua arrays containing float elements (or arrays of arrays in the case of matrices). The meaning of the elements thus depends on their position, as detailed below, and there is no syntactic sugar such as v.x and v.y to access them (unless one enables GLMATH compatibility).

A few other Chipmunk2D structs are represented as string-indexed Lua tables, also described below.

  • vec = {x, y}
    All elements are floats.
    (Rfr: cpVect)

  • mat = {{a, c, tx}, {b, d, ty}}
    All elements are floats.
    (Rfr: cpTransform)

  • bb = {l, r, b, t}
    All elements are floats.
    Beware that the order is different than in cpBB (where the order is l, b, r, t).
    (Rfr: cpBB)

  • color = {r, g, b, a}
    All elements are floats, representing normalized color components (i.e. in the range [0, 1]).
    (Rfr: cpSpaceDebugColor)

  • shapefilter = {
    group: integer,
    categories: integer,
    mask: integer,
    } (Rfr: cpShapeFilter)

  • pointqueryinfo = {
    shape: shape,
    point: vec,
    distance: float,
    gradient: vec,
    } (Rfr: cpPointQueryInfo)

  • segmentqueryinfo = {
    shape: shape,
    point: vec,
    normal: vec,
    alpha: float,
    } (Rfr: cpSegmentQueryInfo)

  • contactpoint = {
    a: vec,
    b: vec,
    distance: float,
    } (Rfr: cpContactPointSet)

GLMATH compatibility

As an option, it is possible to instruct MoonChipmunk to return vectors, matrices, boxes, and colors as MoonGLMATH types, instead of returning them as plain tables (which is the default). [4]

In particular, when this functionality is enabled, functions and methods will return values of the following MoonGLMATH types: vec2 instead of vec, mat2x3 instead of mat, box2 instead of bb, and vec4 instead of color.

(Notice that for function arguments nothing changes, since the above MoonGLMATH types are compatible with the corresponding plain tables used by default, thus they can be used as function arguments in any case).

Use the following functions to control GLMATH compatibility:

  • glmath_compat(boolean)
    Enables/disables GLMATH compatibility (which by default is disabled).
    Enabling this functionality requires MoonGLMATH to be installed.

  • boolean = is_glmath_compat( )
    Returns true if GLMATH compatibility is enabled.

Toolbox

MoonChipmunk comes with a 'toolbox' submodule, located in moonchipmunk/toolbox.lua. This submodule provides the tools that are used in examples and demos for rendering, input handling, and more.

In addition to MoonChipmunk itself, the toolbox uses (and thus requires) the following libraries from the MoonLibs collection:

  • MoonGL: bindings to the OpenGL API, for graphics rendering.

  • MoonGLFW: bindings to GLFW, for window/surface creation and input handling.

  • MoonGLMATH: graphics math library.

  • MoonFreeType: bindings to FreeType, for loading fonts.

  • MoonImage: bindings to stb_image, for loading images.

  • MoonSndFile: bindings to libsndfile, for loading sound samples.

  • MoonAL: bindings to OpenAL, for rendering audio.

(Note that MoonChipmunk itself does not depend on the above libraries. Only the toolbox does, and its use in an application is optional).

The examples and demos, together with the comments in the toolbox script, should hopefully suffice to show how the tools are meant to be used.


1. This manual is written in AsciiDoc, rendered with AsciiDoctor and a CSS from the AsciiDoctor Stylesheet Factory.
2. Objects are anchored to the Lua registry at their creation, so even if the script does not have references to an object, a reference always exists on the registry and this prevents the GC to collect it.
3. It is good practice to not leave invalid references to objects around, because they prevent the GC to collect the memory associated with the userdata.
4. MoonGLMATH types are convenient because they support operators and synctatic sugar, but I chose not to impose their use because one may want to use an alternative math library, or none at all.