singe/testScripts/scene59.singe
2026-09-14 22:32:53 -05:00

93 lines
3.4 KiB
Text

-- Forge milestone 1, genre two: a light gun over video. Hitboxes keyed to disc frames and
-- interpolated between them, a gun that raises hit and miss, ammo that runs out, a reload by a
-- shot off the picture, a prompt at a frame, and a penalty for the hostage. The pointer is
-- injected through authorSetPointer, the door a test uses instead of a mouse.
dofile("Forge/AuthorCompile.singe")
local font = fontLoad("Singe/FreeSansBold.ttf", 18)
fontSelect(font)
fontQuality(FONT_QUALITY_BLENDED)
dofile(authorBuild("testScripts/author/gunvideo.game", singeGetDataPath() .. "gunvideo.singe"))
local gameUpdate = onOverlayUpdate
local frames = 0
local shots = 0
local stage = 0
local hits = 0
local misses = 0
local hostage = 0
local realEvent = authorEvent
function authorEvent(name, event)
if name == "hit" then
if event.self.type == "bandit" then hits = hits + 1 elseif event.self.type == "hostage" then hostage = hostage + 1 end
elseif name == "miss" then
misses = misses + 1
end
return realEvent(name, event)
end
local function shoot(x, y, on)
authorSetPointer(1, x, y, on)
authorSwitchDown(SWITCH_BUTTON3)
authorSwitchUp(SWITCH_BUTTON3)
end
function onOverlayUpdate()
local disc = discGetFrame()
local box = authorTrackBox("bandit")
frames = frames + 1
-- Each shot waits for the disc to reach a frame, so the sequence is the same at any speed.
if (stage == 0) and (disc >= 130) and box then
-- Frame 130 of 120..220: the bandit box has moved a tenth of the way from x=100 to x=400.
debugPrint(string.format("GUN at frame %d the bandit box is at x=%.0f (interpolated from 100 toward 400)", disc, box.x))
shoot(box.x + 10, box.y + 10, true) -- hit
stage = 1
elseif (stage == 1) and (disc >= 150) then
shoot(20, 20, true) -- miss on the picture
shoot(box.x + 10, box.y + 10, true) -- hit (the bandit is dead; no target, so a miss)
stage = 2
elseif (stage == 2) and (disc >= 170) then
-- Out of ammo now (3 shots taken): a shot on the picture does nothing, off it reloads.
local ammo = authorEntity("gun1").vars.ammo
shoot(580, 260, true) -- hostage, but the gun is empty
debugPrint("GUN ammo before reload " .. ammo .. ", hostage hits so far " .. hostage)
shoot(-10, -10, false) -- reload
debugPrint("GUN ammo after reload " .. authorEntity("gun1").vars.ammo)
shoot(580, 260, true) -- hostage
stage = 3
elseif (stage == 3) and (disc >= 320) then
stage = 4
end
local r = gameUpdate()
colorForeground(255, 255, 255, 255)
fontPrint(12, 450, "authored gun game, disc frame " .. disc)
if box then
colorForeground(255, 80, 80, 255)
overlayBox(box.x, box.y, box.x + box.w, box.y + box.h)
end
if (shots == 0 and disc >= 125) or (shots == 1 and disc >= 160) or (shots == 2 and disc >= 200) then
shots = shots + 1
singeScreenshot()
end
if stage == 4 or frames > 1500 then
debugPrint(string.format("GUN RESULT score=%d hits=%d misses=%d hostage=%d ammo=%d", AUTHOR_VARS.score, hits, misses, hostage, authorEntity("gun1").vars.ammo))
if hits ~= 1 or hostage ~= 1 or misses ~= 2 then
debugPrint("GUN FAIL expected 1 hit, 2 misses, 1 hostage")
end
if authorTrackBoxAt({ boxes = { { at = 0, x = 0, y = 0, w = 10, h = 10 }, { at = 10, x = 100, y = 0, w = 10, h = 10 } } }, 5).x ~= 50 then
debugPrint("GUN FAIL interpolation")
end
singeQuit()
end
return r
end