views:

147

answers:

1

Hello,

I am writing a Javascript dialog script which is seen in a lot of typical Role Playing Games.alt text

At the moment I got an array with text strings which you can skip trough. I got at the point where you can make a decision and based on the input a different string will show.

However I don't think this is the right way to do it. These are the requirements for the script:

  • Support for multiple dialog scripts
  • multiple characters
  • user decision input ("Do you like me?" -yes -no)

This is my code at the moment:

// Intro script
var script_intro = [];
script_intro[0] = 'Hello how are you?';
script_intro[1] = 'So I heard..';
script_intro[2] = 'This is a cool game!';

script_intro[3] = [];
script_intro[3][0] = 'Do you like me?';
script_intro[3][1] = [];
script_intro[3][1][0] = 'Jah';
script_intro[3][1][1] = 4;
script_intro[3][2] = [];
script_intro[3][2][0] = 'Nah';
script_intro[3][2][1] = 5;

// Intro script: variation I
var script_intro_1 = [];
script_intro_1[0] = 'I love you too!';

// Intro script: variation II
var script_intro_2 = [];
script_intro_2[0] = 'Damn you...';

function initDialog()
{
    // This is where the text will be shown
    var dialog = document.getElementById('dialog');
    var content = document.getElementById('content');

    var nextButton = document.getElementById('nextButton');
    var optionButton_1 = document.getElementById('optionButton_1');
    var optionButton_2 = document.getElementById('optionButton_2');

    // How fast the characters will appear after each other (milliseconds)
    var scrollSpeed = 50;
}

// Scroll text per line, character
function scrollText(script, line)
{
    var char = 0;

    // If this line contains a question that requires user input
    if(typeof(script[line]) == 'object')
    {
     var textScroller = setInterval(
      function()
      {
       // Add the string char for char
       content.innerHTML += script[line][0][char];
       char ++;

       if(char >= script[line][0].length)
       {
        clearInterval(textScroller);

        // Show options
        options(script, line);
       }
      }, scrollSpeed);
    }
    else
    {
     var textScroller = setInterval(
      function()
      {
       content.innerHTML += script[line][char];
       char++;

       if(char >= script[line].length)
       {
        clearInterval(textScroller);

        // Show next line
        next(script, line);
       };
      }, scrollSpeed);
    }
}

function next(script, line)
{
    line = line + 1;

    // Last line has been shown
    if(script[line] == undefined)
    {
     //alert('End of dialog');
    }
    else
    {
     nextButton.style.visibility = 'visible';

     nextButton.onclick = function()
     {
      nextButton.style.visibility = 'hidden';
      content.innerHTML = '';

      scrollText(script, line);
     }
    }
}

function options(script, line)
{
    optionButton_1.innerHTML = script[line][1][0];
    optionButton_2.innerHTML = script[line][2][0];
    optionButton_1.style.visibility = 'visible';
    optionButton_2.style.visibility = 'visible';

    optionButton_1.onclick = function()
    {
     optionButton_1.style.visibility = 'hidden';
     optionButton_2.style.visibility = 'hidden';
     content.innerHTML = '';

     scrollText('script_intro_1', 0);
    }

    optionButton_2.onclick = function()
    {
     optionButton_1.style.visibility = 'hidden';
     optionButton_2.style.visibility = 'hidden';
     content.innerHTML = '';

     scrollText('script_intro_2', 0);
    }
}

html

<body onload="scrollText(script_intro, 0)">
    <h1>rpg</h1>
    <a id="reset" href="#">Reset</a>
    <div id="device">
     <div id="dialog">
      <strong>NPC:</strong>
      <div id="content"></div>
      <a id="nextButton" href="#">Next</a>
      <a id="optionButton_1" href="#"></a>
      <a id="optionButton_2" href="#"></a>
     </div>
    </div>
</body>

I could really use some feedback. What is the best way to write such script with the requirements above? Is using JSON or XML a better option than an Array for the dialog scripts? I especially need some hints on how to implement multiple choices in the script.

Thank you!

+1  A: 

If this is a script that has a scripted flow to it, I would use the state machine pattern.

http://www.eventhelix.com/RealtimeMantra/HierarchicalStateMachine.htm

There are tons of links, I just grabbed the first I searched from google. What I would do is have a state for each situation the user will presented with options. Each option would be a transition to another state. So for instance

function State(questionText){
    this.transitionsOut = [];
    this.questionText = questionText;
}
State.prototype = {
    transitionsOut:null,
    questionText:null,
}

function Transition(startState, endState, optionText){
    startState.transitionsOut[startState.transitionsOut.length] = this;
    this.start = startState;
    this.end = endState;
}

Transition.prototype = {
    start:null,
    end:null,
    optionText:null
}

Then what you can do, is make your state machine, and then for the current state, print out your State Message, then underneath list each option for that state.

var startState = new State('Where do you want to go');
var north = new State('North');
var south = new State('South');
var transition1 = new Transition(startState,north,'Lets go north');
var transition2 = new Transition(startState,south,'Lets go south');

The code to then display what is in the current state, and the options is trivial, as is the transition from one state to another based on what the user picks.

Zoidberg
Good choice. However, you have an error: `start` is undefined. I believe you meant `startState.transitionsOut.push(this);`
Justin Johnson
Yes, lemme fix it, thanks.
Zoidberg
Thanks for the tip. I found a nice article on IBM: ibm.com/developerworks/web/…. Looks all new and complicated but I'll study :) Thanks for the example, also. More tips are welcome.
richard