DatumHuePlatform v0.0.24datumhue.com
Contents

Bodies, joints and collisions

Make shapes fall, carry one another and hang from joints, and run code when they collide.

Add physics, in the ball pit tutorial, gives the first shapes bodies. This guide goes further: moving platforms, joints, collision handlers and the rules that keep a simulation steady.

Give a shape a body

DrawPrimitive:add_body gives a shape on a draw canvas a body in your app's 2D world, and SceneNode:add_body gives a 3D node one in its 3D world. Without a shape, the collider fits what the handle draws. Sizes and positions are in the handle's own units: canvas pixels on a draw canvas.

Each body has a type, which decides what moves it:

TypeWhat moves itUse it for
dynamicthe simulation: gravity, collisions, impulsesthings that fall, roll and bounce
kinematicyour code alone; it carries what rests on itplatforms, elevators, doors
staticyour code alone; it pushes what rests on it asidefloors, walls, pins

Gravity, physics.gravity, starts out right for a 3D scene measured in meters. On a canvas measured in pixels that is a gentle pull, so the program below sets a stronger one.

This program drops three boxes onto a sliding platform, turning each box red when it first touches something, and swings a bar from a pin:

platform.lualua
local color = datumhue.color
local vec2 = datumhue.math.vec2
local vec3 = datumhue.math.vec3
local physics = datumhue.physics

-- A canvas measures in pixels, so pull harder than the default.
physics.gravity = vec2(0, -600)

local canvas = datumhue.draw.new({
    width = 480,
    height = 320,
    background = color("#2d353b"),
})
canvas:mount({ width = 480, height = 320 })

-- A kinematic platform goes where you move it, and carries
-- what lands on it.
local platform = canvas:rect({
    pos = vec2(-200, -120),
    width = 160,
    height = 16,
    color = color("#7fbbb3"),
})
platform:add_body({ type = "kinematic" })
platform:animate({
    pos = vec2(-20, -112),
    duration = 2,
    easing = "sine_in_out",
    looping = true,
})

-- Dynamic boxes fall onto it, and turn red at their first
-- touch.
for i = 0, 2 do
    local box = canvas:rect({
        pos = vec2(-150 + i * 30, 20 + i * 50),
        width = 24,
        height = 24,
        color = color("#dbbc7f"),
    })
    box:add_body({ type = "dynamic" })
    box:on_collision_start(function()
        box:update({ color = color("#e67e80") })
    end)
end

-- A pendulum: a bar hinged at its left end to a fixed pin.
local pin = canvas:circle({
    pos = vec2(120, 100),
    radius = 6,
    color = color("#d3c6aa"),
})
pin:add_body({ type = "static" })
local bar = canvas:rect({
    pos = vec2(120, 95),
    width = 120,
    height = 10,
    color = color("#a7c080"),
})
bar:add_body({ type = "dynamic" })
-- Anchors are in each shape's own units, from its center: the
-- pin's center, and the bar's left end, 60 px left of its own.
physics.add_joint(pin, bar, {
    type = "revolute",
    anchor2 = vec3(-60, 0, 0),
})

In this example: datumhue.color datumhue.math.vec2 datumhue.math.vec3 datumhue.physics datumhue.physics.gravity datumhue.draw.new DrawCanvas:mount DrawCanvas:rect DrawPrimitive:add_body DrawPrimitive:animate DrawPrimitive:on_collision_start DrawPrimitive:update DrawCanvas:circle datumhue.physics.add_joint

Move bodies the right way

A static or kinematic body goes wherever its handle goes. Assign pos or rotation, call update, or tween it with animate, and the body follows at the next physics step. Move a group, and the bodies inside it follow too.

A dynamic body moves itself. Push it with DrawPrimitive:apply_impulse for a kick or DrawPrimitive:apply_force for a steady push, or assign DrawPrimitive.velocity.

A static or kinematic body inside a dynamic one, in a group or under a scene node, rides along with the nearest dynamic body above it, one step behind, and never collides with it.

Join bodies

physics.add_joint joins two bodies of the same world. A revolute joint is a hinge, as the pendulum's; prismatic slides along an axis, distance keeps bodies within a rope's length, spherical is a ball joint in 3D, and fixed welds them together. The joint holds the pose the bodies are in when you make it, and limits and motors on physics.JointOptions bound its travel or drive it.

React to collisions

DrawPrimitive:on_collision_start runs when a body starts touching another, as the boxes do, and DrawPrimitive:on_collision_end when they part. The handler gets the other handle and, on start, a physics.Contact with the point and direction of the hit.

A body with sensor = true collides with nothing, but still reports what enters and leaves it: a trigger zone for a goal or a pickup. layers and collides_with decide which bodies meet at all, so bullets can pass through their own team.

Ask what is where

physics.raycast finds the first body along a ray, and physics.point_query every body at a point. For a character that walks and climbs steps under your own controls, give a kinematic body DrawPrimitive:character_controller.

Each app simulates in its own worlds: its bodies, joints, queries and gravity never meet another app's, and physics needs no permission. physics.world makes a further world of your own, with its own gravity.

See also

Reference used on this page: datumhue.color datumhue.math.vec2 datumhue.math.vec3 datumhue.physics datumhue.physics.gravity datumhue.draw.new DrawCanvas:mount DrawCanvas:rect DrawPrimitive:add_body DrawPrimitive:animate DrawPrimitive:on_collision_start DrawPrimitive:update DrawCanvas:circle datumhue.physics.add_joint SceneNode:add_body DrawPrimitive:apply_impulse DrawPrimitive:apply_force DrawPrimitive.velocity physics.JointOptions DrawPrimitive:on_collision_end physics.Contact datumhue.physics.raycast datumhue.physics.point_query DrawPrimitive:character_controller datumhue.physics.world

datumhue.com

(c) 2026 Shuusei AB. Quote excerpts of this manual, with attribution to DatumHue, in your own documentation, tutorials, course materials, reviews, and other writing or video. Republishing it in whole or in substantial part needs written permission: support@datumhue.com.

Victor Mono is licensed under the SIL Open Font License 1.1
Copyright (c) 2024, Rune Bjørnerås (https://github.com/rubjo)

This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL


-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------

PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.

The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.

DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.

"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).

"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).

"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.

"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.

PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:

1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.

2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.

3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.

4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.

5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.

TERMINATION
This license becomes null and void if any of the above conditions are
not met.

DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Try

    ↑↓ selectEnter openTab filter

    Settings

    Theme
    Text
    Print

    Keyboard shortcuts

    / or Ctrl KSearch
    ↑ ↓ EnterPick a result
    TabNext result filter
    j kNext or previous entry
    [ ]Previous or next page
    yCopy a link to the current entry
    ?These shortcuts
    EscClose

    On this page