Jibble

Author Topic: Skip through custom typewriter effect  (Read 1796 times)

Skip through custom typewriter effect
« on: 08 Jun 2016, 11:07 »
Hey everyone!
First i want to thank you all for your help, i have been cruising the forum as a guest for weeks and resolved all my problems thanks to you guys.

Well until now, my limited scripting knowledge is showing.
I've got a typewriting script and it works great, but i want to be able to skip the typewriter effect and show the entire line being typed at once (on mouse click or key press):

Code: Adventure Game Studio
  1.     Overlay *TypedText;
  2.    
  3.       void CommentNARRATOR(int delay, String text){
  4.                                                          
  5.  
  6.      int x;
  7.      int y;
  8.      AudioClip *sound;
  9.      sound = aNarrator_voice;
  10.      String displayedLine = "";
  11.      int i = 0;
  12.  
  13.   while (i < text.Length) {
  14.    
  15.      displayedLine = String.Format ("%s%c", displayedLine, text.Chars[i]);
  16.      TypedText = Overlay.CreateTextual(85, 530, 555, eFontnarrator, 65535, displayedLine);
  17.    
  18.     if (text.Chars[i] == ' ')
  19.       Wait(delay/2);
  20.     else if (text.Chars[i] == '[')
  21.       Wait(delay/2);
  22.     else {
  23.       if (sound)
  24.         sound.Play ();
  25.        Wait(delay);
  26.        
  27.      }
  28.  
  29.      i++;
  30.  
  31.   }
  32.  if (TypedText.Valid)
  33.      WaitMouseKey(TYPEnarrator_MAXIMUM_DISPLAY_TIME * (delay * 4));
  34.      TypedText.Remove();
  35.      }
  36.  
  37.  

I tried multiple things, but nothing worked.

if (mouse.IsButtonDown(eMouseLeft))
i = text.Length;
is a start but only type the first letter?

Snarky

  • Global Moderator
  • Global Moderator
  • Mittens Lord
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Skip through custom typewriter effect
« Reply #1 on: 08 Jun 2016, 11:38 »
Instead of

Code: Adventure Game Studio
  1.      displayedLine = String.Format ("%s%c", displayedLine, text.Chars[i]);

Try

Code: Adventure Game Studio
  1.      displayedLine = text.Truncate(i);

(The problem is that you were building the displayedLine character by character, so by skipping all the intermediate steps it would miss out all of the corresponding characters. Here instead we just set displayedLine directly to the first i characters of the text.)

Also, don't set i to text.Length; set it to text.Length-1. Otherwise the body of the loop won't run.
« Last Edit: 08 Jun 2016, 11:42 by Snarky »

Danvzare

  • The Man with No Name
    • I can help with AGS tutoring
    • I can help with proof reading
    • I can help with scripting
    • I can help with voice acting
    • Danvzare worked on one or more games that was nominated for an AGS Award!
Re: Skip through custom typewriter effect
« Reply #2 on: 08 Jun 2016, 11:47 »
I tested this out to see if it works, and it does.

Code: Adventure Game Studio
  1.     Overlay *TypedText;
  2.    
  3.       void CommentNARRATOR(int delay, String text){
  4.                                                          
  5.  
  6.      int x;
  7.      int y;
  8.      AudioClip *sound;
  9.      sound = aNarrator_voice;
  10.      String displayedLine = "";
  11.      int i = 0;
  12.   StartCutscene(3);
  13.   while (i < text.Length) {
  14.    
  15.      displayedLine = String.Format ("%s%c", displayedLine, text.Chars[i]);
  16.      TypedText = Overlay.CreateTextual(85, 530, 555, eFontnarrator, 65535, displayedLine);
  17.    
  18.     if (text.Chars[i] == ' ')
  19.       Wait(delay/2);
  20.     else if (text.Chars[i] == '[')
  21.       Wait(delay/2);
  22.     else {
  23.       if (sound)
  24.         sound.Play ();
  25.        Wait(delay);
  26.        
  27.      }
  28.  
  29.      i++;
  30.  
  31.   }
  32.  EndCutscene();
  33.  if (TypedText.Valid)
  34.      WaitMouseKey(TYPEnarrator_MAXIMUM_DISPLAY_TIME * (delay * 4));
  35.      TypedText.Remove();
  36.      }
  37.  
  38.  

Only two lines of code, and it's done.

