dofile("/recalbox/share/roms/daphne/singe/ActionMax/Framework.singe")
stateStartup = 0
stateSetup = 1
stateTitle = 2
stateMenu = 3
stateIntro = 4
statePlaying = 5
stateGameOver = 6
gameStandard = 0
gameLimited = 1
pixelLow = 0
pixelHigh = 1
pixelUnknown = 2
sprLightOn = spriteLoad("/recalbox/share/roms/daphne/singe/ActionMax/sprite_LightOn.png")
sprLightOff = spriteLoad("/recalbox/share/roms/daphne/singe/ActionMax/sprite_LightOff.png")
sprActionMax = spriteLoad("/recalbox/share/roms/daphne/singe/ActionMax/sprite_ActionMax.png")
sprCrosshair = spriteLoad("/recalbox/share/roms/daphne/singe/ActionMax/sprite_Crosshair.png")
sprBullet = spriteLoad("/recalbox/share/roms/daphne/singe/ActionMax/sprite_Bullet.png")
sprBoxArt = spriteLoad("/recalbox/share/roms/daphne/singe/ActionMax/sprite_" .. gameID .. ".png")
sndActionMax = soundLoad("/recalbox/share/roms/daphne/singe/ActionMax/sound_ActionMax.wav")
sndSteadyAim = soundLoad("/recalbox/share/roms/daphne/singe/ActionMax/sound_ASteadyAimIsCritical.wav")
sndGetReady = soundLoad("/recalbox/share/roms/daphne/singe/ActionMax/sound_GetReadyForAction.wav")
sndGunShot = soundLoad("/recalbox/share/roms/daphne/singe/ActionMax/sound_Gunshot.wav")
sndGoodHit = soundLoad("/recalbox/share/roms/daphne/singe/ActionMax/sound_GoodHit.wav")
sndBadHit = soundLoad("/recalbox/share/roms/daphne/singe/ActionMax/sound_BadHit.wav")
sndGameOver = soundLoad("/recalbox/share/roms/daphne/singe/ActionMax/sound_GameOver.wav")
mouseX = 0
mouseY = 0
halfWidth = 0
crosshairCenterX = spriteGetWidth(sprCrosshair) / 2
crosshairCenterY = spriteGetHeight(sprCrosshair) / 2
currentState = stateStartup
gameMode = gameStandard
shotsFired = 0 -- Total Fired
shotsGood = 0 -- Hit our target
shotsBad = 0 -- Hit our friends
scoreDisplay = 0 -- How long the score is yet to be displayed
scoreTimer = 4 -- How long to display the score + 1
lightDisplay = 0 -- How long the light is yet to be displayed
lightTimer = 2 -- How long to display the light + 1
triggerPulled = 0 -- This isn't quite a boolean. It counts down so we can get multiple pixel samples across frames.
ammoLeft = 0 -- Number of misses remaining in limited ammo mode
ammoCount = 5 -- Number of misses allowed in limited ammo mode
gunLastState = pixelUnknown
sensorLastState = pixelUnknown
thisSeconds = 0
lastSeconds = 0
heartbeat = false
fntBlueStone20 = fontLoad("/recalbox/share/roms/daphne/singe/ActionMax/font_BlueStone.ttf", 20)
fntChemRea16 = fontLoad("/recalbox/share/roms/daphne/singe/ActionMax/font_chemrea.ttf", 16)
fntChemRea32 = fontLoad("/recalbox/share/roms/daphne/singe/ActionMax/font_chemrea.ttf", 32)
fntChemRea48 = fontLoad("/recalbox/share/roms/daphne/singe/ActionMax/font_chemrea.ttf", 48)
fntLEDReal32 = fontLoad("/recalbox/share/roms/daphne/singe/ActionMax/font_LED_Real.ttf", 32)
colorBackground(0, 0, 0)
fontQuality(FONT_QUALITY_BLENDED)
colorForeground(255, 255, 0)
fontSelect(fntBlueStone20)
sprPullToStart = fontToSprite("Pull Trigger to Start!")
sprGetReady = fontToSprite("Get Ready!")
colorForeground(255, 255, 255)
fontSelect(fntChemRea16)
sprLastGame = fontToSprite("LAST GAME SCORE")
colorForeground(255, 255, 0)
fontSelect(fntChemRea32)
sprSelectGameType = fontToSprite("Select Game Type")
sprStandard1 = fontToSprite("Standard")
sprStandard2 = fontToSprite("Game")
sprLimited1 = fontToSprite("Limited")
sprLimited2 = fontToSprite("Ammo")
colorForeground(255, 0, 0)
fontSelect(fntChemRea48)
sprGameOver = fontToSprite("GAME OVER")
discSearch(backgroundFrame)
function getPixelState(intX, intY)
r1, g1, b1 = vldpGetPixel(intX, intY)
-- Determine pixel state
if ((255 - r1 < highThreshold) and (255 - g1 < highThreshold) and (255 - b1 < highThreshold)) then
pixelState = pixelHigh
elseif ((r1 < lowThreshold) and (g1 < lowThreshold) and (b1 < lowThreshold)) then
pixelState = pixelLow
else
pixelState = pixelUnknown
end
return pixelState
end
function onInputPressed(intWhat)
--dr, dg, db = vldpGetPixel(mouseX, mouseY)
--debugPrint("Current Frame: " .. discGetFrame() .. " X: " .. mouseX .. " Y: " .. mouseY .. " R: " .. dr .. " G: " .. dg .. " B: " .. db)
-- They fired!
if (intWhat == SWITCH_BUTTON3) then
if (currentState == stateTitle) then
discSearch(lengthIntro + lengthGame + 2)
discPlay()
currentState = stateMenu
elseif (currentState == stateMenu) then
if (mouseX < halfWidth) then
gameMode = gameStandard
else
ammoLeft = ammoCount
gameMode = gameLimited
end
shotsFired = 0
shotsGood = 0
shotsBad = 0
colorForeground(255, 0, 0)
fontSelect(fntLEDReal32)
discSearch(1)
discPlay()
soundPlay(sndGetReady)
currentState = stateIntro
elseif (currentState == statePlaying) then
-- Make gunshot noise
soundPlay(sndGunShot)
-- We want to sample across two frames
triggerPulled = 2
shotsFired = shotsFired + 1
-- No matter what, we subtract ammo. On good hits, we add it back to make it look like nothing changed.
if (gameMode == gameLimited) then
ammoLeft = ammoLeft - 1
end
end
end
end
--dbgPaused = 0
--dbgSpeed = 1
function onInputReleased(intWhat)
--[[ We don't use this. All this is debug stuff.
if (intWhat == SWITCH_BUTTON1) then
if (currentState == statePlaying) then
discSearch(lengthIntro + lengthGame - 60)
discPlay()
else
if (dbgPaused == 1) then
discPlay()
dbgPaused = 0
else
discPause()
dbgPaused = 1
end
end
end
if (intWhat == SWITCH_RIGHT) then
if (dbgSpeed < 4) then
dbgSpeed = dbgSpeed + 1
end
discChangeSpeed(dbgSpeed, 1)
end
if (intWhat == SWITCH_LEFT) then
if (dbgSpeed > 1) then
dbgSpeed = dbgSpeed - 1
end
discChangeSpeed(dbgSpeed, 1)
end
if (intWhat == SWITCH_UP) then
discStepBackward()
end
if (intWhat == SWITCH_DOWN) then
discStepForward()
end
--]]
end
function onMouseMoved(intX, intY, intXrel, intYrel)
-- Remember the mouse location for use later.
mouseX = intX
mouseY = intY
end
function onOverlayUpdate()
overlayClear()
currentFrame = discGetFrame()
-- Give us a 1 second heartbeat for overlay element timing
thisSeconds = os.time(os.date('*t'))
if (thisSeconds ~= lastSeconds) then
heartbeat = not heartbeat
lastSeconds = thisSeconds
-- Tick off floating score display
if (scoreDisplay > 0) then
scoreDisplay = scoreDisplay - 1
end
-- Tick off light timer
if (lightDisplay > 0) then
lightDisplay = lightDisplay - 1
end
end
if (currentState == stateStartup) then
-- We run this state to cause the overlay to update once before we use the dimensions to build the menu
overlayClear()
currentState = stateSetup
elseif (currentState == stateSetup) then
-- We do all the math to draw the menu here, one time.
halfWidth = (overlayGetWidth() / 2)
logoTop = 5
logoLeft = halfWidth - (spriteGetWidth(sprActionMax) / 2)
logoHeight = logoTop + spriteGetHeight(sprActionMax)
pullToStartHeight = spriteGetHeight(sprPullToStart)
pullToStartTop = overlayGetHeight() - pullToStartHeight
pullToStartLeft = halfWidth - (spriteGetWidth(sprPullToStart) / 2)
getReadyHeight = spriteGetHeight(sprGetReady)
getReadyTop = overlayGetHeight() - getReadyHeight
getReadyLeft = halfWidth - (spriteGetWidth(sprGetReady) / 2)
boxLeft = (halfWidth / 2) - spriteGetWidth(sprBoxArt) / 2 + halfWidth
boxTop = (overlayGetHeight() - (logoHeight + pullToStartHeight)) / 2 - spriteGetHeight(sprBoxArt) / 2 + logoHeight
lastGameLeft = (halfWidth / 2) - spriteGetWidth(sprLastGame) / 2
lastGameTop = logoHeight + logoTop
scoreHeight = 13 -- Point size + 1 instead of spriteGetHeight(sprLastGame)
scoreTop = lastGameTop + scoreHeight + 10
scoreLeft = lastGameLeft
lightLeft = overlayGetWidth() - spriteGetWidth(sprLightOff)
lightTop = overlayGetHeight() - spriteGetHeight(sprLightOff)
bulletWidth = spriteGetWidth(sprBullet)
selectGameTypeLeft = halfWidth - spriteGetWidth(sprSelectGameType) / 2
selectGameTypeTop = 25
standard1Left = halfWidth / 2 - spriteGetWidth(sprStandard1) / 2
standard2Left = halfWidth / 2 - spriteGetWidth(sprStandard2) / 2
limited1Left = halfWidth + (halfWidth / 2) - spriteGetWidth(sprLimited1) / 2
limited2Left = halfWidth + (halfWidth / 2) - spriteGetWidth(sprLimited2) / 2
standardLimited1Top = (overlayGetHeight() / 2) - spriteGetHeight(sprStandard1) + 2
standardLimited2Top = (overlayGetHeight() / 2) + 2
gameOverLeft = halfWidth - spriteGetWidth(sprGameOver) / 2
gameOverTop = (overlayGetHeight() / 2) - spriteGetHeight(sprGameOver)
colorForeground(200, 200, 200)
fontSelect(fntChemRea16)
hndActionMaxSound = soundPlay(sndActionMax)
currentState = stateTitle
elseif (currentState == stateTitle) then
spriteDraw(logoLeft, logoTop, sprActionMax)
spriteDraw(boxLeft, boxTop, sprBoxArt)
spriteDraw(lastGameLeft, lastGameTop, sprLastGame)
y = scoreTop
fontPrint(scoreLeft, y, " Shots Fired: " .. shotsFired)
y = y + scoreHeight
fontPrint(scoreLeft, y, " Good Hits: " .. shotsGood)
y = y + scoreHeight
fontPrint(scoreLeft, y, " Bad Hits: " .. shotsBad)
y = y + scoreHeight
fontPrint(scoreLeft, y, " Shot Score: " .. shotsGood - shotsBad)
y = y + scoreHeight * 2
if (shotsFired > 0) then
scorePercent = math.floor((shotsGood - shotsBad) / shotsFired * 100)
else
scorePercent = 0
end
fontPrint(scoreLeft, y, " Game Score: " .. scorePercent .. "%")
if (heartbeat) then
spriteDraw(pullToStartLeft, pullToStartTop, sprPullToStart)
end
elseif (currentState == stateMenu) then
spriteDraw(selectGameTypeLeft, selectGameTypeTop, sprSelectGameType)
spriteDraw(standard1Left, standardLimited1Top, sprStandard1)
spriteDraw(standard2Left, standardLimited2Top, sprStandard2)
spriteDraw(limited1Left, standardLimited1Top, sprLimited1)
spriteDraw(limited2Left, standardLimited2Top, sprLimited2)
if (currentFrame == lengthIntro + lengthGame + lengthMenu) then
discSearch(lengthIntro + lengthGame + 2)
discPlay()
end
elseif (currentState == stateIntro) then
if (heartbeat) then
spriteDraw(getReadyLeft, getReadyTop, sprGetReady)
end
-- Skip into game video when the intro is over.
if (currentFrame == lengthIntro) then
discSearch(lengthIntro + 1)
discPlay()
currentState = statePlaying
end
elseif (currentState == statePlaying) then
-- Read Sucton Cup Sensor.
sensorLastState = sensorState
sensorState = getPixelState(sensorX, sensorY)
-- Are they firing?
if (triggerPulled > 0) then
-- New frame (according to the sensor)?
if (sensorLastState ~= sensorState) then
-- Did they aim outside the suction cup sensor area?
if ((mouseX < sensorLeft) or (mouseY < sensorTop)) then
-- Yes. Process shot.
gunState = getPixelState(mouseX, mouseY)
else
-- No. They shot the sensor area. Bad user.
gunState = pixelUnknown
end
-- Are we doing the first or second frame sample?
if (triggerPulled == 1) then
--debugPrint("S1: " .. sensorLastState .. " S2: " .. sensorState .. " G1: " .. gunLastState .. " G2: " .. gunState)
-- Decide what happened. Do we have two good samples of each sensor?
if ((gunState ~= pixelUnknown) and (sensorState ~= pixelUnknown) and (gunLastState ~= pixelUnknown) and (sensorLastState ~= pixelUnknown)) then
-- If the sensor and gun states didn't change between frames, then this makes no sense.
if (gunLastState ~= gunState) then
-- Does the gun match the sensor?
if (gunState == sensorState) then
-- Yes! Hit bad guy!
soundPlay(sndGoodHit)
shotsGood = shotsGood + 1
lightDisplay = lightTimer
-- Add it back to make it look like nothing changed.
if (gameMode == gameLimited) then
ammoLeft = ammoLeft + 1
end
else
-- No. Crap - shot a good guy!
soundPlay(sndBadHit)
shotsBad = shotsBad + 1
end
-- Float the score for a bit
scoreDisplay = scoreTimer
end
end
else
-- Remember this info for next pass
gunLastState = gunState
end
-- Get ready for next pass
triggerPulled = triggerPulled - 1
end
end
-- When the game is over, return to the menu.
if (currentFrame == lengthIntro + lengthGame) then
discPause()
discSearch(backgroundFrame)
colorForeground(255, 255, 255)
fontSelect(fntChemRea16)
currentState = stateTitle
end
-- Do we need to show the score?
if (scoreDisplay > 0) then
fontPrint(5, 5, "SCORE: " .. (shotsGood - shotsBad))
end
-- Do we need to light the light?
if (lightDisplay > 0) then
spriteDraw(lightLeft, lightTop, sprLightOn)
else
spriteDraw(lightLeft, lightTop, sprLightOff)
end
-- Do we need to draw the ammo display?
if (gameMode == gameLimited) then
-- Are they out of ammo?
if (ammoLeft < 0) then
discSearch(lengthIntro + lengthGame + 2)
discPlay()
soundPlay(sndGameOver)
currentState = stateGameOver
end
if (ammoLeft > 0) then
bulletStart = overlayGetWidth() - bulletWidth - 5
for i=1,ammoLeft do
spriteDraw(bulletStart, 0, sprBullet)
bulletStart = bulletStart - bulletWidth
end
end
end
elseif (currentState == stateGameOver) then
spriteDraw(gameOverLeft, gameOverTop, sprGameOver)
if (currentFrame == lengthIntro + lengthGame + lengthMenu) then
discPause()
discSearch(backgroundFrame)
colorForeground(255, 255, 255)
fontSelect(fntChemRea16)
currentState = stateTitle
end
end
-- Draw gun crosshair (This must be the last thing we draw so it's on top.)
spriteDraw(mouseX - crosshairCenterX, mouseY - crosshairCenterY, sprCrosshair)
return(OVERLAY_UPDATED)
end
function onShutdown()
discStop()
end
function onSoundCompleted(intWhich)
-- Play the "A Steady Aim is Critical" sound after "ActionMax" is finished.
if (intWhich == hndActionMaxSound) then
soundPlay(sndSteadyAim)
hndActionMaxSound = SOUND_REMOVE_HANDLE
end
end