Adventure Game Studio

AGS Support => Advanced Technical Forum => Topic started by: HillBilly on Sat 22/07/2006 16:20:47

Title: Background speech issues (SOLVED)
Post by: HillBilly on Sat 22/07/2006 16:20:47
Hello,

I've been having some problems with backgroundspeech in AGS v.2.62. What I need is a character(CHIP) randomly mumbling lines while the main character(EGO) can walk around doing stuff. CHIP's talking animation needs to be displayed when he says something, and a sound clip needs to be played, since backgroundspeech don't support voices. Pablo has been so kind to help me out with a script, but unfortunately it still remains some difficulties. Here's the script in question:

           int time=120;
           
           int timer;
           int animating=0;
           int rand;
#sectionstart room_c  // DO NOT EDIT OR REMOVE THIS LINE
function room_c() {
  // script for room: Repeatedly execute       
       timer++;

if (animating==0) {
if (timer==time) {
  rand = Random(3);
  SetCharacterView(CHIP,23);
  AnimateCharacterEx(CHIP, 0, 5, 1, 0, 0);
  if (rand == 0) {
    PlaySound(13);
    DisplaySpeechBackground(CHIP, "Line1.");
  }
  if (rand == 1) {
    PlaySound(14);
    DisplaySpeechBackground(CHIP, "Line2.");
  }
  if (rand == 2) {
    PlaySound(15);
    DisplaySpeechBackground(CHIP, "Line3");
  }
  else if (rand == 3) {
    PlaySound(16);
    DisplaySpeechBackground(CHIP, "Line4.");
  }
  timer=0;
  animating=1;
}
}

if (timer==time) {
  DisplaySpeechBackground(CHIP, "");
  ReleaseCharacterView(CHIP);
  animating=0;
  timer=0;
}
}


Here's the different results of the scipt:

Keeping as it is - CHIP talks and plays the clip, but the talking animation lasts a bit too long. If the main character says something while CHIP does, the talking animation last very long. This is the main problem.

Adding "ReleaseCharacterView(CHIP);" After "DisplaySpeechBackground(CHIP,..." - Of course, now the talking animation won't play. Maybe if I had a way for it to wait until after the sound clip is finished playing, but I don't know how to do that.

Adding "ReleaseCharacterView(CHIP);" after every line EGO says - An unpractical solution, but it worked partly. If EGO talks at the same time as CHIP, CHIP's talking animation stops at the same time as EGO. Since they both say relative short lines, it worked okay. However, if EGO is talking and is "interrupted" by CHIP, I get this:

Quote
(ACI version 2.62.772)

Error: run_text_script1: error -6 (Error (line 672): Script appears to be hung (150001 while loop iterations without an update)) running function 'room_c'

I know, I shouldn't be using 2.62 because this could be solved in a jiffy in 2.72. I'd change if I could, so this will probably be my last game in 2.62.

Thanks.

EDIT: Fix'd some code.

Edit by strazer: Please post error messages in clear text so they show up in the forum search.
Title: Re: Background speech issues
Post by: monkey0506 on Sat 22/07/2006 16:48:44
Quote from: HillBilly on Sat 22/07/2006 16:20:47while(character[CHIP].animating) PlaySound(13);

