-- Water: a pool that floats a light crate, sinks an anchor and bobs a ball; a river with a current -- that carries a crate; the Fox wading in and swimming across; a raft with a propeller and rudder. local font = fontLoad("Singe/FreeSansBold.ttf", 28) local frames = 0 fontSelect(font) discPlay() sceneEnable(true) sceneSetBackground(0, 0, 0, 0) sceneSetAmbient(70, 70, 80) local stone = materialNew() materialSetColor(stone, 130, 130, 140) materialSetRoughness(stone, 0.9) local wood = materialNew() materialSetColor(wood, 160, 110, 60) local iron = materialNew() materialSetColor(iron, 60, 60, 70) materialSetMetallic(iron, 0.8) local water = materialNew() materialSetColor(water, 60, 120, 200) materialSetBlend(water, true) materialSetRoughness(water, 0.2) local red = materialNew() materialSetColor(red, 220, 50, 50) -- The ground, a pool cut into it (a deck round the water), and a river channel with a current. local ground = nodeNew() nodeSetMesh(ground, meshBox(30, 0.2, 30), stone) nodeSetPosition(ground, 0, -3.1, 0) bodyNew(ground, BODY_STATIC, SHAPE_BOX, 30, 0.2, 30) local deck = nodeNew() nodeSetMesh(deck, meshBox(4, 3, 12), stone) nodeSetPosition(deck, -6, -1.5, 0) bodyNew(deck, BODY_STATIC, SHAPE_BOX, 4, 3, 12) local pool = nodeNew() nodeSetMesh(pool, meshBox(8, 3, 12), water) nodeSetPosition(pool, 0, -1.5, 0) bodyNew(pool, BODY_STATIC, SHAPE_BOX, 8, 3, 12) bodySetWater(pool, 1.0, 0.6, 0.2) local river = nodeNew() nodeSetMesh(river, meshBox(6, 3, 12), water) nodeSetPosition(river, 7, -1.5, 0) bodyNew(river, BODY_STATIC, SHAPE_BOX, 6, 3, 12) bodySetWater(river, 1.0, 0.8, 0.2) bodySetCurrent(river, 0, 0, 2.5) -- Things in the water: a crate that floats, an anchor that sinks, a ball, a crate in the river. local crate = nodeNew() nodeSetMesh(crate, meshBox(0.8, 0.8, 0.8), wood) nodeSetPosition(crate, -1, 1.5, 2.5) bodyNew(crate, BODY_DYNAMIC, SHAPE_BOX, 0.8, 0.8, 0.8) bodySetMass(crate, 20) bodySetBuoyancy(crate, 1.6) local anchor = nodeNew() nodeSetMesh(anchor, meshBox(0.5, 0.5, 0.5), iron) nodeSetPosition(anchor, 1.5, 1.5, -3) bodyNew(anchor, BODY_DYNAMIC, SHAPE_BOX, 0.5, 0.5, 0.5) bodySetMass(anchor, 200) bodySetBuoyancy(anchor, 0.3) local ball = nodeNew() nodeSetMesh(ball, meshSphere(0.4, 16), red) nodeSetPosition(ball, 2, 2.5, 2) bodyNew(ball, BODY_DYNAMIC, SHAPE_SPHERE, 0.4) bodySetMass(ball, 2) bodySetBuoyancy(ball, 2.0) local drift = nodeNew() nodeSetMesh(drift, meshBox(0.7, 0.7, 0.7), wood) nodeSetPosition(drift, 7, 0.5, -5) bodyNew(drift, BODY_DYNAMIC, SHAPE_BOX, 0.7, 0.7, 0.7) bodySetMass(drift, 10) bodySetBuoyancy(drift, 1.5) -- The raft: a flat hull with the propeller at the stern. local raft = nodeNew() nodeSetMesh(raft, meshBox(1.6, 0.3, 2.4), wood) nodeSetPosition(raft, 1, 0.3, 4) bodyNew(raft, BODY_DYNAMIC, SHAPE_BOX, 1.6, 0.3, 2.4) bodySetMass(raft, 120) bodySetBuoyancy(raft, 3.0) vehicleNew(raft, VEHICLE_BOAT) vehicleSetThrust(raft, 600, 0, -0.1, 1.2) vehicleSetRudder(raft, 300) -- The Fox wades in from the deck and swims across. local hero = nodeNew() nodeSetPosition(hero, -5, 0.05, -2) playerNew(hero, 0.3, 1.0) local fox = modelInstance(modelLoad("testScripts/Models/Fox.glb")) nodeSetParent(fox, hero) nodeSetScale(fox, 0.01) nodeSetRotation(fox, 0, 90, 0) animationPlay(fox, "Walk", true) local sun = lightNew(LIGHT_DIRECTIONAL) nodeSetPosition(sun, -5, 10, 6) nodeLookAt(sun, 0, 0, 0) lightSetIntensity(sun, 1.5) lightSetShadow(sun, true) local camera = nodeNew() nodeSetPosition(camera, 1, 6, 12) nodeLookAt(camera, 1, -0.5, 0) cameraSet(camera) function onTrigger(trigger, other, entered) if other == hero then debugPrint(string.format("frame %d fox %s %s", frames, entered and "entered" or "left", (trigger == pool) and "the pool" or ((trigger == river) and "the river" or "a trigger"))) end end function onOverlayUpdate() local hx, hy, hz = nodeGetPosition(hero) frames = frames + 1 if playerIsSwimming(hero) then playerMove(hero, 1.5, 0.6, 0) else playerMove(hero, 1.5, 0) end vehicleDrive(raft, 0.7, (frames > 30) and 0.9 or 0, 0) overlayClear() fontPrint(20, 20, string.format("Water, frame %d fox %s at %.1f %.2f raft %.1f m/s", frames, playerIsSwimming(hero) and "swimming" or "walking", hx, hy, vehicleGetSpeed(raft))) if frames % 30 == 0 then local cx, cy = nodeGetPosition(crate) local ax, ay = nodeGetPosition(anchor) local bx, by = nodeGetPosition(ball) local dx, dy, dz = nodeGetPosition(drift) local rx, ry, rz = nodeGetPosition(raft) debugPrint(string.format("frame %d fox %.1f %.2f %s | crate y %.2f anchor y %.2f ball y %.2f | drift z %.1f | raft %.1f %.2f %.1f speed %.1f", frames, hx, hy, tostring(playerIsSwimming(hero)), cy, ay, by, dz, rx, ry, rz, vehicleGetSpeed(raft))) end if frames == 50 or frames == 110 or frames == 170 then singeScreenshot() end if frames == 180 then singeQuit() end end