- A global config script to adjust the engine without having to dig into the code at all
- Control codes for changing text properties like color, speed, font, pauses, as well as position and size of the message box
- Automatic line breaks based on a maximum width and special characters like whitespace and commas
- Easy linking between message boxes and "speaker" instances, automatically updating the message box position
- Basic options for text sound
- Basic callbacks
- Profiles for keeping track of your instances properties (sound, speed etc.)
- Easily create your own skins or use one of the defaults:
Some more features I'd like to add are
- Support for different fonts in one message box
- Showing icons in text
- Loading from .csv files
- Answer options
At its core, textboxy utilizes an action queue
. You queue up different actions like showing strings, changing the position or speed and then execute them all in order.
The strings themselves can be modified using control codes
to adjust color, pauses and other effects.
A really basic queue would look like this:
tbyAddAction(TbyAction.SetPosition, 100, 100);
tbyAddAction(TbyAction.ShowString, "Hello world!");
tbyStart();
This would show a message box with the words "Hello world" at position 100, 100 (top-left corner of the message box).
You can see all available actions below.
Definition | Description | Example |
---|---|---|
SetMaxWidth(maxWidth:Number) |
Sets the maximum width before a line break is automatically inserted. |
// Sets the maximum width
// before a line break to 150 pixels
tbyAddAction(TbyAction.SetMaxWidth, 150); |
SetMaxLines(maxLines:Number) |
Sets the maximum number of lines in a given message box. (In a future version, this should split the message in two single messages, but for now, it just cuts the message off). |
// Message boxes are now
// at most two lines long
tbyAddAction(TbyAction.SetMaxLines, 2); |
SetFont(fontResource:Number) |
Sets the font for following messages. |
// Changes the font to fontBig
tbyAddAction(TbyAction.SetFont, fontBig); |
SetSpeed(speed:Number) |
Sets the speed for following messages. |
// Sets the speed to 5, meaning 5 steps
// pausing between drawing each character
tbyAddAction(TbyAction.SetSpeed, 5); |
SetOrigin(x:Number,
y:Number) |
Sets the message box origin (bottom middle of the message box, where the "bubble" sprite is located). |
// The following messages will be drawn
// with their origin at 100, 100
tbyAddAction(TbyAction.SetOrigin,
100, 100); |
SetPosition(x:Number,
y:Number) |
Sets the message box top-left corner manually. |
// The following messages will be drawn
// with their top-left corner at 10, 10
tbyAddAction(TbyAction.SetPosition,
10, 10); |
SetPause(frames:Number) |
Inserts a pause of x frames in the action queue. Most useful between messages. |
// Pauses for one second before executing
// the next action in the queue
tbyAddAction(TbyAction.SetPause,
room_speed); |
SetSpeaker(instId:Number) |
Binds the following messages to a speaker. The message will then follow the speaker instance. To reset, set to noone or overwrite with tbyActionSetOrigin() or tbyActionSetPosition(). |
// Sets the instance referenced
// in global.player as the speaker
tbyAddAction(TbyAction.SetSpeaker,
global.player); |
SetSound(soundResource:Number) |
Sets the message sound for the following messages. |
// Changes the sound to sndHighPitch
tbyAddAction(TbyAction.SetSound,
sndHighPitch); |
ShowString(message:String) |
Adds a message box. |
// Display the message box
tbyAddAction(TbyAction.ShowString,
"[j]Crazy!!!"); |
Shorthand | ||
tby(<optional>instId:Number,
<optional>speed:Number,
message:String) |
Shortcut to set a common message. |
// Sets speaker, speed and string
tby(id, 4, "First");
// Speaker and string carry over
tby("Second");
// Removes the speaker, speed is still 4
tby(noone, "Third");
// To adjust speed,
// speaker must be specified
tby(noone, 1, "Fourth"); |
tbyPause(frames:Number) |
Shortcut for setting a pause |
// Add a half second pause
tbyPause(room_speed/2); |
Other | ||
tbyStart() |
Starts execution of the current action queue |
tby("Hello");
...
tbyStart(); // Execution starts now |
tbyReset() |
Resets the textbox manager and removes any text instances |
tby("This will never be seen");
tbyReset();
tby("But this will!");
tbyStart(); |
tbyCreateProfile(instId:Number
<optional>sound:Number,
<optional>speed:Number) |
Returns a new profile array |
var oldManProfile =
tbyCreateProfile(
oldMan,
sndOldMan,
4) |
tbyProfile(profile:Array) |
Switches to the specified profile |
tby("Normal stuff");
tbyProfile(oldManProfile);
tby("Now I'm old...");
tbyStart(); |
You can customize the identifiers in the tbyConfig()
script.
Name | Default identifier | Description | Example |
---|---|---|---|
Color | [c/COLOR] |
Sets colors from the configuration | "[c/blue]I'm blue!" |
Wait | [.] |
Waits a set number of frames, can be stacked | A long[.....] pause. |
Jittery | [j] |
Makes the text jitter | Are you [j]crazy[r]?! |
Skip | [^] |
Skips to the next action | Wait,[.] let me fini-[..][^] |
Reset | [r] |
Resets to the default values | "[j][c/red]This is red and jittery.[.] [r]This is neither.[.] [c/blue]This is blue." |
These scripts get called every time the action is executed.
They are useful for a number of things, e.g. setting a pause state during dialogue.
Callback | Description |
---|---|
tbyOnMessageStart(speakerId:Number, message:String) |
Gets called when a new message is shown |
tbyOnMessageEnd() |
Gets called every time a message ends |
tbyOnQueueBegin() |
Gets called when an action queue is beginning |
tbyOnQueueFinish() |
Gets called when an action queue is finished |
Game Maker Studio 2 supports string literals
with @"string"
.
Using these, you can define line breaks without having to type \n
.
//Both of these produce the same output
tby(id, "Hello\nWorld!");
tby(id,
@"Hello
World!");
Assuming the instances player
and oldMan
.
var oldManSpeed = 6;
var playerSpeed = tbyWaitAfterEachChar; //this is the default speed defined in tbyConfig()
tby(player, playerSpeed,
@"Hello,[.] old man.[..]
Do you know where I can find the [c/red]hidden treasure[r]?");
tby(oldMan, oldManSpeed,
@"[j]Oooohhhhh[r],[.] it is the [c/red]hidden treasure[r]
you seek?[.] Good luck finding it,[.]
nobody knows where it is[.].[.].[.].");
tby(player, playerSpeed,
@"You have to know something!")
tbyPause(room_speed/2); //Half a second
tby("Please?") //speaker and speed carry over
tby(oldMan, oldManSpeed,
@"[j]OoooooOooohhh[r],[.] I am telling you,[.] no o-[...][^]")
tby(player, playerSpeed,
@"I get it,[.] you are no help either.");
tbyStart();
Continuing from the example above, again with the instances player
and oldMan
.
// It would make sense to have these as objects variables and addressing them
// from the instances, e.g. player.profile or something
var playerProfile = tbyProfileCreate(player, sndPlayer, tbyWaitAfterEachChar);
var oldManProfile = tbyProfileCreate(oldMan, sndOldMan, 6);
tbyProfile(playerProfile);
tby(
@"Hello,[.] old man.[..]
Do you know where I can find the [c/red]hidden treasure[r]?");
tbyProfile(oldManProfile);
tby(
@"[j]Oooohhhhh[r],[.] it is the [c/red]hidden treasure[r]
you seek?[.] Good luck finding it,[.]
nobody knows where it is[.].[.].[.].");
tbyProfile(playerProfile);
tby(
@"You have to know something!");
tbyPause(room_speed/2); //Half a second
tby("Please?"); //speaker and speed carry over
tbyProfile(oldManProfile);
tby("[j]OoooooOooohhh[r],[.] I am telling you,[.] no o-[...][^]"):
tbyProfile(playerProfile);
tby("I get it,[.] you are no help either.");
tbyStart();
// CREATE_EVENT
tby("This is an ongoing dialogue...");
tby("Still talking, man");
tby("You can take your time with advancing this, you know");
tbyStart();
alarm[0] = 60;
// ALARM_0
tbyReset();
tby(
@"After 60 steps, this box will now appear immediately,
even if something else was showing before!");
tbyStart();
Code snippets used: