121 lines
4.2 KiB
Text
121 lines
4.2 KiB
Text
-- Character controller: the Fox as a player walking a course of stairs, ramps, a wall, a crate to
|
|
-- shove and a moving platform, driven by a scripted route so it runs headless; the camera follows.
|
|
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, 120, 120, 130)
|
|
materialSetRoughness(stone, 0.9)
|
|
local wood = materialNew()
|
|
materialSetColor(wood, 150, 100, 50)
|
|
local steel = materialNew()
|
|
materialSetColor(steel, 90, 110, 150)
|
|
materialSetMetallic(steel, 0.6)
|
|
|
|
local function block(x, y, z, w, h, d, material)
|
|
local node = nodeNew()
|
|
nodeSetMesh(node, meshBox(w, h, d), material)
|
|
nodeSetPosition(node, x, y, z)
|
|
bodyNew(node, BODY_STATIC, SHAPE_BOX, w, h, d)
|
|
return node
|
|
end
|
|
|
|
-- The course runs along +X. Floor, three stairs, a gentle ramp, a steep ramp, a wall to slide along.
|
|
block(8, -0.1, 0, 30, 0.2, 8, stone)
|
|
block(2.0, 0.075, 0, 0.6, 0.15, 4, wood)
|
|
block(2.6, 0.15, 0, 0.6, 0.30, 4, wood)
|
|
block(3.2, 0.225, 0, 0.6, 0.45, 4, wood)
|
|
local ramp = nodeNew()
|
|
nodeSetMesh(ramp, meshBox(3, 0.2, 4), stone)
|
|
nodeSetPosition(ramp, 6.2, 0.7, 0)
|
|
nodeSetRotation(ramp, 0, 0, 25)
|
|
bodyNew(ramp, BODY_STATIC, SHAPE_BOX, 3, 0.2, 4)
|
|
block(9.0, 0.7, 0, 2.6, 2.6, 4, stone) -- The top landing behind the ramp
|
|
local steep = nodeNew()
|
|
nodeSetMesh(steep, meshBox(2, 0.2, 4), stone)
|
|
nodeSetPosition(steep, 11.0, 2.85, 0)
|
|
nodeSetRotation(steep, 0, 0, 60)
|
|
bodyNew(steep, BODY_STATIC, SHAPE_BOX, 2, 0.2, 4)
|
|
block(9.0, 2.4, -2.5, 4, 1.2, 0.2, steel) -- A wall along the landing's far edge
|
|
|
|
-- A crate to shove and a platform that slides back and forth.
|
|
local crate = nodeNew()
|
|
nodeSetMesh(crate, meshBox(0.6, 0.6, 0.6), wood)
|
|
nodeSetPosition(crate, 4.6, 0.3, 0.15)
|
|
bodyNew(crate, BODY_DYNAMIC, SHAPE_BOX, 0.6, 0.6, 0.6)
|
|
bodySetMass(crate, 5)
|
|
local platform = nodeNew()
|
|
nodeSetMesh(platform, meshBox(1.5, 0.2, 1.5), steel)
|
|
nodeSetPosition(platform, 8.5, 2.1, 1.5)
|
|
bodyNew(platform, BODY_KINEMATIC, SHAPE_BOX, 1.5, 0.2, 1.5)
|
|
|
|
-- The player: a capsule with the Fox model hanging off the node, facing +X.
|
|
local player = nodeNew()
|
|
nodeSetPosition(player, 0, 0.05, 0)
|
|
playerNew(player, 0.3, 1.0)
|
|
playerSetStep(player, 0.35)
|
|
local foxModel = modelLoad("testScripts/Models/Fox.glb")
|
|
local fox = modelInstance(foxModel)
|
|
nodeSetParent(fox, player)
|
|
nodeSetScale(fox, 0.01)
|
|
nodeSetRotation(fox, 0, 90, 0)
|
|
animationPlay(fox, "Walk", true)
|
|
|
|
local sun = lightNew(LIGHT_DIRECTIONAL)
|
|
nodeSetPosition(sun, -3, 8, 5)
|
|
nodeLookAt(sun, 6, 0, 0)
|
|
lightSetIntensity(sun, 1.5)
|
|
lightSetShadow(sun, true)
|
|
|
|
local camera = nodeNew()
|
|
cameraSet(camera)
|
|
|
|
local jumped = false
|
|
local landings = 0
|
|
|
|
function onCollision(a, b, x, y, z, speed)
|
|
if a == player or b == player then
|
|
landings = landings + 1
|
|
end
|
|
end
|
|
|
|
function onOverlayUpdate()
|
|
local px, py, pz = nodeGetPosition(player)
|
|
local t = frames / 60
|
|
frames = frames + 1
|
|
-- Route: walk east up the stairs and the ramp, veer to the wall, then onto the platform.
|
|
local vz = 0
|
|
if px > 7.5 and px < 10 then
|
|
vz = (t < 6) and -1.2 or 1.2
|
|
end
|
|
playerMove(player, 3.0, vz)
|
|
if px > 5.5 and not jumped and playerIsOnGround(player) then
|
|
jumped = playerJump(player, 4.5)
|
|
end
|
|
nodeSetRotation(player, 0, math.deg(math.atan(vz, 3.0)) * -1, 0)
|
|
-- The platform slides in Z.
|
|
nodeSetPosition(platform, 8.5, 2.1, 1.5 + math.sin(t * 1.5) * 1.5)
|
|
-- Camera behind and above the player.
|
|
nodeSetPosition(camera, px - 4.5, py + 2.6, pz + 4.5)
|
|
nodeLookAt(camera, px + 1, py + 0.6, pz)
|
|
overlayClear()
|
|
fontPrint(20, 20, string.format("Player, frame %d x %.1f y %.2f ground %s landings %d", frames, px, py, tostring(playerIsOnGround(player)), landings))
|
|
if frames % 30 == 0 then
|
|
local fx, fy, fz = nodeGetWorldPosition(fox)
|
|
local vx, vy, vz = playerGetVelocity(player)
|
|
local cx, cy, cz = nodeGetPosition(crate)
|
|
debugPrint(string.format("frame %d player %.2f %.2f %.2f v %.2f %.2f %.2f ground %s jumped %s crate %.2f %.2f landings %d", frames, px, py, pz, vx, vy, vz, tostring(playerIsOnGround(player)), tostring(jumped), cx, cz, landings))
|
|
end
|
|
if frames == 40 or frames == 80 or frames == 120 or frames == 160 then
|
|
singeScreenshot()
|
|
end
|
|
if frames == 180 then
|
|
singeQuit()
|
|
end
|
|
end
|