Japanese-style dialog closeups [SOLVED]

Started by Snarky, Tue 12/04/2011 09:19:56

Previous topic - Next topic

Snarky

I'm trying to create a dialog system similar to this:



Characters stand around on the screen as usual, and when you click on them you get this closeup that is used for conversations.

I've found that the Sierra-style speech doesn't give enough control to enable this. I can't set the position of the text box, and I'm having trouble positioning the closeup even horizontally (and certainly not vertically):

Code: ags

  SetSpeechStyle(eSpeechSierraWithBackground);
  SetSkipSpeech(3);
  game.text_align = eAlignLeft;
  SetGameOption(OPT_PORTRAITPOSITION, 3); // 3=xpos, but how do I set the actual xpos?


Using character.SayAt I can move around the closeup+text box together, but not each individually. This old thread indicates it's not possible to fully achieve the desired effect.

I tried to write a custom function to take care of it.:

Code: ags

int jSay(this Character*, const string message)
{
  // Backup state
  int oldX = this.x;
  int oldY = this.y;
  int oldZ = this.z;
  int oldView = this.View;

  // Position closeup
  this.FaceLocation(oldX, oldY+1, eNoBlock); // Face front
  this.x = GetViewportX()+CLOSEUP_X;
  this.y = GetViewportY()+System.ViewportHeight;
  this.z = System.ViewportHeight-CLOSEUP_Y;
  this.ChangeView(this.SpeechView);

  // Display the message
  DisplayAt(49, 179, 220, message);

  // Restore backed-up state after dialog is over
  this.x = oldX;
  this.y = oldY;
  this.z = oldZ;
  this.ChangeView(oldView);
}


This works, but not for dialogs, which is a pain.

I also checked out SSH's GuiPortrait module, but it doesn't seem to do what I want it to (namely position the text box).

Is there another solution?

Mazoliin

I've done a similar system to what you're trying, and I've got a gui with a label and two buttons for the characters speaking (as I have the both the player and NPC in closeup).

I have a custom speech function that starts animating the appropriate button and writes text letter by letter to the lable. It's quite a lot of code, and might not be the best solution, but it do work.

It's been a while since I last touched it, but if you wan't I can clean it up and upload the script.

Sephiroth

#2
Hello,

This could be achieved using a set of gui + custom dialog function.

Here is a dialog function I'm using along with the gui explaination:

-First Gui: gGui1 contains a button 'Button1' which will be the portrait. Z order 0.
-Second Gui: gGui2 which is the background of the text, transparency 50, Z order 1.
-Third Gui : gGui3 which has Label1 as title and Label2 as dialog text, Z order 2.

Code: ags

function DialogLine(int namecolour,  String name, String line, int portrait, bool waitforakey)
{
   player.StopMoving();
   //PauseGame();
   
   String tmp2 = "";

   Label1.Text = name;
   Label1.TextColor = namecolour;
   Label2.Text = "";
   Button1.NormalGraphic = portrait;

   gGui1.Visible = true;
   gGui2.Visible = true;
   gGui3.Visible = true;

   int i = 0;
   while (i < line.Length)
   {
     if(line.Chars[i]!= ' ' && line.Chars[i]!= '*')
      Wait(2);
      
     if(line.Chars[i] == '*')
     {
      Wait(6);
     }
     else
       tmp2 = tmp2.AppendChar(line.Chars[i]);
     Label2.Text = tmp2;
     i++;
   }
   Wait(15);
   if (waitforakey == true)
    while (!IsKeyPressed(eKeySpace)) { Wait(5); }
   gGui1.Visible = false;
   gGui2.Visible = false;
   gGui3.Visible = false;
  // UnPauseGame();

}


DialogLine(0, "Myname", "What I have to say",10,  true);
DialogLine(0, "Myname", "What I have to say after space key is pressed",10,  true);

This function is what I'm using but may not fit your requirements:

Using * will create a small pause in the dialog text.
The text is displayed letter by letter with a small delay.
Will wait for space key to be pressed before it returns.

The position for gui elements such as portrait and label can be passed as parameters if needed.

It can be easily adapted, I hope it helps.



Snarky

Alright, thanks guys! So this is essentially a more elaborate version of my second piece of code, then. So I have to give up the whole built-in dialog system, is that right?

