Animation Text Reveal - Advanced Typewriter

L

L0v3

Guest
GM Version: Studio v1.4.1750
Target Platform: ALL
Download:N/A
Links: N/A

Summary:

Animates a draw_text_ext with a typewriter, alpha and color transition effect for individual chars.
This causes an effect similar to what you see in this video:



Tutorial:

To implement this into your project, simply import given scripts and objects then use it like so:

Code:
animation = animation_text_reveal(false, 0, room_seconds(8), 0.2, 0.05, 0.025, c_red, c_white, fnt_arial_68_b, fa_center, fa_middle, room_width / 2, room_height / 2 - 50, "DSEngine#Text Animation Effect", 100, room_width);

It's a fire once and forget animation. If you wish to manipulate it, you can use the user_defined events 0, 1, 3, 5 to pause, unpause, start fadeout and show all text immedieatly. Useful for implementation in systems such as a dialogue engine.

Code:
with (animation)
{
    event_user(0); //Pauses animation.
}

with (animation)
{
    event_user(1); //Resumes animation.
}

with (animation)
{
    event_user(3); //Starts fadeout.
}

with (animation)
{
    event_user(5); //Shows all text.
}

Here is all the associated code you need to copy into your game:

Code:
///animation_text_reveal(gui, depth, duration, tspd, cspd, aspd, color1, color2, font, halign, valign, x, y, string, sep, width);

// Animates a draw_text_ext with a typewriter, alpha and color transition effect for individual chars.
// Returns the animation engine object, which can be manipulated by calling it's user_defined events to
// pause, unpause, start fadeout or show all text immedieatly.
// Use -1 as duration to have it last forever or until destroyed manually or upon room end.

// gui              = Boolean if draw_gui should be used (True) or normal draw event (False).
// depth            = Drawing depth to be used.
// duration         = Total duration for text in steps. -1 to last forever.
// tspd             = Speed of the text reveal typewriter effect in characters per step.
// cspd             = Speed of the color transition effect in decimals per step.
// aspd             = Speed of the alpha transition effect in decimals per step.
// color1           = Initial starting color of text. Usually short for cinematic effect.
// color2           = Final end color of text. Resting color once animation complete.
// font             = Font resource to be used for drawing.
// halign           = The horizontal drawing alignment for drawing.
// valign           = The vertical drawin alignment for drawing.
// x                = The x coordinate of the drawn string.
// y                = The y coordinate of the drawn string.
// string           = The string to draw.
// sep              = The distance in pixels between lines of text.
// width            = The maximum width in pixels of the string before a line break.

// Dependencies: eng_animation_text_reveal, string_array_page_parser

// @Return: Instance of eng_animation_text_reveal.

//Converts arguments to locals.
var gui = argument0;
var draw_depth = argument1;
var duration = argument2;
var tspd = argument3;
var cspd = argument4;
var aspd = argument5;
var color1 = argument6;
var color2 = argument7;
var font = argument8;
var halign = argument9;
var valign = argument10;
var xx = argument11;
var yy = argument12;
var text = argument13;
var sep = argument14;
var width = argument15;

//Creates engine object.
var obj = instance_create(xx, yy, eng_animation_text_reveal);

//Sends over variables.
with (obj)
{
    depth = draw_depth;
    self.gui = gui;
    self.duration = duration;
    self.tspd = tspd;
    self.cspd = cspd;
    self.aspd = aspd;
    self.color1 = color1;
    self.color2 = color2;
    self.font = font;
    self.halign = halign;
    self.valign = valign;
    self.xx = xx;
    self.yy = yy;
    self.text = text;
    self.sep = sep;
    self.width = width;
}

//Delayed creation code.
with (obj)
{
    event_user(2);
}

//Returns object.
return obj;

Code:
///string_array_page_parser(string, array, width, height, font, halign, valign, [sep])

// Parses the given string into an array. Each index in the array will contain all associated text for the page.
// Note: Array should be empty as will overwrite any elements in it. Index 0 will contain the first page, and so on.
// Returns the total amount of pages in the array.

// string           = String to be parsed and stored into the array.
// array            = Array for string to be stored in.
// width            = Maximum width of the string, before a new line is to be created.
// height           = Maximum height of a page, before a new page is to be created.
// font             = Font to do calculations with. Should be same as potiental draw font.
// halign           = Horizontal alignment to do drawing calcuations with.
// valign           = Vertical alignment to do drawing calcuations with.
// sep              = Optional argument. Distance between new lines of text. Default font size / 2.

// @Return: Amount of pages that have been created.

//Converts arguments to locals.
var text = argument[0];
var array = argument[1];
var page_width = argument[2];
var page_height = argument[3];
var font = argument[4];
var halign = argument[5];
var valign = argument[6];
var sep = font_get_size(font) / 2;

//Optional Arguments
if (argument_count = 8)
{
    sep = argument[7]
}

