Help about saybackground speech animation in RepExec()

Started by rmonic79, Sun 28/12/2014 22:17:40

Previous topic - Next topic

rmonic79

I've tried this code without lockview and animate and the classic speech view doesn't work so i solved like this:

Code: ags

     int dialoghi=0;
function room_RepExec()
{
    if (BISTICCIO==true){
    if (dialoghi==0){cbibl.LockView(43);cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);cbibl.SayBackground("asdas");SetTimer(1,80);SetTimer(2, 60);dialoghi++;}
    if (IsTimerExpired(2)){cbibl.UnlockView();SetTimer(1, 20);}
    if (dialoghi==1&&IsTimerExpired(1)){cbibl.LockView(43);cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);cbibl.SayBackground("asdas");SetTimer(1,80);SetTimer(2, 60);dialoghi++;}
    if (dialoghi==2&&IsTimerExpired(1)){cbibl.LockView(43);cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);cbibl.SayBackground("asdas");SetTimer(1,80);SetTimer(2, 60);dialoghi++;}
    if (dialoghi==3&&IsTimerExpired(1)){cbibl.LockView(43);cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);cbibl.SayBackground("asdas");SetTimer(1,80);SetTimer(2, 60);dialoghi++;}
    if (dialoghi==4&&IsTimerExpired(1)){cbibl.LockView(43);cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);cbibl.SayBackground("asdas");SetTimer(1,80);SetTimer(2, 60);dialoghi++;}
    if (dialoghi==5&&IsTimerExpired(1)){cbibl.LockView(43);cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);cbibl.SayBackground("asdas");SetTimer(1,80);SetTimer(2, 60);dialoghi++;}
    if (dialoghi==6&&IsTimerExpired(1)){cbibl.LockView(43);cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);cbibl.SayBackground("asdas");SetTimer(1,80);SetTimer(2, 60);dialoghi++;}
    if (dialoghi==7&&IsTimerExpired(1)){cbibl.LockView(43);cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);cbibl.SayBackground("asdas");SetTimer(1,80);SetTimer(2, 60);dialoghi++;}
    if (dialoghi==8&&IsTimerExpired(1)){cbibl.LockView(43);cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);cbibl.SayBackground("asdas");SetTimer(1,80);SetTimer(2, 60);dialoghi++;}
    if (dialoghi==9&&IsTimerExpired(1)){cbibl.LockView(43);cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);cbibl.SayBackground("asdas");SetTimer(1,80);SetTimer(2, 60);dialoghi++;}
    if (dialoghi==10&&IsTimerExpired(1)){cbibl.LockView(43);cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);cbibl.SayBackground("asdas");SetTimer(1,80);SetTimer(2, 60);dialoghi++;}
    if (dialoghi==11&&IsTimerExpired(1)){cbibl.LockView(43);cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);cbibl.SayBackground("asdas");SetTimer(1,80);SetTimer(2, 60);dialoghi++;}
    if (dialoghi==12&&IsTimerExpired(1)){cbibl.LockView(43);cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);cbibl.SayBackground("asdas");SetTimer(1,80);SetTimer(2, 60);dialoghi++;}
    if (dialoghi==13&&IsTimerExpired(1)){dialoghi=0;}
    
  }
  
}

is there a lighter way to do this?

Monsieur OUXX

#1
I don't know exactly what's wrong with your code, but the "queued background speech" module (s) should make your life much easier.

This one : QueuedSpeech v3.5 here
Or that one : BgSpeech v2.2 here

 

monkey0506

#2
There are three major problems I see with your code.

Problem 1: You believe that whitespace in code is evil. While it can be overdone, unless your mission statement is to have no one ever see, read, use, or understand your code, then whitespace is a must. As a general rule of thumb, if you're putting more than one command on a single line, you're probably doing it wrong.

Code: ags
int dialoghi = 0;

function room_RepExec()
{
  if (BISTICCIO)
  {
    if (dialoghi == 0)
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (IsTimerExpired(2))
    {
      cbibl.UnlockView();
      SetTimer(1, 20);
    }
    if (dialoghi == 1 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 2 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 3 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 4 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 5 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 6 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 7 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 8 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 9 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 10 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 11 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 12 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 13 && IsTimerExpired(1))
    {
      dialoghi = 0;
    }
  }
}


Problem 2: You're breaking one of the first rules of programming: DO NOT repeat yourself. You have the following six lines of code repeated thirteen times:

Code: ags
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;


There is no excuse for copypasta like this showing up in your code. If necessary, create a separate function. In your case, however, it's a matter of...

Problem 3: Abusing conditional statements.