I'm planning multiple-choice conversations, and was hoping I could avoid having to code my own dialog system to keep track of the branching paths and so on. But maybe it's not really all that much more difficult to do it in code than it is in the dialog editor.

However, it would be nice if the Sierra-style speech option was more configurable, so that you could position and style the portrait and text box where and how you wanted, and these workarounds would be unnecessary.

Sephiroth

#4
I'm assuming what you want to achieve can't be done via classic sierra style speech system, but never tried. I'm merely offering an easy alternative.

Also I could post the dialog options code, which can return a number depending on what the user chose, but this is only effective if your dialog branches are not too complex. Or it will require more work, or even a plugin.

Maybe you can specify a custom gui for the text with sierra-style, so you can keep the dialog branches system and position the gui elements the way you like? I will try to see and edit later. Edit : I'm not sure but it seems the only gui you can change is the one for dialog options.

Snarky

Yeah, there is a variable for setting the GUI to use for Sierra-style speech, but I assumed AGS would take over the positioning and all that. I'll look into it when I'm on a non-Mac.

I appreciate the help. I'm probably not going to get very fancy with animated closeups or text appearing letter-by-letter, but it's nice to know that it's an option.

Mazoliin

This is how I do it

Simply set up all the gui elements (a button and a label) on a gui and change all the #define in the begining of the script. Then use charachter.Speak instead of say:

player.Speak("hello");
or
player.Speak("hello", 0, true);

0 is the loop of the characters think view, and the bool determens if the will text be append to already written text.

The text will be written letter by letter, and can be skipped with space or the left mouse button. And it works with the default dialog system.

Sephiroth

Quote
And it works with the default dialog system.

This code doesn't work with default "dialog branches" system, this is rather a more complex character.say command.

On a side note it would be nice to have the sierra-style speech GUI available from the Gui panel in the editor, it would make the whole dialog options system available while allowing any visual modifications.

Mazoliin

QuoteThis code doesn't work with default "dialog branches" system

Well, I got it to work with AGS dialogs on my end, but I only tried it in a simple dialog, one initial with one sub-dialog, but I don't see how it will fail in a more complex setup. But maybe I'm just missing the point entierly since I haven't worked that much with complicated dialogs.

Sephiroth

#9
Intresting, what I achieved is complete dialog option in the form of:

Code: ags


int choice = 0;

DialogLine(...);
DialogLine(...);

choice = DialogOption(...);

if(choice == 1)
{
  DialogLine(...);
  choice = DialogOption(...);
  if(choice == 1)
  {
   //etc
  }
  else if(choice == 2)
  {
   //etc
  }
}
else if(choice == 2)
{
}



I'm using a listbox inside the same dialog gui, and having the keyboard controllling the listbox and checking the input in repeatedly_execute_always I can achieve basic options like this, but I would love to see how you re doing it, there may be a more simple way...

Scripting a complex dialog system is really hard when you don't have Threads functions.

Khris

Quote from: Sephiroth on Tue 12/04/2011 15:45:31
Quote
And it works with the default dialog system.

This code doesn't work with default "dialog branches" system, this is rather a more complex character.say command.

It should if you use only " player.Speak(...);" lines in the dialog scripts instead of the usual "player: ..." ones.

It would be exceptionally great though if we could override the default .Say command.

Snarky

Ah, I guess you're doing it by incorporating function calls into the dialog script, so is instead of writing something like:

Code: ags
@S
EGO: I am looking for the unicorn emporium.
DWARF: Head ye down that road yonder.
return


You'll write:

Code: ags
@S
  cEgo.Speak("I am looking for the unicorn emporium.");
  cDwarf.Speak("Head ye down that road yonder.");
return


Right? Yes, that's quite clever, and I hadn't thought of that. There's going to be a little bit of additional work to make the closeup stay up during the dialog selection, but I think I see how it can be done.

Sephiroth

#12
Thanks for the tips, I also want to achieve something similar, now I can use your idea for dialog text display too, but I also want to have a custom dialog option system, so I thought I had no alternative left...

But I just discovered 'DialogOptionsRenderingInfo' and a set of threaded functions can be defined to totally customize the options display/behaviour. This should work beautifully!

Snarky

Thanks guys! By combining and modifying your samples I was able to get it to do what I wanted. Well, I haven't extended it to dialog options yet, but I feel confident it will work.

SMF spam blocked by CleanTalk