This is (obviously) the problem (as it's the only while loop). The problem is that you have the animation set up to repeat:

AnimateCharacterEx(CHIP, 0, 5, 1, 0, 0); // int CHARID, int loop, int delay, int repeat, int direction, int blocking

So that the character is animating forever (until you manually stop it). Since you never stop the character animating, the while loop is run indefinitely and crashes the game. Perhaps this "while" should be an "if"?
Title: Re: Background speech issues
Post by: HillBilly on Sat 22/07/2006 16:56:54
Quote from: monkey_05_06 on Sat 22/07/2006 16:48:44
Quote from: HillBilly on Sat 22/07/2006 16:20:47while(character[CHIP].animating) PlaySound(13);

This is (obviously) the problem (as it's the only while loop).

D'oh. I'm sorry, I was checking out if there was any .talking varibles, and forgot to remove it. It was not supposed to be there.

Quote from: monkey_05_06 on Sat 22/07/2006 16:48:44The problem is that you have the animation set up to repeat:

AnimateCharacterEx(CHIP, 0, 5, 1, 0, 0); // int CHARID, int loop, int delay, int repeat, int direction, int blocking

So that the character is animating forever (until you manually stop it). Since you never stop the character animating, the while loop is run indefinitely and crashes the game. Perhaps this "while" should be an "if"?

If I remove repeat, CHIP only plays the animation once, and stops at the last frame. And it stays there for aslong as the talking animation would loop.
Title: Re: Background speech issues
Post by: monkey0506 on Sat 22/07/2006 17:00:04
Hmmm...funny the way I write things sometimes...

But...erm...now I'm confused. You said something about the while loop wasn't supposed to be there?

The way you called AnimateCharacterEx is fine BTW, I meant that because it repeats the while loop would run forever.
Title: Re: Background speech issues
Post by: Ashen on Sat 22/07/2006 17:03:54
This could be the best answer:
Quote from: HillBilly on Sat 22/07/2006 16:20:47
Adding "ReleaseCharacterView(CHIP);" After "DisplaySpeechBackground(CHIP,..." - Of course, now the talking animation won't play. Maybe if I had a way for it to wait until after the sound clip is finished playing, but I don't know how to do that.

If you've got no other sounds that're likely to play, you could use IsSoundPlaying. Since it sounds like you might have EGO speaking at the same time, you could try using PlaySoundEx to force Chip's speech to a specific channel, then use IsChannelPlaying to check if it's done (e.g. if (IsChannelPlaying(5) == 0 && character[CHIP].animating) ReleaseCharacterView(CHIP);).
Title: Re: Background speech issues
Post by: HillBilly on Sat 22/07/2006 18:13:53
That worked for the normal talk. He now stops animating right when the text disappears. Unfortunately, it's not the same case when EGO interrupts him. Then the animation keeps looping for a while, and it loops even longer if the player, for example, clicks "look at" on an object again and again.

It seems that when the text disappears(as it does when it's interrupted by "normal" speech), it forgets about the rest of the code. I've tried adding if (IsChannelPlaying(3) == 0 && character[CHIP].animating){ ReleaseCharacterView(CHIP); both before and after "DisplaySpeechBackground", but no luck.

If it makes any difference, the text itself could be sacrified. Aslong as the voice and animation is in sync, I'm happy.
Title: Re: Background speech issues
Post by: Ashen on Sat 22/07/2006 20:13:53
Pah, didn't think about that ...

You could also check EGO's current view against his speech view (character[EGO].view == character[EGO].talkview in 2.62, I think).

Thinking about it though, you should also be able to make use of the overlay functions (since BackgroundSpeech uses them too). Make a new int and assign it the overlay number of the background speech, e.g.:

           int line;
#sectionstart room_c  // DO NOT EDIT OR REMOVE THIS LINE
function room_c() {
  // script for room: Repeatedly execute       
// blah blah blah
    line = DisplaySpeechBackground(CHIP, "Line1.");
// yadda yadda yadda
    line = DisplaySpeechBackground(CHIP, "Line2.");
// etc


Then, you should be able to use IsOverlayValid(line) to check if Chip is 'speaking' and release the view as needed.
Title: Re: Background speech issues
Post by: HillBilly on Sat 22/07/2006 21:05:11
Quote from: Ashen on Sat 22/07/2006 20:13:53
Then, you should be able to use IsOverlayValid(line) to check if Chip is 'speaking' and release the view as needed.

Where would I place this? I tried this:

  else if (rand == 3) {
    PlaySoundEx(16, 3);
    line = DisplaySpeechBackground(CHIP, "Line3.");
    if (IsChannelPlaying(3) == 0 && character[CHIP].animating && IsOverlayValid(line)){
    ReleaseCharacterView(CHIP);
    }
  }


But that seems illogical, and didn't work either. So I'm probably doing it the wrong way. I think I need this spoon-fed.
Title: Re: Background speech issues
Post by: Ashen on Sun 23/07/2006 19:37:29
It'd need to be a seperate check, like the if (timer == time) one, at the end of the rep_ex function - or possibly rep_ex_always, as it may be blocked by EGO's speech otherwise. It doesn't need to be linked with the IsChannelPlaying and character.animating conditions, since it's checking for something else (EGO interupting, rather than the speech finishing on it's own).
Title: Re: Background speech issues
Post by: HillBilly on Sun 23/07/2006 21:42:23
I think I understood you wrong. I tried this:

       timer++;

if (animating==0) {
if (timer==time) {
  rand = Random(3);
  SetCharacterView(CHIP,23);
  AnimateCharacterEx(CHIP, 0, 5, 1, 0, 0);
  if (rand == 0) {
    PlaySoundEx(13, 3);
    line = DisplaySpeechBackground(CHIP, "!");
    if (IsChannelPlaying(3) == 0 && character[CHIP].animating){
    ReleaseCharacterView(CHIP);
    }
  }
  if (rand == 1) {
    PlaySoundEx(14, 3);
    line = DisplaySpeechBackground(CHIP, "!");
    if (IsChannelPlaying(3) == 0 && character[CHIP].animating){
    ReleaseCharacterView(CHIP);
    }
  }
  if (rand == 2) {
    PlaySoundEx(15, 3);
    line = DisplaySpeechBackground(CHIP, "...");
    if (IsChannelPlaying(3) == 0 && character[CHIP].animating){
    ReleaseCharacterView(CHIP);
    }
  }
  else if (rand == 3) {
    PlaySoundEx(16, 3);
    line = DisplaySpeechBackground(CHIP, ".");
    if (IsChannelPlaying(3) == 0 && character[CHIP].animating){
    ReleaseCharacterView(CHIP);
    }
  }
  timer=0;
  animating=1;
}
}

if (timer==time) {
  if (IsOverlayValid(line)){
  DisplaySpeechBackground(CHIP, "");
  ReleaseCharacterView(CHIP);
  animating=0;
  timer=0;
}
}


and this

       timer++;

if (animating==0) {
if (timer==time) {
if (timer==time) {
  rand = Random(3);
  SetCharacterView(CHIP,23);
  AnimateCharacterEx(CHIP, 0, 5, 1, 0, 0);
  if (rand == 0) {
    PlaySoundEx(13, 3);
    line = DisplaySpeechBackground(CHIP, "!");
    if (IsChannelPlaying(3) == 0 && character[CHIP].animating){
    ReleaseCharacterView(CHIP);
    }
  }
  if (rand == 1) {
    PlaySoundEx(14, 3);
    line = DisplaySpeechBackground(CHIP, "!");
    if (IsChannelPlaying(3) == 0 && character[CHIP].animating){
    ReleaseCharacterView(CHIP);
    }
  }
  if (rand == 2) {
    PlaySoundEx(15, 3);
    line = DisplaySpeechBackground(CHIP, ".");
    if (IsChannelPlaying(3) == 0 && character[CHIP].animating){
    ReleaseCharacterView(CHIP);
    }
  }
  else if (rand == 3) {
    PlaySoundEx(16, 3);
    line = DisplaySpeechBackground(CHIP, ".");
    if (IsChannelPlaying(3) == 0 && character[CHIP].animating){
    ReleaseCharacterView(CHIP);
    }
  }
  timer=0;
  animating=1;
}
}
}

  if (IsOverlayValid(line)){
  DisplaySpeechBackground(CHIP, "");
  ReleaseCharacterView(CHIP);
  animating=0;
  timer=0;
}


First code, CHIP didn't talk. Second code, CHIP wouldn't stop animating. :-\
Title: Re: Background speech issues
Post by: HillBilly on Mon 24/07/2006 18:14:55
Ashen helped me through some hardcore PM'ing. Here's the final code(works perfect):

  int time=120;
  int line= -1;         
  int timer;
  int animating=0;
  int rand;
function repeatedly_execute_always() {
  if (IsOverlayValid(line) || IsChannelPlaying(5)) { // If Text OR Sound is still valid
    if(animating == 1 && character[CHIP].animating == 0) {
      // If CHIP should be animating, but isn't - make him dance! (well, TALK, anyway)
      //(There's a vague chance channel 5 could be used by another game sound, and you don't want Chip to randomly animate then, do you...)
      SetCharacterView(CHIP,23);
      AnimateCharacterEx(CHIP, 0,5,0,0,0);
    }   
  }
  else if (line != -1 && IsChannelPlaying(5)==0) { // Text and Sound cleared, View not yet released
    ReleaseCharacterView(CHIP);
    animating = 0;
    timer = 0;
    line = -1;
  }
}
#sectionstart room_c  // DO NOT EDIT OR REMOVE THIS LINE
function room_c() {
  // script for room: Repeatedly execute       
      timer++;

  if (timer==time) {
if (line == -1) {
  rand = Random(3);
  SetCharacterView(CHIP,23);
  if (rand == 0) {
    PlaySoundEx(13, 5);
    line = DisplaySpeechBackground(CHIP, "line1.");
  }
  if (rand == 1) {
    PlaySoundEx(14, 5);
    line = DisplaySpeechBackground(CHIP, "line2.");
  }
  if (rand == 2) {
    PlaySoundEx(15, 5);
    line = DisplaySpeechBackground(CHIP, "line3.");
  }
  else if (rand == 3) {
    PlaySoundEx(16, 5);
    line = DisplaySpeechBackground(CHIP, "line4.");
  }
  timer=0;
  animating=1;
}
}
}