If you are checking the same condition (e.g., IsTimerExpired(1)) several times when you have no logical reason to believe that the result may have changed in-between, then you are doing it wrong. If you find yourself checking multiple values of a variable as separate conditions with the same end-result, then you are doing it wrong. If you are checking that a variable value falls within a certain range by using multiple equals checks, then you are doing it wrong.

Here is a more realistic example of what your above code should look like:

Code: ags
int dialoghi = 0;

function room_RepExec()
{
  if (BISTICCIO)
  {
    if ((dialoghi == 0) || (IsTimerExpired(1))) // this is SLIGHTLY redundant (if dialoghi is 0), but it saves us duplicating other code
    {
      if ((dialoghi >= 0) && (dialoghi < 13)) // 0 <= dialoghi < 13
      {
        // note these lines aren't duplicated 13 times!
        cbibl.LockView(43);
        cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
        cbibl.SayBackground("asdas");
        SetTimer(1, 80);
        SetTimer(2, 60);
        dialoghi++;
      }
      else if (dialoghi == 13) // ONLY if the previous condition was FALSE, then check this one
      {
        dialoghi = 0;
      }
    } // has timer 1 expired
    if (IsTimerExpired(2)) // no ELSE, we want to check timer 2 whether timer 1 has gone off or not
    {
      cbibl.UnlockView();
      SetTimer(1, 20);
    }
  }
}





I realize you are probably fairly new to programming, so please don't take this the wrong way. However, if you look at the expanded version of your code (Problem 1) and compare it to the final version (Problem 3), you'll see that I've cut over 77% of the lines while still maintaining readable code. The benefits of basic programming concepts like these speak for themselves.

As to your actual solution, there isn't really anything that could be done much more eloquently in terms of getting the speech animation to play for background speech aside from making the code more generic*. I've authored a few modules (QueuedSpeech, PersistentSpeech) that manually control the speech animation in-sync with non-standard character speech (e.g., not a blocking Say command). If you're interested, you could look at those modules, or else myself (and others) would be able to show you how to pull that particular feature and use it in your game, but I first feel that it is more important that you understand these more basic programming concepts. Once you have a strong grasp on the basics, then branching out into more advanced topics will be within your reach.

*And for what it's worth, generic programming isn't always simpler, cleaner, or more eloquent than a specialized solution. Instead, I mean that generic code would be more versatile, easily applied to other characters in other situations, adapt to variable game speed, text reading speed, and the like.

Edit: Looking back over this, I realized that the dialoghi == 0 condition actually doesn't depend on the timer, which is what sets everything else in motion. I amended my modified code to reflect this. Again, there are other ways you could accomplish that result, but this is effective enough to show what I am talking about.

rmonic79

Quote from: Monsieur OUXX on Sun 28/12/2014 22:44:52
I don't know exactly what's wrong with your code, but the "queued background speech" module (s) should make your life much easier.

This one : QueuedSpeech v3.5 here
Or that one : BgSpeech v2.2 here
thanks i will take a look ;)

rmonic79

Quote from: monkey_05_06 on Mon 29/12/2014 09:03:30
There are three major problems I see with your code.

Problem 1: You believe that whitespace in code is evil. While it can be overdone, unless your mission statement is to have no one ever see, read, use, or understand your code, then whitespace is a must. As a general rule of thumb, if you're putting more than one command on a single line, you're probably doing it wrong.

Code: ags
int dialoghi = 0;

function room_RepExec()
{
  if (BISTICCIO)
  {
    if (dialoghi == 0)
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (IsTimerExpired(2))
    {
      cbibl.UnlockView();
      SetTimer(1, 20);
    }
    if (dialoghi == 1 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 2 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 3 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 4 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 5 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 6 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 7 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 8 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 9 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 10 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 11 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 12 && IsTimerExpired(1))
    {
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;
    }
    if (dialoghi == 13 && IsTimerExpired(1))
    {
      dialoghi = 0;
    }
  }
}


Problem 2: You're breaking one of the first rules of programming: DO NOT repeat yourself. You have the following six lines of code repeated thirteen times:

Code: ags
      cbibl.LockView(43);
      cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
      cbibl.SayBackground("asdas");
      SetTimer(1, 80);
      SetTimer(2, 60);
      dialoghi++;


There is no excuse for copypasta like this showing up in your code. If necessary, create a separate function. In your case, however, it's a matter of...

Problem 3: Abusing conditional statements.

If you are checking the same condition (e.g., IsTimerExpired(1)) several times when you have no logical reason to believe that the result may have changed in-between, then you are doing it wrong. If you find yourself checking multiple values of a variable as separate conditions with the same end-result, then you are doing it wrong. If you are checking that a variable value falls within a certain range by using multiple equals checks, then you are doing it wrong.

