Sound¶
KKE's sounds are mostly synthesized from impacts: a body with a sound material hits something, and the engine makes the right thump, clink or crack, louder for a harder hit, placed in 3D where it happened, muffled behind walls. A script's job is to say what things are made of.
Sound materials¶
One crate of every material, dropped in a row: listen to the difference. O drops them again, P plays a metal ping in front of you.

-- sounds.lua: one crate of every sound material, dropped in a row. Each
-- hit plays the material's impact sound, louder the faster it hits; the
-- Contact hook prints who hit what. O drops them again.
-- (docs/cookbook/audio.md)
if not audio then
print("sounds.lua: this game has no AudioModule")
return
end
local names = {}
for name, id in pairs(audio.materials()) do table.insert(names, { name = name, id = id }) end
table.sort(names, function(a, b) return a.id < b.id end) -- a stable order
local crates, nameOf = {}, {}
local function drop()
for _, id in ipairs(crates) do physics.remove(id) end
crates, nameOf = {}, {}
for i, m in ipairs(names) do
local id = physics.box { pos = Vec(-4 + i * 1.1, 2 + i * 0.4, 1), size = Vec(0.5, 0.5, 0.5), material = m.id,
color = Vec(0.3 + (i % 3) * 0.25, 0.5, 0.9 - (i % 4) * 0.15) }
table.insert(crates, id)
nameOf[id] = m.name
end
end
-- The engine plays the sounds by itself; this only reports them.
hook.Add("Contact", "sounds.report", function(c)
local who = nameOf[c.a] or nameOf[c.b]
if who and c.speed > 1 then print(string.format("%s hit at %.1f m/s", who, c.speed)) end
end)
-- Your own sound, anywhere: audio.impact(position, material, loudness 0..1).
input.define("sounds.again", "Drop the crates again", "O")
input.define("sounds.ping", "Play a metal ping", "P")
hook.Add("Think", "sounds.keys", function()
if input.pressed("sounds.again") then drop() end
if input.pressed("sounds.ping") then audio.impact(camera.position() + camera.forward() * 2, "Metal", 0.8) end
end)
drop()
audio.materials()is a table of name to id (Stone,Wood,Metal,Glass, ...). Pass the id asmaterialwhen you make a body, and its hits make sound by themselves.audio.impact(position, material, loudness)plays one on demand, for things that aren't collisions: a footstep, a pickup, a bell.- The
Contacthook is how a script hears about hits too:c.speedis how hard,c.materialAandc.materialBwhat.
Where the sound comes from¶
Everything is positioned in 3D relative to the camera, so the crates on
the left sound on the left. Sounds behind walls are quieter and duller
(occlusion, by raycast), and a room's size changes its reverb. Nothing to
set up: it's how AudioModule works. The settings players can change
(volume, the sound visualizer for deaf and hard-of-hearing players,
mono) are in the settings screen every starter game has.
Audio covers the synthesis, spatialization, occlusion and the optional Steam Audio backend; Tutorial 4 adds materials and a pickup chime to the tutorial game.
Next: multiplayer.