Skip to content

Instantly share code, notes, and snippets.

@1bardesign
Created October 5, 2018 07:03
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 1bardesign/696e2a9d9f7be015fc9def142c722367 to your computer and use it in GitHub Desktop.
Save 1bardesign/696e2a9d9f7be015fc9def142c722367 to your computer and use it in GitHub Desktop.
a simple line by line "typewriter" text demo for love2d
--[[
typewriter class
]]
local typewriter = {}
--(metatable used for instances, don't worry about it too much
-- but do read up on metatables at some point)
typewriter._mt = {__index = typewriter}
--create a new typewriter
--character_time should be the time between characters, in seconds
--erase_on_newline determines if this is a single-line typewriter or not
--lines should be the lines to use as content, and slowly type out
function typewriter:new(character_time, line_time, erase_on_newline, lines)
return setmetatable({
--the lines we have to draw
lines = lines,
--the time
time = {
nothing = math.huge, --(this "infinite" wait is triggered when we're out of data)
newline = line_time, --(wait between lines)
character = character_time, --(wait between characters)
},
--a counting-up, usually-negative timer
timer = -character_time,
last_added = "nothing",
erase_on_newline = erase_on_newline,
--where we gather all the text into
text = "",
}, typewriter._mt)
end
--add a line to the typewriter
--returns self for chaining
function typewriter:add(line)
table.insert(self.lines, line)
self.timer = 0
return self
end
--add the next character to be rendered
--returns what was added, as indicated by a string
-- either "nothing", "character" or "newline"
function typewriter:next()
--there's honestly more efficient ways to do this
-- ... but it's not going to matter, and i think this should be clear
--do we have any incoming content at all?
if #self.lines == 0 then
return "nothing"
end
--remove the first character from the next line
--(read up on string.sub)
local added_type = "character"
local next_char = ""
local next_line = self.lines[1]
--(check if we have consumed the line)
if next_line ~= "" then
--we have not - proceed as normal
next_char = next_line:sub(1, 1)
self.lines[1] = next_line:sub(2)
else
--we have!
--remove the line, as we're done with it
table.remove(self.lines, 1)
--and append a newline as the character
added_type = "newline"
next_char = "\n"
end
if self.last_added == "newline" and self.erase_on_newline then
--clear out if the previous addition was end of line
self.text = next_char
else
self.text = self.text .. next_char
end
--(feel free to add a sound here if you like, something was added)
return added_type
end
--update the typewriter
--(you can pass your fixed 1/30 dt here if you like)
function typewriter:update(dt)
self.timer = self.timer + dt
while self.timer > 0 do
self.last_added = self:next()
local time_wait = self.time[self.last_added]
assert(time_wait, "could not find matching wait time")
self.timer = self.timer - time_wait
end
end
function typewriter:draw(x, y, width, mode)
--todo: you could do a fade out here between lines if you wanted :)
love.graphics.printf(
self.text,
x, y,
width, mode
)
end
--[[
demo code
]]
local tw;
function love.load()
tw = typewriter:new(0.05, 2.0, true, {
'Long ago, two races ruled over Earth: HUMANS and MONSTERS. ',
'One day, war broke out between the two races. ',
'After a long battle, the humans were victorious. ',
'They sealed the monsters underground with a magic spell. ',
'Many years later... ',
'MT. Ebott 201X',
'Legends say that those who climb the mountain never return.',
})
end
function love.update(dt)
tw:update(dt)
end
function love.draw()
tw:draw(10, 10, 500, "left")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment