Bouncing balls

The same ball dropped three times over, differing only in restitution: 0.15, 0.50 and 0.90. Every three seconds they are lifted back up.


    
main.lua
local natiny = require("natiny")

natiny.backend.init(arg and arg[1] or natiny.backend.AUTO)
natiny.physics.init()

local win = natiny.window.create("Natiny - Bouncing balls", 960, 640)
natiny.window.set_scale_mode(win, natiny.window.SCALE_MODE_STRETCH)

local BG = natiny.color.from_hex("#151E2C")

local RADIUS = 0.25
local DROP = 2.2      -- metres above the platform
local CYCLE = 3.0     -- seconds before they are lifted back up

-- The same ball three times over. Only the middle number of set_material
-- differs: how much of the speed an impact gives back.
local BALLS = {
    { x = -0.85, restitution = 0.15, color = natiny.color.from_hex("#F06B73") },
    { x =  0.00, restitution = 0.50, color = natiny.color.from_hex("#E6EDFA") },
    { x =  0.85, restitution = 0.70, color = natiny.color.from_hex("#A8C238") },
}

local camera = natiny.camera.create()
natiny.camera.set_fov(camera, 50.0)
natiny.camera.set_clip(camera, 0.1, 100.0)
natiny.entity.set_position(camera, natiny.entity.SPACE_WORLD, 0.0, 1.1, 4.2)
natiny.entity.look_at(camera, 0.0, 0.7, 0.0)

-- Teleporting a body is legitimate; it is the fall that has to be physics.
local function lift()
    for _, ball in ipairs(BALLS) do
        natiny.entity.set_position(ball.body, natiny.entity.SPACE_WORLD, ball.x, DROP, 0)
        natiny.physics.set_velocity(ball.body, 0, 0, 0)
    end
end

local time = 0

local function frame(dt)
    time = time + dt
    if time >= CYCLE then
        time = 0
        lift()
    end

    natiny.window.bind(win, function()
        natiny.render.clear(BG)
        natiny.camera.bind(camera, function()
            natiny.render.tag("model")
        end)
    end)
end

-- One mesh, used twice: drawn as a model and collided with triangle for
-- triangle, so the balls land on the platform they look to land on.
local platform_resource = natiny.resource.load("common/models/platform.glb")
local platform_mesh = natiny.mesh.load(platform_resource)
natiny.resource.destroy(platform_resource)
natiny.model.create(platform_mesh)
natiny.physics.mesh(platform_mesh)

local mesh = natiny.mesh.sphere(RADIUS, 32, 16)
for _, ball in ipairs(BALLS) do
    ball.body = natiny.physics.sphere(RADIUS)
    natiny.physics.set_material(ball.body, 0.4, ball.restitution, 400)
    natiny.physics.set_interpolation(ball.body, true)

    local model = natiny.model.create(mesh)
    natiny.model.set_color(model, ball.color)
    natiny.entity.set_parent(model, ball.body)
end
lift()

natiny.backend.loop(function(dt)
    frame(dt)
end)

natiny.backend.shutdown()