PDA

View Full Version : [AS2] Dialogue in game


stingjc
07-09-2009, 04:07 PM
Alright, I've exhausted myself for a solid week trying to get something to work. But I can't. I've tried forums and tutorials, but to no avail because I'm still stuck. I know how to do everything for my VERY basic game, but this one thing and it is holding up the creation process.

I'm surprised no one has ever had this issue before. If you ask me, it seems fairly common. But either someone made this fabulous tutorial somewhere that I have yet to see or I'm just too stupid to understand how this would work.

I'm creating a very linear game which will be dialogue-heavy. In fact, there will be little action involved at all. Think a game storybook. I'm using ActionScript 2 because AS3 is just too complicate for the type of newbie that I am. But all I'm trying to do is set up dialogue between two characters in my game with an image of the speaking character to the left of the textbox. Something very much like this:

http://games.bigfishgames.com/en_tradewinds-odyssey/screen1.jpg

I considered creating arrays for the dialogue (due to some thankful tips), but my problem is that if I create an array for every time two characters exchange three lines of dialogue, I would end up with over 300 arrays. Not my cup of tea.

So, instead, I focused on this. I created a function called speak. Speak pulls two parameters: charNum and charText. CharNum is a number which specifies which frame of the charPic instance should be displayed, showing which character is currently speaking. CharText is simply the dialogue the character will speak, which will be displayed in the dynamic textbox with variable name 'dialogue'.

The following code is an example of what I have at home. I'm at work trying to get help, so I don't have the actual coding. Therefore, small errors may be present. I'm looking more at the overall functions guiding my code.

function speak(charNum:Number,charText:String = "") {

charText = dialogue;

if (charNum = 2) {
_root.charPic.gotoAndStop(2);
}

if (charNum = 3) {
_root.charPic.gotoAndStop(3);
}

if (Key.isDown(Key.SPACE)) {
dialogue = "";
_root.charPic.gotoAndStop(1);
}
}

I'm sure you guys see the problem. But if you don't, here's an example of a horrible thing happening:

speak(2,"Hello world!");
speak(3,"Hello back to you!");

You see, AS2 sees these as I believe what is called synchronous functions, meaning they run at the same time. Therefore, the second speak function overwrites the first one before the user presses the space bar to go to the next one. See the issue?

I've tried to seek help on this issue (and other before), and I keep getting told about arrays and setInterval. But my problem is that I've tried it all. I don't see a good array tutorial about this type of thing, and setInterval doesn't function like I'd want as well. Instead, it seems that from what I've read and tried, setInterval is for setting a delay up for a certain amount of time. I don't want that. I want a delay to occur until a button (namely the space bar) is pressed.

Like I said, this seems like a fairly common thing to do (stringing together dialogue in a flash movie/game), but I have seen no tutorial nor other help through all my Google and forum searching. A little push in the right direction would be appreciated. Like I said, I've figured out everything else my game needs from preloaders to game inventory to animation effects. I thought dialogue would be the easiest, but it what I'm stuck on.

Thanks in advance for any help to my problem.

(P.S. - If I ever get this problem solved, I will personally author a tutorial on the matter so that no one will be stuck on this kind of thing again without help.)

Noct
07-09-2009, 05:52 PM
Welcome aboard,

There really is no right answer here, there are so many dozens of ways to do something like this that its really a design choice. I would probably go with array of text split per character or conversation, and have those stored in arrays by scene, or however else you're going to organize this.

Sending the text around is pretty simple, you just need to setup the easiest system you can for passing that data in and out. (as OOP as possible)

This is just one way to handle it, but hopefully it will at least get you going. I'd post a file, but we're having some attachment issues at the moment.

All you need onStage to run this code is two dynamic text fields. (charText_0 & charText_1)

