singe/testScripts/scene72.singe
2026-09-14 14:20:17 -05:00

96 lines
3.2 KiB
Text

-- The first-person shooter from FORGE.md's catalogue: a camera on the hero's eyes turned by mouse
-- motion, a gun firing from the middle of the picture, keys moving relative to where the camera
-- looks, and enemies walking the mesh after the hero. The mouse is injected to turn toward the
-- nearest zombie's head before each shot.
dofile("Forge/AuthorCompile.singe")
local font = fontLoad("Singe/FreeSansBold.ttf", 18)
fontSelect(font)
fontQuality(FONT_QUALITY_BLENDED)
dofile(authorBuild("testScripts/author/fps.game", singeGetDataPath() .. "fps.singe"))
local gameUpdate = onOverlayUpdate
local frames = 0
local shots = 0
local hits = 0
local kills = 0
local lastShot = 0
local walked = false
local startZ = nil
local GIVE_UP = 45
local LOOK_SPEED = 0.2
local realEvent = authorEvent
function authorEvent(name, event)
if name == "hit" then hits = hits + 1 elseif name == "death" then kills = kills + 1 end
return realEvent(name, event)
end
function onOverlayUpdate()
local t = authorTime()
local hero = authorEntity("hero")
local eyes = authorEntity("eyes")
local hx, hy, hz = authorPosition(hero)
frames = frames + 1
startZ = startZ or hz
-- A step forward first, to show the keys move relative to the view.
if frames == 5 then
authorKeyDown(0, SCANCODE.W.value)
elseif frames == 40 then
authorKeyUp(0, SCANCODE.W.value)
walked = true
end
-- Turn toward the nearest zombie's head and fire.
if walked and (t - lastShot > 0.3) then
local nearest, best = nil, math.huge
for _, zombie in ipairs(authorEach("zombie")) do
if zombie.vars.state ~= "dead" then
local far = authorDistance3D(zombie, hero)
if far < best then
nearest, best = zombie, far
end
end
end
if nearest then
local head = nodeFind("b_Head_05", nearest.model)
local tx, ty, tz = nodeGetWorldPosition(head)
local ex, ey, ez = authorPosition(eyes)
local wantYaw = math.deg(math.atan(-(tx - ex), -(tz - ez)))
local wantPitch = math.deg(math.atan(ty - ey, math.sqrt((tx - ex) ^ 2 + (tz - ez) ^ 2)))
local dYaw = (eyes.yaw - wantYaw + 540) % 360 - 180
local dPitch = eyes.pitch - wantPitch
authorMouseMoved(0, 0, dYaw / LOOK_SPEED, dPitch / LOOK_SPEED)
if math.abs(dYaw) < 2 then
authorSwitchDown(SWITCH_BUTTON3)
authorSwitchUp(SWITCH_BUTTON3)
lastShot = t
end
end
end
local r = gameUpdate()
colorForeground(255, 255, 255, 255)
fontPrint(12, 450, string.format("authored first person, %.1fs, yaw %.0f, hits %d, kills %d, zombies %d", t, eyes.yaw, hits, kills, authorCount("zombie")))
if (shots == 0 and t > 1) or (shots == 1 and kills > 0) or (shots == 2 and kills >= 4) then
shots = shots + 1
singeScreenshot()
end
local hive = authorEntity("hive")
if (hive.vars.made >= 6 and authorCount("zombie") == 0 and t > 5) or (t > GIVE_UP) then
debugPrint(string.format("FPS RESULT kills=%d hits=%d health=%d bites=%d movedForward=%.1f after=%.1fs", kills, hits, AUTHOR_VARS.health, AUTHOR_VARS.bites, startZ - hz, t))
if kills < 4 then debugPrint("FPS FAIL fewer than four zombies were killed") end
if startZ - hz < 1 then debugPrint("FPS FAIL W did not move the hero forward") end
singeQuit()
end
return r
end