singe/testScripts/scene10.singe

122 lines
3.9 KiB
Text

-- Physics stage 3: a trigger volume in the crates' path, collision callbacks, and a raycast
-- through the middle of the overlay that flicks whatever it hits.
local font = fontLoad("Singe/FreeSansBold.ttf", 28)
local frames = 0
local entered, left, collisions, lastSpeed, picks = 0, 0, 0, 0, 0
fontSelect(font)
discPlay()
sceneEnable(true)
sceneSetBackground(18, 18, 30, 255)
sceneSetAmbient(70, 70, 85)
local floorLook = materialNew()
materialSetColor(floorLook, 120, 110, 100)
materialSetRoughness(floorLook, 0.9)
local crateLook = materialNew()
materialSetColor(crateLook, 200, 140, 60)
local ballLook = materialNew()
materialSetColor(ballLook, 60, 140, 230)
local paddleLook = materialNew()
materialSetColor(paddleLook, 230, 60, 40)
local zoneLook = materialNew()
materialSetColor(zoneLook, 80, 255, 120, 70)
materialSetBlend(zoneLook, true)
materialSetUnlit(zoneLook, true)
local markLook = materialNew()
materialSetColor(markLook, 255, 255, 80)
materialSetEmissive(markLook, 120, 120, 0)
local floor = nodeNew()
nodeSetMesh(floor, meshBox(14, 0.2, 14), floorLook)
nodeSetPosition(floor, 0, -1.9, 0)
bodyNew(floor, BODY_STATIC, SHAPE_BOX, 14, 0.2, 14)
local crates = {}
for i = 1, 4 do
local crate = nodeNew()
nodeSetMesh(crate, meshBox(0.6, 0.6, 0.6), crateLook)
nodeSetPosition(crate, -1.0, -1.5 + (i - 1) * 0.62, 0)
bodyNew(crate, BODY_DYNAMIC, SHAPE_BOX, 0.6, 0.6, 0.6)
crates[i] = crate
end
local ball = nodeNew()
nodeSetMesh(ball, meshSphere(0.35, 32), ballLook)
nodeSetPosition(ball, 0.2, 1.5, 0.3)
bodyNew(ball, BODY_DYNAMIC, SHAPE_SPHERE, 0.35)
bodySetBounce(ball, 0.5)
-- The trigger: a translucent green volume to the right of the stack.
local zone = nodeNew()
nodeSetMesh(zone, meshBox(1.6, 1.6, 2.4), zoneLook)
nodeSetPosition(zone, 1.8, -1.0, 0)
bodyNew(zone, BODY_STATIC, SHAPE_BOX, 1.6, 1.6, 2.4)
bodySetTrigger(zone, true)
local paddle = nodeNew()
nodeSetMesh(paddle, meshBox(0.3, 1.2, 1.6), paddleLook)
nodeSetPosition(paddle, -4.0, -1.2, 0)
bodyNew(paddle, BODY_KINEMATIC, SHAPE_BOX, 0.3, 1.2, 1.6)
-- A marker placed where the pick ray hits.
local mark = nodeNew()
nodeSetMesh(mark, meshSphere(0.08, 12), markLook)
nodeSetVisible(mark, false)
local sun = lightNew(LIGHT_DIRECTIONAL)
nodeSetPosition(sun, -3, 6, 4)
nodeLookAt(sun, 0, 0, 0)
lightSetIntensity(sun, 1.2)
lightSetShadow(sun, true)
local camera = nodeNew()
nodeSetPosition(camera, 1.0, 1.6, 6.5)
nodeLookAt(camera, 0.2, -0.6, 0)
cameraSet(camera)
function onCollision(a, b, x, y, z, speed)
collisions = collisions + 1
lastSpeed = speed
end
function onTrigger(trigger, other, isEntering)
if isEntering then
entered = entered + 1
else
left = left + 1
end
debugPrint(string.format("trigger %d %s node %d", trigger, isEntering and "entered by" or "left by", other))
end
function onOverlayUpdate()
frames = frames + 1
overlayClear()
fontPrint(20, 20, string.format("Physics %d hits %d (%.1f) in %d out %d picks %d", frames, collisions, lastSpeed, entered, left, picks))
if frames >= 60 and frames < 150 then
nodeMove(paddle, 0.06, 0, 0)
end
if frames % 30 == 0 and frames <= 240 then
-- A ray from the camera through the overlay's centre; flick whatever it hits upward.
local w, h = sceneGetSize()
local ox, oy, oz = sceneUnproject(w / 2, h / 2, 0)
local fx, fy, fz = sceneUnproject(w / 2, h / 2, 10)
local hit, hx, hy, hz = physicsRaycast(ox, oy, oz, fx - ox, fy - oy, fz - oz)
if hit then
picks = picks + 1
nodeSetVisible(mark, true)
nodeSetPosition(mark, hx, hy, hz)
if hit ~= floor and hit ~= zone and hit ~= paddle then
bodyApplyImpulse(hit, 0, 3, 0, hx, hy, hz)
end
debugPrint(string.format("pick node %d at %.2f %.2f %.2f", hit, hx, hy, hz))
end
end
if frames == 50 or frames == 130 or frames == 220 then
singeScreenshot()
end
if frames == 250 then
debugPrint(string.format("RESULT collisions=%d entered=%d left=%d picks=%d", collisions, entered, left, picks))
singeQuit()
end
end