By the way, those lines are StartCutscene(3) and EndCutscene().
(They're on lines 12 and 32.)
« Last Edit: 08 Jun 2016, 11:49 by Danvzare »

Re: Skip through custom typewriter effect
« Reply #3 on: 08 Jun 2016, 12:21 »
Hi Snarky!

Code: Adventure Game Studio
  1. displayedLine = text.Truncate(i);
  2.  

I loose my last letter!
(thanks for the text.Length-1 tip)


Hey Danvzare!

It works perfectly indeed, thank you! I didn't know it was "proper" to use StartCutscene/EndCutscene like that.

Snarky

  • Global Moderator
  • Global Moderator
  • Mittens Lord
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Skip through custom typewriter effect
« Reply #4 on: 08 Jun 2016, 12:56 »
Hi Snarky!

Code: Adventure Game Studio
  1. displayedLine = text.Truncate(i);
  2.  

I loose my last letter!
(thanks for the text.Length-1 tip)

Oh, right. Unlike the version you had, Truncate(i) doesn't include the i'th character, so to behave the same way you should change the loop to go from 1 to text.Length, instead of from 0 to text.Length-1. (And then set the value back to text.Length in the skip event.) Like this:

Code: Adventure Game Studio
  1.   int i = 1;     // 1 instead of 0
  2.   while (i <= text.Length) // Notice the equals sign
  3.   {
  4.     // ...
  5.     i++;
  6.   }

The StartCutscene()/EndCutscene() solution certainly works, but it's a bit inefficient internally. If you have background animations going on at the same time, they will jump ahead any time you skip, which you may or may not want.

Re: Skip through custom typewriter effect
« Reply #5 on: 08 Jun 2016, 14:11 »
Ooookay thanks i see now. Works the same!

I can skip, but i think it's messing with the waitmousekey, if i click when the line is done it's getting to the next line directly whithout the typing effect.

 I've got:

Code: Adventure Game Studio
  1.  
  2.      i++;
  3.  
  4.       if (mouse.IsButtonDown(eMouseLeft)){
  5.       i = text.Length;  
  6.       }  
  7.   }
  8.       if (TypedText.Valid)
  9.      WaitMouseKey(TYPEnarrator_MAXIMUM_DISPLAY_TIME * (delay * 4));
  10.      // if i put a Wait() here it's solving the problem but not for the first line in the dialog (which is triggered by an option)
  11.      TypedText.Remove();
  12.       }
  13.  

I think i'm missing a stupid detail as always :/

Snarky

  • Global Moderator
  • Global Moderator
  • Mittens Lord
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Skip through custom typewriter effect
« Reply #6 on: 08 Jun 2016, 16:15 »
If you're happy with the StartCutscene()/EndCutscene() solution, just go with that.

Otherwise, off the top of my head the best solution has to do with setting a flag when you skip to the end of the typewriting (e.g. typingInterrupted = true), and treat that case separately. Depending on how robust you want to make it (i.e. what happens if the user presses the mouse button and doesn't let go?) it could get a bit complicated, though.

Re: Skip through custom typewriter effect
« Reply #7 on: 08 Jun 2016, 16:55 »
Try this:

Code: [Select]
bool MyWait(int delay) {
  int i = 0;
  bool down;
  while (i < delay) {
    Wait(1);
    down = mouse.IsButtonDown(eMouseLeft);
    if (down) i = delay;
    i++;
  }
  return down;
}

Overlay *TypedText;

void CommentNARRATOR(String text, int delay) {
 
  int x;
  int y;
  AudioClip *sound;
  sound = aNarrator_voice;
  String displayedLine = "";
  int i = 0;
  bool skip = false;
 
  while (i < text.Length) {
   
    displayedLine = text.Truncate(i + 1);
    TypedText = Overlay.CreateTextual(85, 530, 555, eFontnarrator, 65535, displayedLine);
   
    if (text.Chars[i] == 32 || text.Chars[i] == 91) {
      skip = MyWait(delay / 2);
      if (skip) i = text.Length - 2;
    }
    else {
      if (sound != null && !skip)
        sound.Play();
      skip = MyWait(delay); 
      if (skip) i = text.Length - 2;
    }
    i++;
  }
  if (skip) {
    Game.StopAudio(eAudioTypeSound);
    while (mouse.IsButtonDown(eMouseLeft)) Wait(1);
  }
 
  if (TypedText.Valid && !skip)
    WaitMouseKey(TYPEnarrator_MAXIMUM_DISPLAY_TIME * (delay * 4));
  TypedText.Remove();
}

Re: Skip through custom typewriter effect
« Reply #8 on: 08 Jun 2016, 18:03 »
Hi Khris!

I get a "Error (line 15): Parameter type does not match prototype" :/


Re: Skip through custom typewriter effect
« Reply #9 on: 08 Jun 2016, 19:25 »
Sorry, I completely forgot; I switched around the order of the parameters because I wanted to make delay into an optional parameter.

Look at your GlobalScript.ash for the line that says
Code: [Select]
import void CommentNARRATOR(int delay, String text);Change it to
Code: [Select]
import void CommentNARRATOR(String text, delay = 4);  // default value, delay is now optional
However, if you already have lots of function calls in your script, you might probably switch the order in the function definition instead, otherwise you have to change all those function calls.

Re: Skip through custom typewriter effect
« Reply #10 on: 09 Jun 2016, 10:47 »
Okay thanks a lot! Works like a charm :) i kept the int delay, i like being able to change the speed directly.

