mirror of
https://github.com/DramaticShape/DramaticShapeVoxelMod.git
synced 2026-08-12 06:50:51 +02:00
108 lines
3.8 KiB
Lua
108 lines
3.8 KiB
Lua
-- HORDE MODE: the card at the end.
|
|
--
|
|
-- A stack state, unlike the mode itself -- and for the opposite reason.
|
|
-- Horde mode cannot be a pushed state because pushing one stops the
|
|
-- overworld ticking and the player could not walk; the GAME OVER card
|
|
-- WANTS exactly that. Pushed, it freezes the world underneath, takes the
|
|
-- buttons, and stands there until A.
|
|
--
|
|
-- It draws in the engine's own 160x144 UI canvas with the game's own
|
|
-- font, which is what makes it work in VR for free: with a headset live
|
|
-- and something other than the overworld on top of the stack, lib/VR
|
|
-- already puts the flat screen on the floating panel (or on the Pokedex
|
|
-- in the player's left hand). A card drawn the way the game draws cards
|
|
-- arrives there with no VR code at all.
|
|
--
|
|
-- A pops it and hands over to Horde.finish, which is what puts the world
|
|
-- back: the map, the cell, the facing, the camera rung, the hour, the
|
|
-- music, and every NPC the horde had turned into a mob.
|
|
|
|
-- the mod namespace (see main.lua): V.require loads a sibling module
|
|
local V = ...
|
|
|
|
local Horde = V.require("Horde")
|
|
|
|
local W, H = 160, 144
|
|
|
|
local HordeGameOver = {}
|
|
HordeGameOver.__index = HordeGameOver
|
|
|
|
function HordeGameOver.new(game)
|
|
local self = setmetatable({}, HordeGameOver)
|
|
self.game = game
|
|
self.isOpaque = true
|
|
self.t = 0
|
|
-- the session is read ONCE, here: Horde.finish clears it, and this card
|
|
-- outlives that by a frame or two while the warp home fades
|
|
local s = Horde.session or {}
|
|
self.score = math.floor(s.score or 0)
|
|
self.best = math.floor(s.best or 0)
|
|
self.wave = math.max(1, s.wave or 1)
|
|
self.kills = s.kills or 0
|
|
self.done = false
|
|
return self
|
|
end
|
|
|
|
function HordeGameOver:update(dt)
|
|
self.t = self.t + (dt or 0)
|
|
if self.done then return end
|
|
-- a beat of dead air before the prompt takes input, so the button that
|
|
-- was being mashed at the moment of death does not dismiss the card
|
|
if self.t < 0.6 then return end
|
|
local input = self.game and self.game.input
|
|
if input and input:wasPressed("a") then
|
|
self.done = true
|
|
pcall(function()
|
|
require("src.core.Sound").play(self.game.data, "Press_AB")
|
|
end)
|
|
self.game.stack:pop()
|
|
pcall(Horde.finish, self.game)
|
|
end
|
|
end
|
|
|
|
-- THE CARD IS DRAWN THE WAY THE GAME DRAWS CARDS: a bordered white box
|
|
-- with black text in it (Font.drawBox then setColor(0,0,0)), exactly as
|
|
-- HallOfFame and every menu do. That is not decoration -- the UI canvas
|
|
-- is a FOUR-SHADE Game Boy screen, and an arbitrary colour drawn into it
|
|
-- has nowhere to land. A first cut of this card painted a dark red on
|
|
-- near-black and composited as a rectangle of pure black, with the score
|
|
-- in it and invisible.
|
|
local function centred(Font, str, y, scale)
|
|
scale = scale or 1
|
|
local w = Font.width(str) * scale
|
|
love.graphics.push()
|
|
love.graphics.translate(math.floor((W - w) / 2), y)
|
|
love.graphics.scale(scale, scale)
|
|
Font.draw(str, 0, 0)
|
|
love.graphics.pop()
|
|
end
|
|
|
|
function HordeGameOver:draw()
|
|
local ok, Font = pcall(require, "src.render.Font")
|
|
if not ok then return end
|
|
|
|
-- the whole screen as one box: isOpaque keeps the stack from drawing
|
|
-- the world under it, but the canvas still holds whatever was there
|
|
Font.drawBox(0, 0, 20, 18)
|
|
|
|
love.graphics.setColor(0, 0, 0, 1)
|
|
centred(Font, "GAME OVER", 3 * 8, 2)
|
|
|
|
centred(Font, ("SCORE %d"):format(self.score), 8 * 8)
|
|
centred(Font, ("WAVE %d"):format(self.wave), 10 * 8)
|
|
centred(Font, ("KILLS %d"):format(self.kills), 11 * 8)
|
|
|
|
if self.best > 0 then
|
|
centred(Font, (self.score >= self.best) and "NEW BEST!"
|
|
or ("BEST %d"):format(self.best), 13 * 8)
|
|
end
|
|
|
|
-- the prompt blinks the way every "press a button" in this game blinks
|
|
if self.t > 0.6 and (self.t % 1.0) < 0.62 then
|
|
centred(Font, "PRESS A", 15 * 8)
|
|
end
|
|
love.graphics.setColor(1, 1, 1, 1)
|
|
end
|
|
|
|
return HordeGameOver
|