Simple textboxes for Game Maker Studio 2
Switch branches/tags
Clone or download

README.md

textboxy


Twitter | Marketplace

textboxy aims to be a simple to use textbox engine for GameMaker Studio 2.

Features

  • 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

Explanation

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.

Usage

Actions

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();

Control Codes

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."

Callbacks

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

Examples

String literals

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!");

Basic dialogue

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();

Profiles

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();

Resetting the queue

// 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();

Credits

Code snippets used: