Sustained and struck, side by side
import hive.ui
type Msg { Tick }
type Car {
seat: Int
x: Float
z: Float
speed: Float
knock: Bool
}
// A func like every other shape-maker, and worth noticing that a sound is
// exactly as much of a value as a box is: sixty of these are built a second
// and thrown away, while the voice on the other end of the name goes on
// running the whole time.
func noises(cars: Car[]): ui.Shape[dyn] {
mut ui.Shape[dyn] out = []
for each car in cars {
// Sustained: it lasts as long as the scene goes on naming it, and
// bends with the speed rather than being restarted at a new one.
append(out, ui.sound([
ui.at(car.x, 0.6, car.z),
ui.voice(ui.Voice.Engine()),
ui.pitch(0.7 + car.speed / 90.0),
ui.volume(0.6),
], "engine-{car.seat}"))
// Struck: it fires when the name arrives and is deaf to everything
// after it. Letting the name go and bringing it back is a second one.
if car.knock {
append(out, ui.sound([
ui.at(car.x, 0.6, car.z),
ui.voice(ui.Voice.Impact()),
ui.pitch(1.0),
ui.volume(0.8),
], "hit-{car.seat}"))
}
}
return out
}
func view(cars: Car[dyn]): ui.View {
solids := [ui.ground([ui.paint(ui.Tone.HEX("#3a3f45"))], 400.0, 400.0)]
return ui.scene([
ui.grow(1),
ui.eye(0.0, 1.4, 6.0),
ui.aim(0.0, 0.0),
ui.background(ui.Tone.HEX("#8ec5ff")),
], solids + noises(cars))
}
proc update(cars: Car[dyn], msg: Msg, envelope: hive.syslink.Envelope): Car[dyn] {
return cars
}
proc main(): void {
Car[dyn] grid = [Car(1, -2.0, 0.0, 40.0, false), Car(2, 2.0, -6.0, 62.0, true)]
ui.window("Sound", view, update, grid)
}