Dialogue Text Box Library (DTB)
DTB is a code snippet that you can use to implement a dialogue text box to any game in just seconds.
Setting it up goes as follows:
- Add the dtb code to the top of your own code.
- Call dtb_init in your initialization.
- Call dtb_update in your update.
- Call dtb_draw function in your draw.
And that all there is! You can now simply call "dtb_disp" wherever you want.
Usage
dtb_init(numlines) |
Call this to initialize all dtb's variables. Takes an optional parameter which defines the maximum number of lines that will be displayed. Defaults to 3.
dtb_update() |
Call this every update. All logic is contained within dtb.
dtb_draw() |
Call this every time the screen gets drawn. Preferably at the end so the textbox always appears at the top.
dtb_disp(txt, callback) |
Call this to display txt in a textbox. The text is added to a queu so this function can be called multiple times after each other without interfering with the previous text.
Takes an optional callback parameter (function) which is called when this particular piece of text is done displaying.
The actual snippet
Here is the minimized snippet. 1370 characters and 447 tokens:
-- dialogue text box library by oli414. minimized. function dtb_init(n) dtb_q={}dtb_f={}dtb_n=3 if n then dtb_n=n end _dtb_c() end function dtb_disp(t,c)local s,l,w,h,u s={}l=""w=""h=""u=function()if #w+#l>29 then add(s,l)l=""end l=l..w w=""end for i=1,#t do h=sub(t,i,i)w=w..h if h==" "then u()elseif #w>28 then w=w.."-"u()end end u()if l~=""then add(s,l)end add(dtb_q,s)if c==nil then c=0 end add(dtb_f,c)end function _dtb_c()dtb_d={}for i=1,dtb_n do add(dtb_d,"")end dtb_c=0 dtb_l=0 end function _dtb_l()dtb_c+=1 for i=1,#dtb_d-1 do dtb_d[i]=dtb_d[i+1]end dtb_d[#dtb_d]=""sfx(2)end function dtb_update()if #dtb_q>0 then if dtb_c==0 then dtb_c=1 end local z,x,q,c z=#dtb_d x=dtb_q[1]q=#dtb_d[z]c=q>=#x[dtb_c]if c and dtb_c>=#x then if btnp(4) then if dtb_f[1]~=0 then dtb_f[1]()end del(dtb_f,dtb_f[1])del(dtb_q,dtb_q[1])_dtb_c()sfx(2)return end elseif dtb_c>0 then dtb_l-=1 if not c then if dtb_l<=0 then local v,h v=q+1 h=sub(x[dtb_c],v,v)dtb_l=1 if h~=" " then sfx(0)end if h=="." then dtb_l=6 end dtb_d[z]=dtb_d[z]..h end if btnp(4) then dtb_d[z]=x[dtb_c]end else if btnp(4) then _dtb_l()end end end end end function dtb_draw()if #dtb_q>0 then local z,o z=#dtb_d o=0 if dtb_c<z then o=z-dtb_c end rectfill(2,125-z*8,125,125,0)if dtb_c>0 and #dtb_d[#dtb_d]==#dtb_q[1][dtb_c] then print("\x8e",118,120,1)end for i=1,z do print(dtb_d[i],4,i*8+119-(z+o)*8,7)end end end |
A readable/editable version can be found in this demo's code.
Feel free to use and customize this code in your own projects! I'd love to see it being used!
Very nice! I might try using this is in my next adventure game.
Excellent, great job! Any plans to implement scrolling via up/down on dialogs that end up longer than 3 lines?
@Scathe that's a neat idea! I'm struggling a little with adding more features tho. It rapidly increases the number of tokens even though some people might not need/require all of the features.
@Oli414 I'll be using this in one of my carts. Thank you so much!
Is there a way to implement this on my #tinytvjam to display directions?
@JetJaguar not really, you only have 10x11 pixels to work with in the useable draw routine for the jam; anything bigger than that is basically drawn over by the uneditable code.
This looks really solid. I've been dreading tacking dialogue in my current project with my dwindling token budget. Totally going to use this :)
@HotSoup Awesome! Looking forward to it!
@JetJaguar Like 2Tie said, there's just too little space to make it work I think.
@jade Thanks! Feel free
@Oli414 This is amazing! I've also added in a thing when it changes the text sound effect depending on what you set the variable 'mood' to.
Goodness this is sexy! I'll definitely be using this in my game. I was dreading refactoring my own text box library but it looks like I can cut that todo item now!
Bless! I was working on my own dialogue system, but it proved complicated. This is a real neat template! :D
Hey, I might be doing something wrong, but when I use the callback in dtb_disp(), the callback function gets called immediately, instead of for the text to be finished. Any idea?
EDIT: I fixed it. having the full function under callback does work
dtb_disp(text[level], --start fade function() fading=true end)
I'm actually working on something like this, but it operates at 4-different messaging levels. Will let you know more when I do myself. :)
Nice library; only 7 functions!
I've been working on my own and it's nice to see how someone else solves the problem. What made you choose to store the current character? I'm considering using a single string as input that then gets broken into lines ahead of time, then they get fed to the animation part. I like your use of a queue, it makes a lot of sense since the best dialog in games is dynamic and DTBs need a general interface.
Do you have any plans to expand this to include basic widgets that show up in dialog, like Yes/No and multiple choice? Highlighted words? I'm hoping to get something like that going for mine.
Thanks for sharing!
Hi! thank you! I've been using this for my personal little fish adventure game.
I can't seem to get it to display text when i move to another map screen tho :( i'm changing some coordinates in dtb_disp() is that not enough ?
EDIT: i fiddled with Camera() and it is doing the right thing, (128,0) at one screen over, but the dialogue is still not printing on the second screen. is the draw functions not being affected my camera() somehow ?
This is really neat! However does anyone know how to use it in between interactions? Like for example
scene 1: A and B were talking (showing with this dtb module)
scene 2: allow player to investigate the environment
scene 3: A and B talking again (showing with this dtb module)
as far as I understand the content of dtb_disp() was decided inside _init(), but scene 2 requires interactions inside _update. How to add the conversation in scene 3 after that? Sorry if my question sounds silly, thank you in advanced!
Been a while since I made this, I'm currently revisiting the project for which I made this and I made a much more efficient version if you don't need any fancy features:
function dtb_init() dtb_q={} dtb_p=1 dtb_qt=nil end function dtb_update() if #dtb_q~=0 then dtb_p+=1 if dtb_p>#dtb_qt then dtb_p=#dtb_qt if btnp(🅾️) then del(dtb_q,dtb_qt) dtb_qt=dtb_q[1] dtb_p=1 end elseif btnp(🅾️) then dtb_p=#dtb_qt end end end function dtb_draw() if dtb_qt~=nil then rectfill(2,105,125,125,1) print(sub(dtb_qt,1,dtb_p),4,107,7) if dtb_p==#dtb_qt then print("🅾️",117,119,13) end end end function dtb_disp(str) add(dtb_q,str) if (#dtb_q==1) dtb_qt=dtb_q[1] end |
This version has no callback, no sounds and no no configurable line length.
You can split your text across multiple lines using a line break /n
It's a bit more basic but uses lot less tokens!
If you wish to modify this:
dtb_q is the queue of texts to display. Each string in this table is shown as a separate box, and displayed in the ordered it's in.
dtb_qt is the current queue text, usually dtb_q[1] or nil.
dtb_p is the text pointer, ranging from 1 to #dtb_qt.
This is exactly what I was looking for and I had no clue where to start tackling it. Thank you so much, beautiful work :)
Beautiful!! I was just opening a new file to play around with displaying dialogue and wow here it is all solved already 😊
I hacked in some rudimentary support for speaker/title on the text box. You can now identify who or what is sending the message. It also supports not having a title or speaker defined and will display that like it used to.
I've attached a cartridge for reference (the forum software kept removing lines from my codeblocks??). Press the left arrow to initiate the text box, press Z (⭕) to advance.
I'm also keen to allow for the ability to change textbox position (just top or bottom, maybe center too) for each message, but that'll wait for another day.
[Please log in to post a comment]