But i still get the same problem as with Snarky's script: when i click on a finished line, it skips to the next without typing.
If i put a wait() just after the waitmousekey it's good, but when i click on a dialog option for example the next first line skip the typing.

Re: Skip through custom typewriter effect
« Reply #11 on: 09 Jun 2016, 12:10 »
At the very start of the function, add this:
Code: [Select]
  while (mouse.IsButtonDown(eMouseLeft)) Wait(1);
As for stating the delay, the key word is "optional".
By using the import line like I suggested, you can state the delay or omit it, which will set it to 4.

Code: [Select]
  CommentNARRATOR("Standard delay");  // uses delay = 4
  CommentNARRATOR("Slow talking", 10);

Re: Skip through custom typewriter effect
« Reply #12 on: 09 Jun 2016, 15:54 »
Quote
As for stating the delay, the key word is "optional".
By using the import line like I suggested, you can state the delay or omit it, which will set it to 4.

Ok yes got it, even more handy.

And yes thank you that solved it!! I don't quite understand all of it for now but i'll make sure to study it :)
Thanks for the quick reply and taking time to explain, you guys are awesome.

Re: Skip through custom typewriter effect
« Reply #13 on: 16 Nov 2021, 16:57 »
I'm sorry to dredge up this ancient post!

I'm using this CommentNARRATOR typewriter code for my next game, and was wondering how to go about rendering the typed text in a GUI label rather than as an overlay? This is because I have lighting/shadow GUI layers running in the game, and I'd like the text to be "above" this. The overlay is always drawn behind the GUI in the Z order, if that makes sense.

I've been fiddling around with no avail. Any help would be greatly appreciated :)

Many thanks,
Shaun

Code: Adventure Game Studio
  1.      Overlay *TypedText;
  2.  
  3. void CommentNARRATOR(String text, int delay) {
  4.  
  5.    while (mouse.IsButtonDown(eMouseLeft)) Wait(1);
  6.  
  7.   int x;
  8.   int y;
  9.   AudioClip *sound;
  10.   sound = null;
  11.   String displayedLine = "";
  12.   int i = 0;
  13.   bool skip = false;
  14.  
  15.   while (i < text.Length) {
  16.    
  17.     displayedLine = text.Truncate(i + 1);
  18.     TypedText = Overlay.CreateTextual(10, 140, 300, eFontMunro2, 65535, displayedLine);
  19.    
  20.     if (text.Chars[i] == 32 || text.Chars[i] == 91) {
  21.       skip = MyWait(delay / 2);
  22.       if (skip) i = text.Length - 2;
  23.     }
  24.     else {
  25.       if (sound != null && !skip)
  26.         sound.Play();
  27.       skip = MyWait(delay);
  28.       if (skip) i = text.Length - 2;
  29.     }
  30.     i++;
  31.   }
  32.   if (skip) {
  33.     Game.StopAudio(eAudioTypeSound);
  34.     while (mouse.IsButtonDown(eMouseLeft)) Wait(1);
  35.   }
  36.  
  37.   if (TypedText.Valid && !skip)
  38.     WaitMouseKey(delay*4);
  39.    WaitMouseKey(4000 * (delay * 4));
  40.    //WaitMouseKey(TYPEnarrator_MAXIMUM_DISPLAY_TIME * (delay * 4));
  41.   TypedText.Remove();
  42. }
  43.  
Support Cloak and Dagger Games on Patreon: https://www.patreon.com/user?u=460039

Re: Skip through custom typewriter effect
« Reply #14 on: 16 Nov 2021, 17:59 »
@shaun9991, it seems simple, just replace
Code: Adventure Game Studio
  1. TypedText = Overlay.CreateTextual(10, 140, 300, eFontMunro2, 65535, displayedLine);
  2.  
with
Code: Adventure Game Studio
  1. myLabel.Text = displayedLine;
  2.  

Of course you'd also have to make gui visible before typewriter effect starts, and replace "TypedText.Remove();" with "gMyGui.Visible = false;" or similar.
« Last Edit: 16 Nov 2021, 18:00 by Crimson Wizard »

Re: Skip through custom typewriter effect
« Reply #15 on: 17 Nov 2021, 08:43 »
That worked a charm, thank you so much CW! :)
Support Cloak and Dagger Games on Patreon: https://www.patreon.com/user?u=460039