Skip to content

Instantly share code, notes, and snippets.

@1bardesign
Created June 12, 2019 02:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 1bardesign/9554def9058eddcc9bdf610f2b13de2c to your computer and use it in GitHub Desktop.
Save 1bardesign/9554def9058eddcc9bdf610f2b13de2c to your computer and use it in GitHub Desktop.
example dialogue system for love2d based on coroutines - runnable love file prepared here: https://www.dropbox.com/s/0n6vs634jzlk266/dialogue_co.love
--dialogue type
local dialogue = {}
dialogue._mt = {
__index = dialogue,
}
function dialogue:new(f)
return setmetatable({
f = f,
txt = "",
options = nil,
option_selected = nil,
}, dialogue._mt):reset()
end
function dialogue:reset()
self.co = coroutine.wrap(self.f)
self.done = false
return self
end
function dialogue:next()
--finished?
if self.done then
return
end
--collect input
local input = nil
if self.options then
input = self.option_selected
end
--actually run the coroutine
self.txt, self.options = self.co(input)
--reset selection
self.option_selected =
self.options and 1
or nil
--detect done (happens when control falls out of the dialogue routine)
if self.txt == nil then
self.co = nil
self.done = true
end
end
function dialogue:keypressed(k)
if self.options then
--option toggle
if k == "up" then
self.option_selected = self.option_selected + 1
if self.option_selected > #self.options then
self.option_selected = 1
end
elseif k == "down" then
self.option_selected = self.option_selected - 1
if self.option_selected < 1 then
self.option_selected = #self.options
end
end
end
local select_pressed =
k == "space"
or k == "return"
or k == "z"
if select_pressed then
self:next()
end
end
function dialogue:draw()
local lines = {
self.txt,
"",
}
if self.options then
for i,v in ipairs(self.options) do
local s = v[1]
if i == self.option_selected then
s = "> "..s
end
table.insert(lines, s)
end
end
for i,v in ipairs(lines) do
love.graphics.print(v, 10, i * 10)
end
end
--functions to use in dialogue
function say(str)
coroutine.yield(str)
end
function ask(str, options)
local res = coroutine.yield(str, options)
local opt = options[res]
local f
if type(opt) == "table" then
f = opt[2]
end
if type(f) ~= "function" then
error("bad response")
end
f()
end
return dialogue
local dialogue = require("dialogue")
local d
function love.load()
d = dialogue:new(function()
say("look ma, i'm talking!")
say("all sorts of separate lines")
say("written like it's totally linear declarative code")
local res = ask("isn't that great?", {
{"yes", function()
say("yeah, it's great!")
end},
{"no", function()
say("well, heck to you too then.")
end},
})
say("bye!")
end)
d:next()
end
function love.keypressed(k)
if d.co then
d:keypressed(k)
else
love.event.quit()
end
end
function love.draw()
d:draw()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment