146 lines
3.9 KiB
Text
146 lines
3.9 KiB
Text
-- Lesson 26: Characters That Move Themselves. The finished script, exactly as the lesson ends.
|
|
local ROOM = 20
|
|
local WALL_HEIGHT = 2
|
|
local AGENT_RADIUS = 0.4
|
|
local AGENT_HEIGHT = 1.8
|
|
local WALK_SPEED = 2.2
|
|
|
|
sceneEnable(true)
|
|
sceneSetBackground(28, 32, 42, 255)
|
|
sceneSetAmbient(80, 86, 100)
|
|
|
|
local floorLook = materialNew()
|
|
materialSetColor(floorLook, 96, 102, 110)
|
|
materialSetRoughness(floorLook, 0.9)
|
|
|
|
local wallLook = materialNew()
|
|
materialSetColor(wallLook, 150, 128, 104)
|
|
materialSetRoughness(wallLook, 0.8)
|
|
|
|
local walkerLook = materialNew()
|
|
materialSetColor(walkerLook, 225, 85, 60)
|
|
materialSetEmissive(walkerLook, 70, 18, 10)
|
|
|
|
local wandererLook = materialNew()
|
|
materialSetColor(wandererLook, 80, 150, 225)
|
|
materialSetEmissive(wandererLook, 10, 30, 70)
|
|
|
|
local ground = nodeNew()
|
|
nodeSetMesh(ground, meshPlane(ROOM, ROOM), floorLook)
|
|
|
|
local wallMesh = meshBox(1, WALL_HEIGHT, 1)
|
|
local walls = {}
|
|
|
|
|
|
function addWall(x, z, width, depth)
|
|
local wall = nodeNew()
|
|
nodeSetMesh(wall, wallMesh, wallLook)
|
|
nodeSetScale(wall, width, 1, depth)
|
|
nodeSetPosition(wall, x, WALL_HEIGHT / 2, z)
|
|
walls[#walls + 1] = wall
|
|
end
|
|
|
|
|
|
function makeWalker(x, z, look)
|
|
local walker = nodeNew()
|
|
nodeSetPosition(walker, x, 0, z)
|
|
local body = nodeNew()
|
|
nodeSetParent(body, walker)
|
|
nodeSetMesh(body, meshBox(0.7, AGENT_HEIGHT, 0.7), look)
|
|
nodeSetPosition(body, 0, AGENT_HEIGHT / 2, 0)
|
|
local nose = nodeNew()
|
|
nodeSetParent(nose, body)
|
|
nodeSetMesh(nose, meshSphere(0.22, 16), look)
|
|
nodeSetPosition(nose, 0, 0.4, -0.45)
|
|
return walker
|
|
end
|
|
|
|
|
|
addWall(-4, 0, 12, 0.6)
|
|
addWall(7.5, 0, 5, 0.6)
|
|
addWall(-3, -6, 0.6, 8)
|
|
|
|
local nav = navNew(AGENT_RADIUS, AGENT_HEIGHT, 45, 0.3)
|
|
navAddNode(nav, ground)
|
|
for _, wall in ipairs(walls) do
|
|
navAddNode(nav, wall)
|
|
end
|
|
navBuild(nav)
|
|
|
|
local walker = makeWalker(-7, 7, walkerLook)
|
|
local walkerAgent = navAgentNew(nav, walker, AGENT_RADIUS, AGENT_HEIGHT, WALK_SPEED)
|
|
|
|
local wanderer = makeWalker(6, -6, wandererLook)
|
|
local wandererAgent = navAgentNew(nav, wanderer, AGENT_RADIUS, AGENT_HEIGHT, 1.4)
|
|
|
|
local posts = {
|
|
{ 7, 0, 7 },
|
|
{ 7, 0, -7 },
|
|
{ -7, 0, -7 },
|
|
{ -7, 0, 7 },
|
|
{ 30, 0, 30 }
|
|
}
|
|
local post = 0
|
|
local message = "Button 1 sends the red one somewhere."
|
|
|
|
local sun = lightNew(LIGHT_DIRECTIONAL)
|
|
nodeSetPosition(sun, 8, 14, 6)
|
|
nodeLookAt(sun, 0, 0, 0)
|
|
lightSetIntensity(sun, 3.5)
|
|
lightSetShadow(sun, true)
|
|
|
|
local camera = nodeNew()
|
|
nodeSetPosition(camera, 0, 17, 19)
|
|
nodeLookAt(camera, 0, 0, 0)
|
|
cameraSet(camera)
|
|
cameraSetPerspective(55, 0.1, 120)
|
|
|
|
navAgentMoveTo(wandererAgent, navRandomPoint(nav))
|
|
|
|
|
|
function onInputPressed(what)
|
|
if what ~= SWITCH_BUTTON1 then
|
|
return
|
|
end
|
|
post = post % #posts + 1
|
|
local target = posts[post]
|
|
if navAgentMoveTo(walkerAgent, target[1], target[2], target[3]) then
|
|
message = string.format("Walking to post %d.", post)
|
|
else
|
|
message = string.format("No path to post %d. Staying put.", post)
|
|
end
|
|
end
|
|
|
|
|
|
function onNavArrived(agent)
|
|
if agent == wandererAgent then
|
|
navAgentMoveTo(agent, navRandomPoint(nav))
|
|
else
|
|
message = string.format("Arrived at post %d.", post)
|
|
end
|
|
end
|
|
|
|
|
|
function onOverlayUpdate()
|
|
overlayClear()
|
|
navDraw(nav, 0, 170, 190)
|
|
|
|
local target = posts[post]
|
|
if target ~= nil then
|
|
local x, y, z = nodeGetWorldPosition(walker)
|
|
local route = navPath(nav, x, y, z, target[1], target[2], target[3])
|
|
if route ~= nil then
|
|
for i = 2, #route do
|
|
local a = route[i - 1]
|
|
local b = route[i]
|
|
lineDraw(a[1], a[2] + 0.1, a[3], b[1], b[2] + 0.1, b[3], 255, 215, 60)
|
|
end
|
|
end
|
|
end
|
|
|
|
local vx, vy, vz = navAgentGetVelocity(walkerAgent)
|
|
local speed = math.sqrt(vx * vx + vz * vz)
|
|
overlayPrint(2, 2, message)
|
|
overlayPrint(2, 4, string.format("Speed %.2f", speed))
|
|
return OVERLAY_UPDATED
|
|
end
|