2014-11-08 21:48:22

So I started trying to learn bgt again a day ago or so, and I want to know how to make a menu that uses a screen reader instead of sapi. I looked at the opensource projects Mason released like scrolling battles just to get ideas of how to do it, but it was really confusing. Can someone help me?

2014-11-09 01:13:14

Opensource? Where is the source of that game?

I post sounds I record to freesound. Click here to visit my freesound page
I usually post game recordings to anyaudio. Click here to visit my anyaudio page

2014-11-09 01:34:48

A small example:
// This is even going to check whether any of the four screen readers is running and set the menu output accordingly if one is found active.
// If not, Sapi is used instead.
// The existence of the DLL files for System Access and NVDA is not checked in any way.
// It's just a fast simple test example but it should work. I haven't tried to run it myself, so excuse me for compilation errors if there are any. Trying to find them should at least prove to be a good exercise for you. :-D

// Declare some global stuff first:
#include "dynamic_menu.bgt"
uint8 active_screen_reader=0; // The initial value of 0 means Sapi. This is going to store the screen reader that's found running in the system if any.
tts_voice sapi; // Will be used for output if no screen reader is present.
dynamic_menu menu;

void main()
{
show_game_window ("Menu test"); // Is needed for proper keyboard handling.
// Now, the most interesting part where the actual speech output mode is determined for the menu object.
for (uint8 x=1; x<5; x++)
if (screen_reader_is_running (x))
active_screen_reader=x;
menu.set_output_mode (active_screen_reader);
if (active_screen_reader == 0) // No screen reader was found and we are still using Sapi
menu.set_tts_object (sapi);
// Finally, run two test menus to demonstrate the results in practice.
testmenu1();
testmenu2();
alert ("Hurray!", "We have reached the end of the script. There is nothing else to do. Bye!");
}

void testmenu1()
{
menu.reset (false); // This is needed every time a new menu is to be created, if you want to use a single object for all the menus in your game, which is the easiest solution to keep track of. Like this, only the actual menu items will be removed from the object. If the boolean parameter in the function call was set to true, all the other settings for the menu object,including the speech mode etc. would be erased too.
// A very fast and neat way to add a bunch of items into the menu all at once and pretty easily if their exact text is known in advance.
string[] menu_items={"Hey there!", "How are you?", "I'm fine,", "Thank you."}; // See the array initialization lists section of the language tutorial for a description of this cool technique.
for (uint8 x=0; x<menu_items.length(); x++)
menu.add_item_tts (menu_items[x]); // This method must be used whenever adding an item that should be spoken using a screen reader or Sapi. So, this whole approach would have to be slightly modified to work for items using sounds.
menu.run_extended ("Here comes:", true, 1, true); // This declaration defines that the menu prompt is TTS (to be spoken with a screen reader or Sapi depending on the output mode) too, that the cursor should automatically be placed on the first item of the menu when the prompt is finished talking, and that the first item should also be read automatically right after the prompt. See the description of the run_extended method of the dynamic_menu include class under the helper layer object reference for more details.
// As none of the menu items has any associated behavior, no matter which one you choose in this menu, the script will always display the alert box at the end of the main function and exit right after you press enter in this menu.
}

void testmenu2()
{
menu.reset (false);
// This menu is going to be a bit more advanced. First, generate a list of several words, then determine how many items the menu is going to contain, and finally generate some text for each of the items using any of the words in the list randomly.
string[] words={"good", "morning", "afternoon", "evening", "night", "bye", "you", "how", "are", "there", "hello", "I'm fine", "thanks"};
uint8 item_count=random (3, 10);
for (uint8 x=1; x<=item_count; x++)
{
// First, determine the number of words the text for this item is going to consist of.
uint8 word_count=random (2, words.length() -1); // Remember that arrays are 0-based, so if you want something to be able to go all the way up to the last element but you want to prevent it from exceeding the upper boundary, always use the array length minus one.
string item_text; // This is going to store the dynamically generated text of the item in the end.
for (uint8 x=1; x<=word_count; x++)
{
item_text+=words[random (0, words.length() -1]);
// Add a space after the word unless this is the last one.
if (x < word_count)
item_text+=" ";
}
// The item text is fully generated now, so add it into the menu.
menu.add_item_tts (item_text);
}
// We have our menu. Run it now, performing different actions based on the item the user chooses this time: Display a specific message and exit immediately on the first item, play a sound and regenerate the menu on the second one, just start all over again on the third one, or say how many items the menu has and recreate it on any other item.
uint8 result=menu.run_extended ("Here comes:", true, 1, true); // This time, we need to know which item was chosen, so it has to be returned into a variable.
switch (result)
{
case 1:
alert ("Great!", "How do you like this so far?");
exit();
break;
case 2:
sound audio;
if (file_exists ("menusound.wav"))
{
audio.load ("menusound.wav");
audio.play_wait();
}
else
alert ("Error!", "The expected sound could not be found.");
testmenu2();
return;
case 3:
main();
return;
default:
alert ("All right:","The menu has " + menu.get_item_count() + " items.");
testmenu2();
return;
}
}

Hope this helps, and works... :-)
Lukas

I won't be using this account any more or participating in the forum activity through other childish means like creating an alternate account. I've asked for the account to be removed but I'm not sure if that's actually technically possible here. Just writing this for people to know that I won't be replying, posting new topics or checking private messages until the account is potentially removed.

2014-11-09 02:39:09

Hi,
@burak mason released a few open source projects that he is not coding anymore from back in the mtg studios days.
@lukas thanks, I'll try and run that and see if that works.