RPG Style Dialog with Colored Words

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Melvin

I am trying to setup a dialog system where some words and hints are colored to emphasize them, like so:

An example of what I'm trying to accomplish

I’ve noticed that Godot has BBCode for the RichTextLabel node, but I’ve not figured out how to integrate it with the system I’ve set up. For the purpose of this question, I’ll provide the most basic code of what I’m working with:

extends RichTextLabel




var NPC_TEST = []
func SET_NPC_TEST():
	NPC_TEST.push_back("<NPC NAME>")
	NPC_TEST.push_back("Hello! I am a NPC, and this is the color RED.")
	pass



var TIMER = Timer.new()
var WAIT_TIME = 0.05




var LINE = 0
var LINE_ARRAY = []




func _ready():
	TIMER_START()
	READY_NPC()
	START_DIALOG()
	pass




func READY_NPC():
	SET_NPC_TEST()
	pass




func TIMER_START():
	TIMER.connect("timeout", self, "TIMER_TIMEOUT_FUNCTION")
	TIMER.set_wait_time(WAIT_TIME)
	add_child(TIMER)
	TIMER.start()
	pass




func TIMER_TIMEOUT_FUNCTION():
	if LINE_ARRAY.size() > 0:
		self.add_text(LINE_ARRAY.pop_front())
		pass
	pass




func START_DIALOG():
	if LINE < NPC_TEST.size():
		LINE += 1
		LINE_ARRAY = []
		for i in NPC_TEST[LINE]:
			LINE_ARRAY.append(i)
			pass
		pass
	pass

Note: I know “pass” does not do anything, it is just a habit of mine.

Anyway I hope my setup isn’t too complicated, but lets take a gander at this line:

NPC_TEST.push_back("Hello! I am a NPC, and this is the color RED.")

I would like the word “RED” to be… well, red.

I know this doesn’t work:

NPC_TEST.push_back("Hello! I am a NPC, and this is the color [color=red]RED[/color].")

Any tips and tricks to get around this would be greatly appreciated!

:bust_in_silhouette: Reply From: flurick

Using bbcode_text instead of text seems to work, there are some open github isses but this could probably be a new one about clearing up the naming a bit.

Thank you for even taking the time, but I should probably mention that my situation doesn’t use RichTextLabel.text or RichTextLabel.set_text(). I am using add_text() as it appears to be the only thing I can use to simulate the typing effect I’m after. I have used RichTextLabel.bbcode_text but it behaves in much the same way as text and set_text(). Allow me to briefly explain what the code is doing:

It basically takes the string from the array NPC_TEST:

NPC_TEST = ["Hello! I am a NPC, and this is the color RED."]

Passes it to another array LINE_ARRAY, chopping it up so that it looks like this:

LINE_ARRAY = ["H", "e", "l", "l", "o", "!", " ", "I", " ", "a", "m", " ", "a", " ", "N", "P", "C", ",", "a", "n", "d", " ", "t", "h", "i", "s", " ", "i", "s", " ", "t", "h", "e", " ", "c", "o", "l", "o", "r", " ", "R", "E", "D", "."]

Then, using a Timer, prints the letters from LINE_ARRAY, one-by-one, on the RichTextLabel using add_text(). Simulating the aforementioned typing effect:

RichTextLabel.add_text(LINE_ARRAY.pop_front())

Perhaps what I’m doing here makes bbcoding impossible, but hopefully now you can see the dilemma I’m in.

Melvin | 2019-09-03 16:31

:bust_in_silhouette: Reply From: Melvin

So I have figured it out…
Using the woes from someone else’s post (here), I now know the existence of set_visible_characters.

I don’t quite understand it fully, but here is the working code:

extends RichTextLabel




var NPC_TEST = []
func SET_NPC_TEST():
	NPC_TEST.push_back("<NPC NAME>")
	NPC_TEST.push_back("Hello! I am a NPC, and this is the color [color=red]RED[/color].")
	pass



var TIMER = Timer.new()
var WAIT_TIME = 0.05




var LINE = 0
var LINE_ARRAY = []




func _ready():
	TIMER_START()
	READY_NPC()
	START_DIALOG()
	self.bbcode_enabled = true
	pass




func READY_NPC():
	SET_NPC_TEST()
	pass




func TIMER_START():
	TIMER.connect("timeout", self, "TIMER_TIMEOUT_FUNCTION")
	TIMER.set_wait_time(WAIT_TIME)
	add_child(TIMER)
	TIMER.start()
	pass




func TIMER_TIMEOUT_FUNCTION():
	if LINE_ARRAY.size() > 0:
		#self.add_text(LINE_ARRAY.pop_front())
		self.bbcode_text = NPC_TEST[1]
		self.set_visible_characters(get_visible_characters()+1)
		pass
	pass




func START_DIALOG():
	if LINE < NPC_TEST.size():
		LINE += 1
		LINE_ARRAY = []
		for i in NPC_TEST[LINE]:
			LINE_ARRAY.append(i)
			pass
		pass
	pass