[SOLVED] Continuous speech animation over several lines of dialogue

Started by Laura Hunt, Mon 29/07/2019 13:44:48

Previous topic - Next topic

Laura Hunt

From what I've seen, every time a "Say" command is used (or a new line is spoken inside a dialogue), the speaking character's speech animation gets triggered from the start. So if I have a character say five lines, instead of the animation rolling across those 5 lines uninterrupted, it starts again for every new line.

This is a bit of a problem because I have an "angry" speaking animation in which the character among other things moves his arms up and down, so that sometimes the animation gets cut when for example, he has his arms up, and re-triggered from the initial position with his arms down, so it all looks a bit jerky. Nothing huge, nothing game-breaking, just annoying.

Is there a (simple) way around this by any chance, so that the whole animation plays seamlessly from the character's first line to the last?

eri0o

I can't understand what you just said, but you will probably need to write your own specialized Speech function if you need to personalize for all your particular Edge cases. Can't you just removing animation from being on Say and create a MySay with an optional parameter that triggers the specific animation, and then have different views/loops depending on YOUR knowledge of the sentence ahead?

Khris

Something like this could work:
Code: ags
  player.LockView(player.SpeechView);
  player.Animate(player.Loop, 5, eRepeat, eNoBlock);
  player.SayBackground("the first line");
  WaitMouseKey(20000);
  player.SayBackground("the 2nd line");
  WaitMouseKey(20000);
  player.UnlockView();

Laura Hunt

Quote from: Khris on Tue 30/07/2019 12:35:37
Something like this could work:
Code: ags
  player.LockView(player.SpeechView);
  player.Animate(player.Loop, 5, eRepeat, eNoBlock);
  player.SayBackground("the first line");
  WaitMouseKey(20000);
  player.SayBackground("the 2nd line");
  WaitMouseKey(20000);
  player.UnlockView();



* puts on thinking glasses, squints at code * Hmmmmm mayyyyybeee... I'll give it a try and see. Thanks for the suggestion, Khris! :)

Laura Hunt

#4
Quote from: eri0o on Tue 30/07/2019 11:51:51
I can't understand what you just said,

Imagine that I have a speaking animation in which my character first raises his arms, then shakes his fist, then brings his arms back down, and then it starts again.

If I do the following, the whole animation will play because the sentence is long enough and might even loop a couple of times:

Code: ags
cJohn.Say("My name is John and I am very angry because of reasons I don't want to talk about right now");


But if I do the following:

Code: ags
cJohn.Say("My name is John.");    // John raises his arms.
cJohn.Say("I am very angry".);     // John raises his arms *again* because the animation plays from the start with each new "Say".
cJohn.Say("Because of reasons I don't want to talk about...");    //John raises his arms and shakes his fist because the sentence is long enough for that.
cJohn.Say("...right now.");   // Animation starts again from the beginning, so that in the middle of shaking his fist, he raises his arms again all of a sudden.


So in the second case, 1) I rarely get to see him shake his fist because most sentences are too short for him to reach that part of the animation, and 2) the animation gets cut off all the time as it keeps starting over with each new sentence. So what I'm looking for is a way for the whole animation to play uninterruptedly the same way it does when I have him say all this in a single sentence.

Quote from: eri0o on Tue 30/07/2019 11:51:51
but you will probably need to write your own specialized Speech function if you need to personalize for all your particular Edge cases. Can't you just removing animation from being on Say and create a MySay with an optional parameter that triggers the specific animation, and then have different views/loops depending on YOUR knowledge of the sentence ahead?

Yes, one option would be to divide the long loop into shorter loops (one for raising arms, one for shaking fist, one for bringing arms down) and assign a different one to each sentence but that still wouldn't fix the issue of the different loops cutting each other off when they transition into each other; unlike having a single, long, smooth animation.

Like I said, it's not a huge issue and if I don't find a satisfactory alternative I'll just bite the bullet because I have a lot more stuff to focus on, but I wanted to ask just in case somebody had a "ah yeah, just do THIS magic thing" tip ;)


Khris

The code I posted works in general, but here's an improved way:

Code: ags
void MySayBackground(this Character*, String message) {
  Overlay* o = this.SayBackground(message);
  int delay = ((message.Length / game.text_speed) + 1) * GetGameSpeed();
  WaitMouseKey(delay);  // replace this depending on how player can skip speech
  if (o != null && o.Valid) o.Remove();  
}


With this, you can do:
Code: ags
  player.LockView(player.SpeechView);
  player.Animate(player.Loop, 5, eRepeat, eNoBlock);
  player.MySayBackground("the first line");
  player.MySayBackground("the 2nd line");
  player.UnlockView();

Laura Hunt

#6
That looks great, thanks! I wasn't too happy with the idea of having a fixed delay for each line (or having to guesstimate it myself case by case) but this is amazing! I'll try to give it a test run in my game tonight ;-D

Laura Hunt

It works like a CHARM! Just one correction, though. Instead of

Code: ags
Overlay* o = player.SayBackground(message);


It needs to be

Code: ags
Overlay* o = this.SayBackground(message);



Thanks SO much, Khris. You're a star.

Khris


SMF spam blocked by CleanTalk