How to implement a simple dialog box

Hi there,

I am working on a (quite) simple 2D RPG. Its more like a proof of concept with different features (collision, loot-system and so on)
The last thing I want to implement is a simple quest-system.

My requirement is quite standard: If clicked on a NPC I want to display a textbox with some sort of quest descripton, lore or just a story. like in almost every game out there.

I googled a lot but I cant find anything that covers my needs in a basic way. Of course, I came across frameworks like “Empty Keys” but they seem to be too overweight for a simple task like a plain textbox.

How do you implement such things? Or can you recommend some framework that covers simple UI?

best regards
Wiago

Have you looked at the Monogame Extended project? Mabe it has some usefull stuff for you? They have a bitmap fonts demo where they display some text :slight_smile:

MonoGame Extended

Yes, checked this as well, but since the whole GUI topic is not implemented yet I didn’t take further notice of that project. But still, I’ll take a look at the bitmap fonts demo

This kind of dialogue window is a bit more difficult than it seems. I made my own controls for my game (I am not using the MG extended, this is the original 3.5.1.) and it looks like this:

What you need:

Static things:

  • A background.
  • Any fancy stuff you would like to add (like the quest giver’s avatar in the top right corner).

Dynamic things:

  • X number of texts that are displayed in each step of the dialogue.
  • Buttons for navigating in the dialogue (obviously back and continue visibility/enabled status should be based on the step number, like Back cannot be seen at the first step and Continue cannot be seen in the final step, etc…).
  • Probably a container for specific controls that are used for reacting on quests. Sometimes an Accept/Decline button pair, sometimes multiple button where more than 2 selections are available, etc… These should be a user control and all of them should be inherited from a generic base control.

Also, you need to take into account the multilinguality. In my game, you can go to the menu even when a dialogue is displayed, and when you change the language and go back to the game, the dialogue will display the selected language’s content. So once again, this is not easy.
Unfortunately my code is a bit messy as it was half-experimental and I violated many rules during development, so I cannot give you one single class that you could use as mine is using at least 6-8 different classes and my whole custom “engine”, but I can give you further advices if you would like. :slight_smile:

2 Likes

THAT! is exactly what I wanted :slight_smile:
You don’t need to share your code, I also dont have a problem to build an own little “engine” for that since it is an project to try and test all needed features.

But yet, I dont have a real idea where to start. Maybe my thinking is unnecessarily complicated.
First I was thinking about WPF, but including WPF seems to bee too much for this feature.

Maybe you can briefly explain how you have done this? is just drawing an image with text at a specific position like you do with e.g. players character (spriteBatch.Draw() and spriteBatch.DrawString() ) ?

Well, first of all my engine contains the basic controls: button, textbox, checkbox.
So, when I want a button I only need to create a variable from it and call its update and draw at the right places. The button will handle the mouseover, click and similar events and changes the image that is displayed based on its states (isvisible, isenabled, ismouseover, …), although I have an OnClick event that I can subscribe onto so this is what I am using in my dialogue to navigate. It looks like this:

CustomButton nextButton = new CustomButton(...);
nextButton.OnClick += NextClick();

private void NextClick() { ... }

My static mousehandler class takes care of pressed/released state changes, so even if you hold the left mouse button pressed for a long time over a button, the OnClick event is only called once. Even, if you hold the button pressed, but you move the cursor from/onto the same button, the event will not get called until you do not release the button. I tried to mimic the winforms functionalities. :smiley:

The same applies to my other controls as well, so the textbox handles its own statuses and update/draw logic, etc.

So, basically this dialogue will be one big class with its own Update and Draw method. Also, it should either have an Initialize or LoadContent or similar methods where you can instantiate those controls that you want to display. This dialogue should not take care of control states, “simply” iterate through the controls and call their Update/Draw in the dialogue’s Update/Draw method.

I strongly recommend to create your own TextView control, in which you can display any kind of text. In its Initialize method you should split the text into multiple texts based on your own wrapping logic. My logic is the following:

- 5px padding on all sides
- One line of text width must be the maximum available width based on the control
width and the padding. If the control is 200px wide, then it will be 200-2x5, so
190. I iterate through eash word in the text, check if the current size will be
smaller than this maximum and if it is, then I simply append the word to the actual
line of text. When I exceed the maximum value, or I have a line break in the text,
I add a new line of text to my list.
- You should create your own text scrolling, or simply design the displayed text to
be smaller than the available space.
- In your dialogue you should have a list of texts you want to display. In each step
add one of them to the TextView, call wrapping logic and in its Draw method draw
each line of text.

Maybe there is an easier way to do this, I do not know. :smiley:

Basically, when I create a new control I always create the Constructor, Initialize and/or LoadContent, Update and Draw methods, and any extra public methods that I need to call from outside of the control.
To be totally honest, I only use enum keys and not actual strings when I want to display a text. This is because my controls have a public UpdateText method that is called when I change language. This method changes the source string to a new one based on the selected language and call the wrapping logic on this new text. The new text list overwrites the previous list and in the Draw method I dispay this new list, this is why the player can change language settings during a dialogue. :slight_smile:
So, I have someting like this in my control:

private List<TranslationKey> KeysOfTheTextIWantToDisplay { get; set; } 
private List<string> DisplayedTexts { get; set; }

private MyClassConstructor(List<TranslationKey> keysOfTheTextIWantToDisplay , ...)
{
   ...
   KeysOfTheTextIWantToDisplay = keysOfTheTextIWantToDisplay;
   ...
}

public void UpdateTexts()
{
   DisplayedTexts.Clear();

   foreach(translationKey key in KeysOfTheTextIWantToDisplay)
   {
      List<string> wrappedTexts = WrapText(LanguageHelper.GetText(key));

      foreach(string s in wrappedTexts)
         DisplayedTexts.Add(s);
   }

   ...
}

private List<string> WrapText(string textToWrap)
{
   //based on the above logic wrap the text into small parts and return them
   return wrappedTexts;
}
2 Likes

Thank you for that insight. :slight_smile:
So, I’ll probably start with my own implementation instead of searching for a convenient 3rd party tool. It actually does not sound that difficult.
Maybe switching to monogame.extended at some point when the GUI part is implemented as it sounds quite promising.

thanks again

I honestly do not know Extended, but I am not even interested in it. Not because of “it”, but because I had some experience with XNA before and for me doing things like I am doing in my engine is good enough. I am confident of creating my own controls, creating my own small engine that I can use.

Good luck with your development and feel free to ask help here! :slight_smile:

At this point, I want to mention Blog I came across yesterday. It’s not really a public library yet but the author offers access via NuGet. An actually really simple to use lib for buttons, text areas and so on.
Might be usefull for whoever stumbles over this topic :slight_smile:

http://www.indie-dev.at/?p=904

1 Like

I think you can use the SpriteFont for bitmap fonts. I have my own bitmap font class that I use from legacy projects so have never used SpriteFont but I’m pretty sure apps out there that convert fonts on your computer to SpriteFont format.

The most complicated thing here is the text-wrapping / alignment logic which can be a real pain in the ass if you are implementing it yourself. I would presume SpriteFont does that for you but I’m not sure.

The other ui elements are just regular sprites so not too hard to implement - it’s just always really fiddly laying everything out!

The SpriteFont does not wrap the text, however you can use its MeasureString method to get a text length in pixel. You need to multiply this value by your scaling value (scaling should be a vector2, because you can scale the text’ width and height as well), so in the end you need to compare the substrings’ length + the spaces’ length between each word to the text area’s available size. It’s not too difficult, but not the easiest thing in development. :slight_smile: