[3.4.0b2] Programming a custom Speech GUI, also using Tween Module

Started by LostTrainDude, Fri 08/07/2016 11:57:36

Previous topic - Next topic

LostTrainDude

I've been playing around, experimenting with the amazing Tween Module and I'm trying to create a custom Speech GUI that I'd like to see behave somewhat like this:

  • The actual GUI box should appear (rolling out, if you like) from the bottom to the top over the character's head, just like the LucasArts Speech does.
  • Other than the text wrapping, also the GUI Box's size should always be "aware" of the speaking character's position relatively to the screen, stretching to avoid going out of bounds
  • Could also be non-blocking
Is any of these unachieavable? The least important for me is the first one, anyway. I could easily discard it without problems and just have an instantly appearing GUI Box.

My own answers about the matter:

  • Maybe yes. I figured that you can only do the other way around, being the x=0 and y=0 "hardwired" to be placed at the top-left. I know how to place it over a character's head, at least (laugh)
  • Maybe not. Probably using the System.ViewportWidth and System.ViewportHeight, but I frankly have no clue about how to manage this properly (I suck at geometry!)
  • Maybe not. But maybe involves more, harder stuff like surfaces and timers
Does any of you have some solutions for these?
As always, thanks a million in advance!
"We do not stop playing because we grow old, we grow old because we stop playing."

Crimson Wizard

Unfortunately I do not have a time for detailed answer right now, but I will make following note.
None of these are unachievable, but you should be aware of general issues AGS currently have with custom speech system:
- It is more work to write dialogs, because you cannot make dialog scripts automatically call your own custom speech function, so you need to put normal function calls all time instead of simplier "EGO: Hello world" lines.
- You will have to find way to play the voice clips yourself if you want to use voice speech in your game (IIRC this becomes a real issue if speech is non blocking).

LostTrainDude

Thanks CW for the answer!

Quote from: Crimson Wizard on Fri 08/07/2016 12:19:10
- It is more work to write dialogs, because you cannot make dialog scripts automatically call your own custom speech function, so you need to put normal function calls all time instead of simplier "EGO: Hello world" lines.
I figured this a while ago, actually, especially reading other people's threads about the subject. As I discussed in a not-so-popular thread, what really bugs me are the dialog branches (switching on and off, mostly) rather than the actual lines. Or so I think, at least.

Quote from: Crimson Wizard on Fri 08/07/2016 12:19:10
- You will have to find way to play the voice clips yourself if you want to use voice speech in your game (IIRC this becomes a real issue if speech is non blocking).
This I didn't think about. And yes, it becomes difficult when using SayBackground which is non-blocking. In the upcoming talkie release of Fanbots I had to mix multiple tracks altogether to create situations in which more than one character is talking and play it with the AudioClip.Play() function. Not a big deal, but it can easily become one on a larger project with lots of non-blocking speech.
"We do not stop playing because we grow old, we grow old because we stop playing."

edmundito

Hi, this is quite a challenging question! It's not an easy thing to create, or to solve without really tryingg to do it, but here are some tips on how to get you there:

1. Think of the keyframes: Where does it start, where does it end?
2. Figure out how to code the end first, code a function that displays simple box on top of the character that roughly achieves what you are trying to do, without animation.
3. Try to think about how to resize it to fit the end result. Write a function that can resize the box when you call your custom speech function
4. Once you create that resized box, save all the data, rewind it to the start position and play the Tweens.

I followed a similar approach with Display2 in the Tween Module demo. If you download the source code and run the game in AGS, you may be able to see it by calling:

Code: ags
Display2('Hello world!');


https://raw.githubusercontent.com/edmundito/ags-tween/master/Tween/Display2.asc

Notice that the first call a function called _reflow, this is the function that resizes the window to fit the right size. You might be able to get some ideas on how to resize your box.
Finally, the rest of the code just rewinds to the start position, plays back the tween, controls the wait time, and then ends the tween.
The Tween Module now supports AGS 3.6.0!

LostTrainDude

You're right Edmundito: This is very close to the thing I want to achieve (I may have slightly changed my idea on how I want this to look like, in the meantime)!

Your code is very easy to read and indeed interesting. Actually I think I have never read a noloopcheck function before, I read the documentation about it but wanted to know: why did you use it? Is it for optimization purposes? I'm also curious about the fact that when you import it in the script header you can omit the noloopcheck from the import.

On my own I have been able to create a GUI that appears and animates at the given position, but I'm not quite there yet, as I need to solve the text wrapping issue whenever the speaking character is too close to the viewport's borders. I'm not sure whether it's my lack of math\trigonometry knowledge or something else :P

Thanks a lot!
"We do not stop playing because we grow old, we grow old because we stop playing."

edmundito

Depends on what you'd like to do. If you want to push the GUI so that it doesn't overlap the end of the room, once you get the position, you can ensure that it is never placed beyond the screen:

Code: ags

// Assuming that the target X position of the GUI is so that it's centered on the character:
// character screen X - half GUI width
int targetX = (cYourCharacter.X - GetViewportX()) - (gYourGui.Width / 2);

// If the GUI ends over the screen width, then set it to the screen with - the gui width.
if (targetX + gYourGui.Width > System.ScreenWidth) {
  targetX = System.ScreenWidth - gYourGui.Width;
}
// The gui is less than the screen width, set it to 0.
if (targetX < 0) {
  targetX = 0;
}
gYourGui.X = targetX;

// Another option is to use the ClampInt function that comes in the tween 2 module:
int targetX = (cYourCharacter.X - GetViewportX()) - (gYourGui.Width / 2);
targetX = TweenMaths.ClampInt(targetX, 0, System.ScreenWidth - gYourGui.Width);
gYourGui.X = targetX;


noloopcheck is there because my function does the dangerous thing of having a while loop that waits indefinitely until the user clicks. Probably not necessary to use because the limit is pretty high.
The Tween Module now supports AGS 3.6.0!

SMF spam blocked by CleanTalk