//Setups variables for loop.
draw_set_font(font);
draw_set_halign(halign);
draw_set_valign(valign);
var current = 1;
var total = 1;
var length = string_length(text) + 1;
var page_count = 0;

//Enters a loop for each letter.
while (total < length)
{  
    //Makes a copy for current page.
    var copy = string_copy(text, 1, current);
 
    //Stores the page.
    array[@page_count] = copy;
 
    //Checks for line break.
    if (string_char_at(copy, current) = "#" and string_char_at(copy, current-1) != "\")
    {
        //Clears the main text string, to calculate for new page.
        text = string_delete(text, 1, current);
        current = 0;
     
        //Increments Page Count.
        page_count += 1;
    }
 
    //Calcuates the height of current copy.
    var height = string_height_ext(copy, sep, page_width);
 
    //Checks to see if new page.
    if (height >= page_height)
    {                  
        //Checks ahead for word completion.
        var skip = 0;
        for (var i = current; i < length; i++)
        {
            //Checks for space.
            if (string_char_at(text, i) = " ")
            {
                skip = i;
                break;
            }
        }

        //If word completion ahead.
        if (skip != 0)
        {
            //Checks behind for word start.
            var start = 0;
            for (var i = current; i > 1; i--)
            {
                //Checks for space.
                if (string_char_at(text, i) = " ")
                {
                    start = i;
                    break;
                }
            }
         
            //Checks if word start.
            if (start != 0)
            {
                //Updates copy for current page.
                copy = string_copy(text, 1, start);
                array[@page_count] = copy;
            }
        }
     
        //Decrements Strings.
        var delta = start - current;
        current += delta;
        total += delta;
     
        //Clears the main text string, to calculate for new page.
        text = string_delete(text, 1, current);
        current = 0;
     
        //Increments Page Count.
        page_count += 1;
    }
 
    //Increments Strings.
    current += 1;
    total += 1;
}

//Returns final page count.
return page_count;

Code:
Information about object: eng_animation_text_reveal
Sprite:
Solid: false
Visible: true
Depth: 0
Persistent: false
Parent:
Children:
Mask:
No Physics Object
Create Event:
execute code:

///Creation Code

//Data Variables
gui = noone;
duration = noone;
tspd = noone;
cspd = noone;
aspd = noone;
color1 = noone;
color2 = noone;
font = noone;
halign = noone;
valign = noone;
xx = noone;
yy = noone;
text = noone;
sep = noone;
width = noone;

//Instance Variables
chars = ds_list_create();
lines[0] = noone;
hoffset = noone;
voffset = noone;
fadeout = false;
paused = false;
total = 0;
count = 0;
step = 0;
line = 0;

Destroy Event:
execute code:

///Cleans-Up Leaks
for (var i = 0; i < ds_list_size(chars); i++)
{
    var data = ds_list_find_value(chars, i);
    ds_list_destroy(data);
}
ds_list_destroy(chars);

Step Event:
execute code:

///Animation Update

//Checks if paused.
if (paused) exit;

//Typewriter Effect
if (count < string_length(text))
{
    //Increments count.
    count += tspd;
    total = clamp(ceil(count), 0, ds_list_size(chars));
}

//Color Effect
for (var i = 0; i < total; i++)
{
    //Updates color value for char.
    var data = ds_list_find_value(chars, i);
    var color = ds_list_find_value(data, 0);
    color = clamp(color + cspd, 0, 1);
    ds_list_replace(data, 0, color);
}

//Alpha Effect
for (var i = 0; i < total; i++)
{
    //Checks for fadeout.
    if (!fadeout)
    {
        //Updates alpha value for char.
        var data = ds_list_find_value(chars, i);
        var alpha = ds_list_find_value(data, 1);
        alpha = clamp(alpha + aspd, 0, 1);
        ds_list_replace(data, 1, alpha);
    }
}

//Checks if infinite duration.
if (duration = -1) exit;

//Increments step for alarm.
step++;

//Check for fadeout start.
if (!fadeout and step > fadeout_start)
{
    fadeout = true;
}

//Checks if fadeout.
if (fadeout)
{
    //Fadeout Alpha Effect
    for (var i = 0; i < ds_list_size(chars); i++)
    {
        //Updates alpha value for char.
        var data = ds_list_find_value(chars, i);
        var alpha = ds_list_find_value(data, 1);
        alpha = clamp(alpha - aspd, 0, 1);
        ds_list_replace(data, 1, alpha);
    }
 
    //Check for fadeout complete.
    if (step = duration)
    {
        //Suicide
        instance_destroy();
    }
}

Other Event: Room End:
execute code:

///Calls Destroy Event
instance_destroy();

Other Event: User Defined 0:
execute code:

///Pauses Animation
paused = true;

Other Event: User Defined 1:
execute code:

///Resumes Animation
paused = false;

Other Event: User Defined 2:
execute code:

///Delayed Creation Code

//Calculates fadeout start.
if (duration != -1)
{
    fadeout_start = duration - (1 / aspd);
}

//Setup line array.
draw_set_font(font);
var height = string_height("Height String") + 1;
string_array_page_parser(text, lines, width, height, font, halign, valign, sep);

//Enters a loop for each line.
for (var i1 = 0; i1 < array_length_1d(lines); i1++)
{
    //Determines offset for line.
    line = i1;
    event_user(4);
    var line_width = 0;
 
    //Enters a loop for each char.
    for (var i2 = 1; i2 < string_length(lines[i1]) + 1; i2++)
    {
        //Determins variables.
        var char = string_char_at(lines[i1], i2);
        var x1 = xx - hoffset + line_width;
        var y1 = yy - voffset + sep * i1;
     
        //Creates character data.
        var data = ds_list_create();
        ds_list_add(data, 0); //Color
        ds_list_add(data, 0); //Alpha
        ds_list_add(data, char); //Char
        ds_list_add(data, x1); //x-pos
        ds_list_add(data, y1); //y-pos
     
        //Updates variables.
        ds_list_add(chars, data);
        line_width += string_width(char);
    }

}

Other Event: User Defined 3:
execute code:

///Starts Fadeout

//Checks if infinite duration.
if (duration = -1) exit;

//Updates variables.
fadeout = true;
step = fadeout_start;

Other Event: User Defined 4:
execute code:

///Updates offset for line.

//Setups drawing font.
draw_set_font(font);

//Determines the line.
var line_text = lines[line];

//Determines horizontal alignment offset.
switch (halign)
{
    case fa_left:
        hoffset = 0;
        break;
     
    case fa_center:
        hoffset = string_width_ext(line_text, sep, width) / 2;
        break;
     
    case fa_right:
        hoffset = string_width_ext(line_text, sep, width);
        break;
}

//Determines vertical alignment offset.
switch (valign)
{
    case fa_top:
        voffset = 0;
        break;
     
    case fa_middle:
        voffset = string_height_ext(text, sep, width) / 2;
        break;
     
    case fa_bottom:
        voffset = string_height_ext(text, sep, width);
        break;
}

Other Event: User Defined 5:
execute code:

///Show all text.

//Skips to the end and shows all text, but does not start the fadeout.

//Color Effect
for (var i = 0; i < ds_list_size(chars); i++)
{
    //Updates color value for char.
    var data = ds_list_find_value(chars, i);
    var color = ds_list_find_value(data, 0);
    color = 1;
    ds_list_replace(data, 0, color);
}

//Alpha Effect
for (var i = 0; i < ds_list_size(chars); i++)
{
    //Checks for fadeout.
    if (!fadeout)
    {
        //Updates alpha value for char.
        var data = ds_list_find_value(chars, i);
        var alpha = ds_list_find_value(data, 1);
        alpha = 1;
        ds_list_replace(data, 1, alpha);
    }
}

Draw Event:
execute code:

///Handles Drawing

//Checks if correct draw event.
if (gui) exit;

//Setups drawing.
draw_set_font(font);
draw_set_halign(fa_left);
draw_set_valign(fa_top);

//Enters a loop for each character.
for (var i = 0; i < ds_list_size(chars); i++)
{
    //Retrives the char data.
    var data = ds_list_find_value(chars, i);
    var color = ds_list_find_value(data, 0);
    var alpha = ds_list_find_value(data, 1);
    var char = ds_list_find_value(data, 2);
    var x1 = ds_list_find_value(data, 3);
    var y1 = ds_list_find_value(data, 4);
 
    //Setups drawing.
    draw_set_color(merge_color(color1, color2, color));
    draw_set_alpha(alpha);
 
    //Draws character.
    draw_text(x1, y1, char);
}

//Resets drawing alpha.
draw_set_alpha(1);

Draw GUI Event:
execute code:

///Handles Drawing

//Checks if correct draw event.
if (!gui) exit;

//Setups drawing.
draw_set_font(font);
draw_set_halign(fa_left);
draw_set_valign(fa_top);

//Enters a loop for each character.
for (var i = 0; i < ds_list_size(chars); i++)
{
    //Retrives the char data.
    var data = ds_list_find_value(chars, i);
    var color = ds_list_find_value(data, 0);
    var alpha = ds_list_find_value(data, 1);
    var char = ds_list_find_value(data, 2);
    var x1 = ds_list_find_value(data, 3);
    var y1 = ds_list_find_value(data, 4);
 
    //Setups drawing.
    draw_set_color(merge_color(color1, color2, color));
    draw_set_alpha(alpha);
 
    //Draws character.
    draw_text(x1, y1, char);
}

//Resets drawing alpha.
draw_set_alpha(1);
 
Top