var sceneNum:Number = 1;
var curChar:Number = 1;
var charScope:MovieClip = this;
var char1_speechNum:Number = 0;
var char2_speechNum:Number = 0;
var char1_textField:TextField = this.charText_0;
var char2_textField:TextField = this.charText_1;
//Store conversation text in arrays (multiple if needed)
var char1_dialogArr_scene1:Array = new Array("Hello", "How are you?", "Very well.");
var char1_dialogArr_scene2:Array = new Array("xxxxx", "xxxxx", "xxxxx");
var char1_dialogArr_scene3:Array = new Array("xxxxx", "xxxxx", "xxxxx");
var char1_dialogArr:Array = new Array(char1_dialogArr_scene1, char1_dialogArr_scene2, char1_dialogArr_scene3);
//
var char2_dialogArr_scene1:Array = new Array("Hello", "I'm fine, and you?", "Sweet.");
var char2_dialogArr_scene2:Array = new Array("xxxxx", "xxxxx", "xxxxx");
var char2_dialogArr_scene3:Array = new Array("xxxxx", "xxxxx", "xxxxx");
var char2_dialogArr:Array = new Array(char2_dialogArr_scene1, char2_dialogArr_scene2, char2_dialogArr_scene3);
//Pass scene number and charname in
function speechParse(sceneNum:Number, charName:String):String {
//Grabbing characters number
var charNum:Number = parseInt(charName.charAt(charName.length-1));
//Selecting main array for chose char
var charArr:Array = charScope[charName+"_dialogArr"];
//Selecting scene array from charArr
var curArr:Array = charArr[(sceneNum-1)];
//Selecting text from speech array
var curStr:String = curArr[charScope[charName+"_speechNum"]];
//Checking if we're outta text yet
if (!curStr) {
//This is where you would change scenes/text/characters as needed
curStr = "I'm outta text.";
}
charScope[charName+"_speechNum"]++;
//Return string of text
return curStr;
}
//Listen for the spacebar press
var keyListener:Object = new Object();
keyListener.onKeyDown = function():Void {
if (Key.isDown(Key.SPACE)) {
//Change characters on press
if (curChar == 0) {
curChar = 1;
} else {
curChar = 0;
}
//get text to send
var charText:String = speechParse(sceneNum, ("char"+(curChar+1)));
//select proper textfield
var charTextField:TextField = charScope["char"+(curChar+1)+"_textField"];
//send speech to field
charTextField.text = charText;
}
};
Key.addListener(keyListener);

rrh
07-09-2009, 07:44 PM
This might reach the point where I'd make a separate editor or something that can load, edit and output an XML listing of the dialogue.

<text>
<scene sceneID="Level1" >
<speech charID="Frank">How are you?</speech>
<speech charID="George">I am fine.</speech>
<speech charID="Frank">Good to hear it.</speech>
</scene>
<scene sceneID="Level2" >
<speech charID="Frank">That level was harder than the first.</speech>
<speech charID="George">I hope that's as tough as it gets.</speech>
<speech charID="Frank">I'm sure it'll be fine.</speech>
</scene>
</text>

Noct
07-09-2009, 10:15 PM
Yeah, thats a very good point. XML would outfit you with a lot of organization options perfectly suited for something like this. Especially if you're going to have multiple characters and/or groups of dialogue...

bluemagica
07-09-2009, 11:18 PM
yep, xml would certainly make it easy on you! But from what I read, it seems you are not quite grasping the concept of arrays and such, hence I am going to stick to it!

1) You need some variables, to keep track of dialogues, scenes, e.t.c. so make some variables like

curr_dialogue = 0;
curr_scene = 1; //by scene,I mean your story pages, not a scene as in flash timeline
2) Next setup the array, and NO, you don't make 300 arrays:-

darr = [{1,"Hello"},{2,"hello to you too"},{1,"nice day"}];
the above is the shorthand format of creating a 2d array, and 1,2, e.t.c are the char pic, and next is what to say, obviously!

3) Now, let's make a function to use! The function depends entirely upon you, but I will make one which is the shortest i can think of.

//you call this function like: say_dialogue(0); where 0 is the index of the dialogue in the array
function say_dialogue(dn,da=darr)
{
_root.charPic._alpha = 100;
_root.charPic.gotoAndStop(da[dn][0]);
chartext.text = da[dn][1];
}

//You also need to consider clearing it
function clear_dialogue()
{
chartext.text="";
_root.charPic._alpha=0;
}
4) All that is left is calling it and decidewhen and where to call it.

//Sorry I forgot how to do the onClick thing, but you can get the idea
nextBtn.onClick()
{
if(curr_scene==1 && curr_dialogue<2)
{
say_dialogue(curr_dialogue);
curr_dialogue++;
}
}
The above is basically, If I am on page one, and all three dialogues haven't been shown, play them on click of a button named nextBtn!