Here is a more realistic example of what your above code should look like:

Code: ags
int dialoghi = 0;

function room_RepExec()
{
  if (BISTICCIO)
  {
    if ((dialoghi == 0) || (IsTimerExpired(1))) // this is SLIGHTLY redundant (if dialoghi is 0), but it saves us duplicating other code
    {
      if ((dialoghi >= 0) && (dialoghi < 13)) // 0 <= dialoghi < 13
      {
        // note these lines aren't duplicated 13 times!
        cbibl.LockView(43);
        cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
        cbibl.SayBackground("asdas");
        SetTimer(1, 80);
        SetTimer(2, 60);
        dialoghi++;
      }
      else if (dialoghi == 13) // ONLY if the previous condition was FALSE, then check this one
      {
        dialoghi = 0;
      }
    } // has timer 1 expired
    if (IsTimerExpired(2)) // no ELSE, we want to check timer 2 whether timer 1 has gone off or not
    {
      cbibl.UnlockView();
      SetTimer(1, 20);
    }
  }
}





I realize you are probably fairly new to programming, so please don't take this the wrong way. However, if you look at the expanded version of your code (Problem 1) and compare it to the final version (Problem 3), you'll see that I've cut over 77% of the lines while still maintaining readable code. The benefits of basic programming concepts like these speak for themselves.

As to your actual solution, there isn't really anything that could be done much more eloquently in terms of getting the speech animation to play for background speech aside from making the code more generic*. I've authored a few modules (QueuedSpeech, PersistentSpeech) that manually control the speech animation in-sync with non-standard character speech (e.g., not a blocking Say command). If you're interested, you could look at those modules, or else myself (and others) would be able to show you how to pull that particular feature and use it in your game, but I first feel that it is more important that you understand these more basic programming concepts. Once you have a strong grasp on the basics, then branching out into more advanced topics will be within your reach.

*And for what it's worth, generic programming isn't always simpler, cleaner, or more eloquent than a specialized solution. Instead, I mean that generic code would be more versatile, easily applied to other characters in other situations, adapt to variable game speed, text reading speed, and the like.

Edit: Looking back over this, I realized that the dialoghi == 0 condition actually doesn't depend on the timer, which is what sets everything else in motion. I amended my modified code to reflect this. Again, there are other ways you could accomplish that result, but this is effective enough to show what I am talking about.

thanks so much for advices, you're right i'm a noob to programming, this is why for me it's hard to optimize the code and write it in the properly way (but i'm learning thanks to all of you, six month ago i didn't know anything about coding). There's something i don't understand, maybe because i used copy and paste to show it. The text should change with counter, "asdas" was only an example (it was in the actual code) to try the scene. Can you help me to do this better than my horrible code :) (i know it's horrible this is why i opened the topic even if it works)
i will take a look at plugins but before use them i need to understand the concept.

monkey0506

A couple more tips (about forum etiquette): It's not necessary to quote the entire post to respond to someone, nor is it necessary to create separate posts (it's actually against the rules ;)). Just put the name of who you're addressing, and use quotes to give emphasis to particular things you are responding to.

