122 lines
3.9 KiB
Text
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
|