-- 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.kind == "bandit" then hits = hits + 1 elseif event.self.kind == "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