Created
June 12, 2019 02:32
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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