2014-11-02 00:59:32

Hi all,
Yes, I know there's the screen reader functions in BGT which I plan on using, with particular attention to the screen_reader_is_running function, as it'll look for any of the four readers if the reader parameter isn't specified.
However, instead of simply popping up an alert box if the screen reader isn't running, I want it to switch to Sapi. The most obvious way to do this, though counterproductive code whise, is to use the screen reader speak function and make two different versions of the same output. The Screen Reader Speak version and under it, the tts_speak version if screen reader running is false.
So, aside from the menus, is there a way I could have BGT read from a file and either TTS could be called if screen reader is false, or the other way around? You know, for story text, NPC conversation to the player, etc. Similar to how Paladin of the Sky does it.
I can support screen readers for individual text strings, because I read the language tutorial and the reffrence, but I suppose I can make individual files for each chapter or what have you, because if I make text files how can I make BGT read only certain things from it at certain parts based on location and other factors.
It's a sidescroller and I'll just make indevidual files for inclusion for gameplay, but I was looking at the screen reader function and was like, okay, I can make screen reader speak something individually, but what about if I wanted to make Sapi say the same thing without having to write the same text in the parameters of a different function.

2014-11-02 02:20:21

Sort of.
You want to write two functions.  InitializeSpeech, say, and speak.  Your InitializeSpeech function sets the flag, so that you're not constantly checking.  The speak function takes a string and speaks it based on the flag with a simple if statement.  This should do the trick, and it should only take 20 lines at most.

My Blog
Twitter: @ajhicks1992

2014-11-02 05:15:30 (edited by CAE_Jones 2014-11-02 05:16:19)

You could use something like this:
https://dl.dropboxusercontent.com/u/165 … _voice.bgt
That versions from 2011, though.
The version in here is newer, but has a (unfinished) word_speaker feature that in practice means it requires some of the other includes:
https://dl.dropboxusercontent.com/u/165 … cludes.zip
Or you could use someone else's. Speech_manager is one, I think.

Or, you could just do this:

tts_voice voice;
void speak(string text) {
for(uint i=1; i<=5; i++) {
if(screen_reader_is_running(i)) {
if(screen_reader_speak(i, text)) return;
}
}
voice.speak(text);
}

This has been done a few different ways, a few different times. You can probably find more if you search the blastbay forums.

看過來!
"If you want utopia but reality gives you Lovecraft, you don't give up, you carve your utopia out of the corpses of dead gods."
MaxAngor wrote:
    George... Don't do that.

2014-11-02 07:51:51

It's worth adding something in particular to this, because I think it applies generally and, in this case, is basically a giant spike through the middle of the conversation.
As some general rules that can make questions like this easier:
If you have a block of code repeated once, it may be a candidate for a function for code clarity, especially if long, but moving it will give you no net gain save for easier maintenance.  It is good to have many short functions (20 lines tops, 50 for rare exceptional bits) rather than few long ones.
if a block of code is repeated twice or more, it almost certainly should be in a function.  If the block of code is repeated twice exactly, is more than 2 or 3 lines, and performs some specific namable functionality, think hard before deciding not to give it a function.  Knowing when this is a good idea comes with practice, but I think a good rule of thumb is to ask yourself if you can put a comment before such blocks that says something like "computes the maximum of two integers", or similar.  You are likely to want to use such blocks for a third time later, or possibly even in a completely different project.
If the block is repeated three or more times,, think very very hard before not putting it in a function.  If the block is repeated four or more times or is repeated across multiple files, may the gods of programming smite you for your blasphemy.
To make these rules go even further, note that global state is bad.  Putting your global state inside a class is one of those brilliant ideas that costs almost nothing, and you can still create the class globally and use it globally if needed.  If you make sure all the related functionality is in the same file with the class, you can move it between projects instantaneously.  This isn't really object oriented programming; it's exploiting what I think of as the "alternate universe" feature of classes, and it's saved me so many times.  I'm not sure why so many people go into abstract perfection theory land when talking about classes, because this is one of those super obvious things that has an immediate and demonstrable benefit (OO is demonstrable, but not immediate).  Yet no one talks about it first.
And finally, for the most bang for your buck, most programmers have trouble with more than 3 levels of nesting (that is, open braces), and it's not linear.  Four might be okay for good programmers, five is going to require you to bend your brain when you look at it next week no matter who you are, 6 necessitates very, very explanatory comments, and I have never seen 7 anywhere ever.  This is mostly related to my first point--if you can break the function up into 3 smaller ones, it can cut down on this nesting, giving you easier to manipulate blocks.  You then replace the 50 lines of code in the original function with the 3 function calls, and everyone is much happier.  It's debatable whether you count the function's left brace  in this, and you'll eventually not need the rule, but it can certainly help manage things at first.  Yes, this can be taken too far, but trust me, you'll know.
Since this particular conversation was the perfect place to put this and the solution I proposed falls directly out of the above, I figured I'd give the reasoning process that leads to it.  Unlike much of programming, this is something that doesn't require huge amounts of experience to follow or understand.  I don't have to say "trust me, you'll get it once you've done it wrong", and that's really nice for a change.  If you follow this and find yourself deleting code or writing less than usual, you are doing it right.  Good programmers can and do add features by decreasing line counts.

My Blog
Twitter: @ajhicks1992

2014-11-03 01:19:45

I can't comment on the screen reader functionality as I've never used it, but I'll add this. You don't need to make individual files for each chapter of story text. If you don't want to deal with parsing a text file to find the part you need to speak, just put all of your text in to a dictionary, serialize it to a string and write that string to a file.
This makes your life nice and easy because then you can just deserialize it when your game loads, and when you need to speak a specific block of text you just look it up by name.

Official server host for vgstorm.com and developer of the Manamon 2 netplay server.
PSA: sending unsolicited PMs or emails to people you don't know asking them to buy you stuff is disrespectful. You'll just be ignored, so don't waste your time.

2014-11-03 01:58:40

But wouldn't that be editable only by a dedicated tool?  I guess the serialization format could be human-readable, but I think the point here is that he wants to separate content creation from programming.  Which is a superbly superb idea, even if it's harder for a few hours at the beginning.

My Blog
Twitter: @ajhicks1992

2014-11-03 03:28:04

It sounded like he was just trying to figure out a way to separate a file into parts or chapters so they could be spoken at the correct time.
I just saved a dictionary in BGT's native serialization format and then just used a quick and dirty tool to add, delete etc.

Official server host for vgstorm.com and developer of the Manamon 2 netplay server.
PSA: sending unsolicited PMs or emails to people you don't know asking them to buy you stuff is disrespectful. You'll just be ignored, so don't waste your time.