As far as the code, I figured that you probably didn't want the same text over and over, but my post was getting pretty long as it was. The modules (not the same as plugins) sound like what you're looking for, but let me just say you should not try to use both of them together. They are independently coded to approach the same problem in different ways. For what it's worth, the module I wrote is more current, but many people seem to prefer SSH's module (I'll leave that to you ;)).

Extending from what we have in my last post, you need to use an array. Think of it as a collection of variables that all share the same name. We'll use your existing dialoghi variable to keep track of which line of background speech we're currently on, and store the actual text inside of the array. Like this:

Code: ags
int dialoghi = 0;
String dialoglines[]; // the array of dialog text
#define DIALOG_COUNT 13 // how many lines of dialog do we have

function room_Load()
{
  dialoglines = new String[DIALOG_COUNT]; // initialize the array itself
  dialoglines[0] = "asdas"; // fill in each line of dialog, starting from index 0...
  dialoglines[1] = "asdaf";
  // ...
  dialoglines[12] = "asdaz"; // ...and ending with DIALOG_COUNT - 1
}
 
function room_RepExec()
{
  if (BISTICCIO)
  {
    if ((dialoghi == 0) || (IsTimerExpired(1))) // this is SLIGHTLY redundant (if dialoghi is 0), but it saves us duplicating other code
    {
      if ((dialoghi >= 0) && (dialoghi < DIALOG_COUNT)) // 0 <= dialoghi < 13
      {
        // note these lines aren't duplicated 13 times!
        cbibl.LockView(43);
        cbibl.Animate(0, 6, eRepeat, eNoBlock, eForwards);
        cbibl.SayBackground(dialoglines[dialoghi]); // NOTICE we changed this! we now say whichever text line has the same # as dialoghi
        SetTimer(1, 80);
        SetTimer(2, 60);
        dialoghi++;
      }
      else if (dialoghi == DIALOG_COUNT) // ONLY if the previous condition was FALSE, then check this one
      {
        dialoghi = 0;
      }
    } // has timer 1 expired
    if (IsTimerExpired(2)) // no ELSE, we want to check timer 2 whether timer 1 has gone off or not
    {
      cbibl.UnlockView();
      SetTimer(1, 20);
    }
  }
}


By using dialoghi as an index to the array, we select each line in order, letting you display as many messages as you need (just update DIALOG_COUNT and add your text). This is a step toward making your code more generic, which as I said before can have many benefits.

Monsieur OUXX

#6
A little comment about the use of word "plugin". Be careful, don't confuse "plugins" and "modules" in the AGS world.

- Modules are just custom scripts (written in a slightly packaged manner)that we exchange to help each other. That's what I recommeneded to use above. You could make a module if you wanted to. It's very common to use a shitload of modules if you intend on making a full-length game, because they allow you to do things you (and others before you) have seen in certain types of adventure games (for example: background speeches, as seen in Lucasarts games ;) )
- Plugins are special libraries that were written in C++ or in C# or other advanced languages, then compiled into .DLL files. They need to be copied to your game folder if you want it to be able to start up. They are not part of standard AGS and they are usually used to perform advanced stuff that require a lot of calculations, such as graphic filters, etc. It's not very common to use plugins, especially if you're a beginner, unless you need to do something very specific or CPU-hungry.


 

rmonic79

thanks guys, sorry for plugin instead of module :)
the solution with array was brilliant and gave me the chance to work with them in ags and also optimize some old code in the game. ;)

rmonic79

just for let you know, using background speech with animation gave me some problems like: the character sometimes stop walking, often doesn't approach objects or hotspot ( for example he open the door from distance ), and more often if a look at something the background dialogue stops forever. I'm using another solution with idleview at 0 delay and timers created with variables ( like i read in a monkey post) and it seems to works fine now. Is it normal to have this problem? (i use 9verbs template)

monkey0506

The key to running a queue for background speech with animations is that you don't want it to interfere with other code, and that can be a fine line to balance. For example, I recently discovered that the 8-Direction module (which is rather dated anyway) is calling UnlockView on the player character every loop that the player isn't moving. This would totally prevent you from having the player speak in the background if you were using this other module.

Inversely, if the player is talking in the background but wants to start walking around, I don't think that should be blocked (hence talking in the background and not with a normal Say command).

Not to self-promote, but I'd really recommend that you check out the QueuedSpeech module. I think you'll find it much easier than recoding all of this by yourself.

Example of my module:

Code: ags
function room_Load()
{
  QueuedSpeech.ClearQueue(); // make sure we don't have any lingering items from other rooms
  QueuedSpeech.Paused = true; // don't start talking yet!
  // fill in the background dialogue only when the room is being loaded
  cbibl.SayQueued("asdas");
  cbibl.SayQueued("asdaf");
  // ...
  cbibl.SayQueued("asdaz");
}
 
function room_RepExec()
{
  QueuedSpeech.Paused = !BISTICCIO; // if BISTICCIO is TRUE, then the background dialogue will run, if BISTICCIO is FALSE then the background dialogue will pause
}


And that's all that you have to do to set it up. Animations will play and stop automatically, the player can talk in the background without blocking, etc.

rmonic79

thanks ;) the last time i tried to download the module it was unavaible so i tried only bgspeech but now works fine. :)

monkey0506

Yeah, the link in the first post was out-of-date, but I uploaded a new version a few days ago and updated the first post link as well.

Have you had a chance to test this, or were you only saying that the link was working?

rmonic79

i can't use vers. 4.0 because i'm still working on ags 3.3.0 and the link to queuedspeech 3.5  is unavaible, can you reupload it?

monkey0506

I sometimes forget that people have some innate fear of using pre-release versions. Unless you're very, very far along into your project, I would suggest upgrading to AGS 3.4. Make a back-up copy of your project folder first, then just open your game with 3.4. It's pretty reasonably stable lately, and we're starting to hone in on the final feature fixes for a full release.

That said, the links for the QueuedSpeech v3.5 module in the module's thread should still be valid, but you can snag it here. Note that v4 has a totally different way of doing things from v3.5, so the above code snippet won't work with older versions of the module.

rmonic79


Snarky


SMF spam blocked by CleanTalk