add dialog
This commit is contained in:
parent
c92c0f6ff7
commit
5413823b26
13 changed files with 390 additions and 32 deletions
|
|
@ -0,0 +1,110 @@
|
|||
-- Dead-simple modal dialogue overlay driven by a narrator (Ink) story.
|
||||
-- No variables, no saved state: open a book, walk its paragraphs, pick a
|
||||
-- choice, then a keypress dismisses it. `narrator` is the global set up in
|
||||
-- main.lua; Dialogable entities (see npc.lua) call Dialogue.open on bump.
|
||||
Dialogue = {}
|
||||
|
||||
local story -- active narrator story, or nil when the box is closed
|
||||
local paragraphs = {} -- text lines currently shown
|
||||
local choices = {} -- current choices (empty once we reach an ending)
|
||||
local selected = 1
|
||||
|
||||
function Dialogue.isOpen()
|
||||
return story ~= nil
|
||||
end
|
||||
|
||||
-- Run the story forward to the next choice point (or the end), gathering every
|
||||
-- paragraph printed along the way.
|
||||
local function advance()
|
||||
paragraphs = {}
|
||||
while story:can_continue() do
|
||||
for _, p in ipairs(story:continue()) do
|
||||
table.insert(paragraphs, p.text)
|
||||
end
|
||||
end
|
||||
choices = story:can_choose() and story:get_choices() or {}
|
||||
selected = 1
|
||||
end
|
||||
|
||||
function Dialogue.open(book)
|
||||
if story then return end -- already talking: ignore repeat bumps
|
||||
story = narrator.init_story(book)
|
||||
story:begin()
|
||||
advance()
|
||||
end
|
||||
|
||||
function Dialogue.close()
|
||||
story, paragraphs, choices, selected = nil, {}, {}, 1
|
||||
end
|
||||
|
||||
function Dialogue.keypressed(key)
|
||||
if #choices == 0 then
|
||||
-- an ending is on screen: any key dismisses the box
|
||||
Dialogue.close()
|
||||
elseif key == "up" then
|
||||
selected = selected > 1 and selected - 1 or #choices
|
||||
elseif key == "down" then
|
||||
selected = selected < #choices and selected + 1 or 1
|
||||
elseif key == "return" or key == "space" or key == "x" then
|
||||
story:choose(selected)
|
||||
advance()
|
||||
end
|
||||
end
|
||||
|
||||
-- LCD font sized to the current play area, rebuilt only when the size changes,
|
||||
-- so dialogue text scales with the game like every sprite does.
|
||||
local dlgFont, dlgFontSize
|
||||
local function dialogueFont()
|
||||
local size = math.max(8, math.floor(height / gridHeight * 0.4))
|
||||
if not dlgFont or size ~= dlgFontSize then
|
||||
dlgFont = love.graphics.newFont("font/LCD_Solid.ttf", size)
|
||||
dlgFontSize = size
|
||||
end
|
||||
return dlgFont
|
||||
end
|
||||
|
||||
function Dialogue.draw()
|
||||
if not story then return end
|
||||
|
||||
local fnt = dialogueFont()
|
||||
local fh = fnt:getHeight()
|
||||
local pad, lineH = fh * 0.8, fh * 1.3
|
||||
local boxH = height * 0.4
|
||||
local y0 = height - boxH
|
||||
local wrap = width - pad * 2
|
||||
|
||||
-- Dialogue obeys the world's colour rule: only the channels the player has
|
||||
-- are rendered. One colour -> that colour; all three -> white (additive), so
|
||||
-- a red-only player literally reads the sign in red.
|
||||
local has = { red = false, green = false, blue = false }
|
||||
for _, c in ipairs(currentRoom.colorsPlayerHas) do has[c] = true end
|
||||
local r = has.red and 1 or 0
|
||||
local g = has.green and 1 or 0
|
||||
local b = has.blue and 1 or 0
|
||||
|
||||
local prevFont = love.graphics.getFont()
|
||||
love.graphics.setFont(fnt)
|
||||
|
||||
love.graphics.setColor(0, 0, 0, 0.82)
|
||||
love.graphics.rectangle("fill", 0, y0, width, boxH)
|
||||
|
||||
local y = y0 + pad
|
||||
love.graphics.setColor(r, g, b, 1)
|
||||
for _, text in ipairs(paragraphs) do
|
||||
love.graphics.printf(text, pad, y, wrap)
|
||||
local _, lines = fnt:getWrap(text, wrap)
|
||||
y = y + math.max(1, #lines) * lineH
|
||||
end
|
||||
|
||||
y = y + lineH * 0.5
|
||||
for i, choice in ipairs(choices) do
|
||||
local dim = (i == selected) and 1 or 0.5 -- selected is brighter + "> "
|
||||
love.graphics.setColor(r * dim, g * dim, b * dim, 1)
|
||||
local line = ((i == selected) and "> " or " ") .. choice.text
|
||||
love.graphics.printf(line, pad, y, wrap)
|
||||
local _, lines = fnt:getWrap(line, wrap)
|
||||
y = y + math.max(1, #lines) * lineH
|
||||
end
|
||||
|
||||
love.graphics.setFont(prevFont)
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue