Sign in to follow this  

Design for a Dialogue System in a RPG

This topic is 1446 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I need feedback on my design for the dialogue feature I am working on. If you have any recommendations on your design or how I can structure the code better, I will gladly listen to them. Working on a role playing game has been tough but the codebase grows so much in a week! I would think I would be used to this after finished working on small prototypes of simple games.

 

This feature right now is for one Soldier NPC that is a talking quest givers for my role playing pc game in Java. Future npcs will inherit the below instance variables from a class called NPC. 

public class Soldier extends Sprite implements Collidable,Talkable
{
// This is an enum of 4 possible states: attacking, healing, running and idle
private ActionState state;
private SoldierIdleAnimation soldierIdleAnimation;

// for bounding box collision to trigger the talk button indicator
private Rectangle rectangle;
// This is the question mark image on the top of its head when a quest is not done

private QuestNotFinishedImage questNotFinishedImage;
// This is the exclaimation point mark to indicate you have satisfied the requirements for the quest.
private QuestFinishedImage questFinishedImage;
// This is an enum with 2 possible states: Finished and NotFinished
private QuestState questState;
// This is an indicator that pops up when you are near the soldier which means you are near enough to talk to it
private NPCTalkImage npcTalkImage;
// This gets turned on when the main character is near the soldier to trigger the talk button indicator
private boolean canTalk;
// This is the dialogue bar for the npc. Each npc will get their own dialogue bar.
private NPCDialogueBox npcDialogueBox;
// This gets turned on when the main character presses the T button
private boolean isTPressed;
// This is also an enum with 2 possible states: isRunning or IsNotRunning
private Dialogue dialogue;
 
}
 

 


The second question I have is: does this code look overkill for a colliding with talking npcs algorithm for my main character class

for(int i = 0; i < charactersToAdd.size();i++)
{
          Talkable character = (Talkable) charactersToAdd.get(i);
         /* make sure the rectangle is not from the main character
         *  because you do not want to collide with yourself
         */
         if(character != this)
         {
                 // get rectangle from the characters in the list besides main character
                 Rectangle rectangle = character.getRectangle();
 
                 // if main characters bounding box collides with the npc bounding box
                 if(getRectangle().intersects(rectangle) )
                 {
 
                 // make the talk button indicator appear
                 character.setTalk(true, isTPressed);
                 }
                 else 
                 {
                  // make the talk button indicator disappear 
                 character.setTalk(false,isTPressed);
                 }
                 }
          }
}

The third question is how much should I plan when making an RPG? So far development has been okay. Every feature had its failure before finally getting it to work properly. I was able to get by so far with what I have done with a rough outline of the working implemented feature in my head. 

 

This is the first time I am working on an RPG. Working on this type of game made me remember how much code is required to get something simple to work.

Edited by warnexus

Share this post


Link to post
Share on other sites

Working on this type of game made me remember how much code is required to get something simple to work.

 

 

Or maybe our definition of what "simple" means, is incorrect. What gamers call simple is mostly out of pure ignorance. Us programmers know better smile.png

 

I would second composition on this one. Just be aware of what objects you need and who owns them. If you are just going to expose one of the objects inside another then does it really need to exist inside that object or should it be outside and you just pass it as a parameter to some Update() function. The thing about composition is that it can break encapsulation if you just expose the hosted objects themselves.

 

http://en.wikipedia.org/wiki/Composition_over_inheritance at the bottom it talks about "drawbacks" to composition

 

 


One drawback to using composition in place of inheritance is that all of the methods being provided by the composed classes must be implemented in the derived class, even if they are only forwarding methods. In contrast, inheritance does not require all of a base class's methods to be re-implemented within the derived class. Rather, the derived class need only implement (override) the methods having different behavior than the base class methods. This can require significantly less programming effort if the base class contains many methods providing default behavior and only a few of them need to be overridden within the derived class. This drawback can be avoided by using traits.

 

 

The reason for this drawback is because you still want to support encapsulation. By simply exposing the internal object so you can have access to all it's functions you are breaking encapsulation and exposing potential issues down the line. This is why I say make sure the "parent" object really needs to store the child object or can it just be passed to one of the parent object functions and you create and handle it outside of the parent object.

 

 

If you must store it, then generally avoid calling new yourself in the parent ctor. Don't let the parent control the lifetime but let the user outside as it's more flexible.

Edited by rpiller

Share this post


Link to post
Share on other sites

In fact, I am glad I got a big post like this. It definitely thought provoking to me! =] To answer your questions:

 

charactersToAdd is an ArrayList where my characters are stored in the Game class. I also have a separate Arraylist for mainMenuButtons for example ("NEW GAME", "Continue Game"). Game loops draws all the elements for either one of the Arraylist depending on what "state" my game is in. If the game is in the MAIN MENU state, it draws from the Arraylist that contains mainMenuButtons. If the game is in the OVERWORLD state, it draws from the Arraylist that contains the characters(the main character and the soldier).

 

I do not understand what do you mean by broad phase collision detection prefixed.

 

Do you have confusion about my talking collision algorithm? 

 

Dialogue mode activation requires a bounding box collision because it is the only approach I can think of and test for the main character being close enough to talk to the npc.

 

Ah! A Talk instance! I never thought of that. A Dialogue instance? That is interesting. I will see if I can change it to that. Right now my Dialogue is just an enum with two states: ISRUNNING and ISNOTRUNNING.

 

What do you mean by data driven mechanism?

 

In terms of planning, I do also have all the required features all written on paper. The challenge every day was how to implement a feature even given my past experience with game programming and how to better structure the code. 

 

I will try the composition approach and see what difference it makes. Time to refactor the dialogue feature.

Edited by warnexus

Share this post


Link to post
Share on other sites


I do not understand what do you mean by broad phase collision detection prefixed.

Broad phase collision detection means that in a first phase collision is checked not exactly but fast, and false hits are tolerated. There are several approaches to that, dependent on the circumstances and the type of game. For example in 3D, broad phase collision check may be done using spheres as collision volumes, and only if a collision is detected with them the better fitting (but more costly) collision volumes are used. In both 3D and 2D one can think of axis aligned boxes before rotated boxes are used. Another popular approach is to subdivide the amount of potential colliders, e.g. by using spatial regions.

 


Do you have confusion about my talking collision algorithm?

No; its just about the name "charactersToAdd".

 


Dialogue mode activation requires a bounding box collision because it is the only approach I can think of and test for the main character being close enough to talk to the npc.

I have nothing to contradict. I just say that collision can be checked without the background of conversation, i.e. the collision detection sub-system itself need not (and should not) know about conversation at all.

 


Ah! A Talk instance! I never thought of that. A Dialogue instance? That is interesting. I will see if I can change it to that. Right now my Dialogue is just an enum with two states: ISRUNNING and ISNOTRUNNING.

What I meant by those 2 classes is this: An instance of Dialogue is a game asset like a texture or mesh. It holds what can be said by whom and under what conditions, and what effects take place (i.e. item exchange). An instance of Talk, on the other hand, is a runtime thing. Its existence shows that one or more characters are currently talking (i.e. they do gossip or they process a Dialogue) or have talked about something. It stores who participates, where inside a Dialogue the talk currently is, and similar things.

 


What do you mean by data driven mechanism?

It means that processing is controlled by the data coming with the game entities, not with the code belonging to classes (uh, well, thereabout). For example, let Item be a game entity that can be utilized by a character. Let us say there is an Item that is defined to be a pillow (the graphical representation shows this). However, the level designer has given the pillow a damage value of 10. So the pillow has become a weapon. Your code is not prepared to know that a pillow can be used as weapon, but this is okay because your code knows that a damage value gather than 0 means that the item can be used as weapon.

 

Another example is Dialogue. When a Talk is in progress by processing a Dialogue, the processor looks into the Dialogue and finds a value that means "the opposite says the subsequently stored sentence and wait for an answer", or "the opposite gives …" followed by the item kind "gold coins" followed by the amount "10".

Share this post


Link to post
Share on other sites
This is what my DialogueSystem looks like. I wanted to know should each NPC have a dialogue system of their own. I'm not sure how to "when to actually create." Should I create it in the NPC class and just have the dialogue system created when the user presses the button to initiate conversation with the NPC? It sounds trivial but I need feedback from experts.
 
Should the system wipes itself clean if the user stops talking to the npc? Or does the system hangs around in the game loop all the time updating itself to see if the user presses the button for talking to npcs? 
 
public class DialogueSystem {
 
private TextDialogue dialogue;
private DialogueBox box;
private static DialogueState state;
private DrawTextGraphicsSystem textSystem;
private NPC npc;
private DialogueMark mark;
 
}
Edited by warnexus

Share this post


Link to post
Share on other sites

I think each npc should have that information that is specific to that entity (the text, color, image, what have you), probably stored (or referenced, or what have you) in a HasDialogue component of some sort. I assume you have some manner of interacting with npcs (press a button or collide with), so why not have an OnInteract method that sends the specifics of the dialogue to the DialogueSystem, which handles all of the displaying and whatnot for you.

 

Something along the lines of:

OnInteract()
{
     DialogueSystem.Process(this.DialogueInfo);
}

Process(DialogueInfo dialogue)
{
     DisplayDialogueWindow();
     WriteDialogueText(dialogue.Text);
}

Share this post


Link to post
Share on other sites

 

I think each npc should have that information that is specific to that entity (the text, color, image, what have you), probably stored (or referenced, or what have you) in a HasDialogue component of some sort. I assume you have some manner of interacting with npcs (press a button or collide with), so why not have an OnInteract method that sends the specifics of the dialogue to the DialogueSystem, which handles all of the displaying and whatnot for you.

 

Something along the lines of:

OnInteract()
{
     DialogueSystem.Process(this.DialogueInfo);
}

Process(DialogueInfo dialogue)
{
     DisplayDialogueWindow();
     WriteDialogueText(dialogue.Text);
}

That works too. I actually got something similar to the above you speak of. The npc interaction is actually a combination of colliding and a button press. valid collision prompts the button to show up. pressing it triggers the conversation. 

 

Awesome response!

Share this post


Link to post
Share on other sites

This topic is 1446 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this