159 lines
3.4 KiB
Text
159 lines
3.4 KiB
Text
-- Learn to Program with Singe -- Lesson 18: Quick-Time Events
|
|
|
|
dofile("Singe/Framework.singe")
|
|
|
|
overlaySetResolution(discGetWidth(), discGetHeight())
|
|
|
|
local FIRST_FRAME = 20
|
|
local WRONG_FRAME = 362
|
|
local LATE_FRAME = 388
|
|
local LAST_FRAME = 415
|
|
|
|
local PROMPT_COL = 54
|
|
local PROMPT_ROW = 22
|
|
local GAUGE_X = 210
|
|
local GAUGE_Y = 330
|
|
local GAUGE_W = 300
|
|
local GAUGE_H = 18
|
|
|
|
local RIGHT_SCORE = 100
|
|
|
|
local moves = {
|
|
{ first = 60, last = 105, switch = SWITCH_LEFT, name = "LEFT" },
|
|
{ first = 140, last = 185, switch = SWITCH_UP, name = "UP" },
|
|
{ first = 220, last = 265, switch = SWITCH_RIGHT, name = "RIGHT" },
|
|
{ first = 300, last = 345, switch = SWITCH_DOWN, name = "DOWN" },
|
|
}
|
|
|
|
local score = 0
|
|
local runOver = false
|
|
local verdict = ""
|
|
|
|
|
|
local function fillBar(x, y, width, height)
|
|
if width < 1 then
|
|
return
|
|
end
|
|
for row = 0, height - 1 do
|
|
overlayLine(x, y + row, x + width - 1, y + row)
|
|
end
|
|
end
|
|
|
|
|
|
local function isDirection(what)
|
|
return what == SWITCH_UP or what == SWITCH_DOWN or what == SWITCH_LEFT or what == SWITCH_RIGHT
|
|
end
|
|
|
|
|
|
local function moveAt(frame)
|
|
for _, move in ipairs(moves) do
|
|
if move.answer == nil and frame >= move.first and frame <= move.last then
|
|
return move
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
|
|
local function startRun()
|
|
score = 0
|
|
runOver = false
|
|
verdict = ""
|
|
for _, move in ipairs(moves) do
|
|
move.answer = nil
|
|
end
|
|
discSkipToFrame(FIRST_FRAME)
|
|
end
|
|
|
|
|
|
local function endRun(reason, frame)
|
|
verdict = reason
|
|
runOver = true
|
|
discSkipToFrame(frame)
|
|
end
|
|
|
|
|
|
function onInputPressed(what)
|
|
if runOver then
|
|
if what == SWITCH_START1 then
|
|
startRun()
|
|
end
|
|
return
|
|
end
|
|
|
|
if not isDirection(what) then
|
|
return
|
|
end
|
|
|
|
local move = moveAt(discGetFrame())
|
|
if move == nil then
|
|
return
|
|
end
|
|
|
|
if what == move.switch then
|
|
move.answer = "right"
|
|
score = score + RIGHT_SCORE
|
|
else
|
|
move.answer = "wrong"
|
|
endRun("WRONG WAY", WRONG_FRAME)
|
|
end
|
|
end
|
|
|
|
|
|
function onOverlayUpdate()
|
|
local frame = discGetFrame()
|
|
|
|
if not runOver then
|
|
for _, move in ipairs(moves) do
|
|
if move.answer == nil and frame > move.last then
|
|
move.answer = "late"
|
|
endRun("TOO SLOW", LATE_FRAME)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
if frame >= LAST_FRAME and discGetState() == DISC_PLAYING then
|
|
if not runOver then
|
|
verdict = "CLEAR"
|
|
runOver = true
|
|
end
|
|
discSearch(LAST_FRAME)
|
|
end
|
|
|
|
overlayClear()
|
|
|
|
local move = nil
|
|
if not runOver then
|
|
move = moveAt(frame)
|
|
end
|
|
|
|
if move ~= nil then
|
|
local left = move.last - frame
|
|
local span = move.last - move.first
|
|
|
|
overlayPrint(PROMPT_COL, PROMPT_ROW, "PRESS " .. move.name)
|
|
|
|
colorForeground(255, 255, 255, 255)
|
|
overlayBox(GAUGE_X - 2, GAUGE_Y - 2, GAUGE_X + GAUGE_W + 1, GAUGE_Y + GAUGE_H + 1)
|
|
|
|
if left * 3 < span then
|
|
colorForeground(255, 60, 60, 255)
|
|
else
|
|
colorForeground(255, 200, 0, 255)
|
|
end
|
|
fillBar(GAUGE_X, GAUGE_Y, GAUGE_W * left // span, GAUGE_H)
|
|
end
|
|
|
|
overlayPrint(2, 1, "SCORE " .. score .. " FRAME " .. frame)
|
|
|
|
if runOver then
|
|
overlayPrint(2, 3, verdict)
|
|
overlayPrint(2, 4, "PRESS 1 TO RUN IT AGAIN")
|
|
end
|
|
|
|
return OVERLAY_UPDATED
|
|
end
|
|
|
|
|
|
startRun()
|