Tag: GML

GML draw_text_rtf() script enables drawing of pseudo-rich text strings

When I was working on my recent blog post on string handling and text drawing in GML, I had the idea for a function that would draw formatted text. (You can read a paragraph in that post where I complained about how difficult this is to do using the built-in GML draw_text() functions.)

I posted a feature request to the official GameMaker bug tracking site (which recently closed its submission system and now works differently, by the way). And this spurred a discussion with some of the other users on the bugtracker. A user named Miah_84 came up with a script that very nearly did everything I wanted. I made a few modifications and cleaned up the code, and present it below.

The downside of this script is that it is very slow, as it makes numerous calls to the draw_text() function, which is itself very slow, and iterates over the raw rtf string several times in order to parse it. Running the demo project on my 2.0GHz Core 2 Duo laptop with discrete graphics, it only runs at around 200fps in debug mode. Comment out the call to the draw_text_rtf function, and the frame rate jumps to about 1100fps. The more formatting in the string, the slower the function will draw.

Still, combined with surfaces, this can be an extremely useful function for displaying text to the screen, in ways that was not possible previously using native GML functions.

Discussion thread on this script at http://www.gmlscripts.com/forums/viewtopic.php?pid=3358#p3358 — I expect that in the near future this will end up as an addition on GMLScripts.com, as well.

Download draw_text_rtf.gml.zip

Demo Project RTFDemo.gmz

GameMaker Tutorial: String handling and Drawing Text

[Editor’s note: This article was written primarily with GameMaker: Studio 1.x in mind. There have been some changes to the way GameMaker Studio 2 handles strings, mainly dealing with escaping codes, and this article has not yet been updated to reflect that. Refer to the official manual chapter on Strings for all the details.]

Drawing text to the screen is a basic part of most videogames. There are a huge number of useful applications for text. Just a few of the more common applications:

  1. Score
  2. HUD/Dashboard
  3. Menus
  4. Special effects
  5. Messages and dialogs
  6. Instructions/Story
  7. Debugging/diagnostics/benchmarking — it can be incredibly useful to draw the current value of variables to the screen when debugging, or performance metrics.

Things to know about drawing stuff in GameMaker

  1. Draw functions only work in Draw Events:  If you try to use them anywhere else, nothing happens. If you’re drawing in the Draw GUI Event, you’ll want to be familiar with the draw_set_gui_size() function so your Draw GUI stuff will be drawn to the proper scale if you’re using Views.
  2. Drawing directly to the screen (especially text) is slow. Draw a lot of text and performance will suffer.
  3. There are ways to improve performance when drawing text. The most important of these is to use Surfaces. Surfaces are not available in the free edition of GameMaker, and not all hardware may support them. Using surfaces properly is not that difficult once you understand them, but is generally considered to be an “advanced” concept in GameMaker, and is less straightforward than drawing directly to the screen in the “normal” way.
  4. But there are challenges. Setting up a Surface for optimizing text performance is tricky because it can be hard to know in advance how large the surface needs to be to contain the text you are drawing. Fortunately, GameMaker provides some useful functions which can enable you to get the dimensions needed for the surface: string_width() and string_height(), which give you the width and height, respectively, in pixels of a string drawn with draw_text() in the current font. If you’re using draw_text_ext() string_width_ext() and string_height_ext() are the functions to use instead. These functions allow you to create a drawing surface of proper dimensions, provided you know the string and font and can decide on a width prior to creating the surface. Keep in mind that the dimensions of a string depend on the font used to display it, so always use draw_set_font() to set the font to the correct one that you intend to draw the string with before using the measurement functions.
  5. Draw settings (for things such as color, alpha transparency, and font alignment) are global in GameMaker. That means that if you have multiple objects which draw functions, and if any of them changes the color, alpha, or font alignment, all objects will be drawn using those same settings. For this reason, if you are using draw functions in your objects, it’s best to set all the draw settings in the object in order to make sure they are what they need to be. If you never change color, or alpha, or font alignment, then you don’t need to set that property before you use draw functions — but if you do need to change them for one object, it’s best to set them to what they need in the Draw event of every object, immediately before calling the drawing routines.
  6. For serious performance optimization, you need to learn how GameMaker “batches” drawing operations, and organize your code to have the least number of drawing batches as possible.

Fonts

Everyone these days knows what fonts are, right? Fonts are like the clothes that text dresses up in when it wants to go out and be seen. In GameMaker, fonts are game resources, just like sprites, or objects, or other resources, and need to be added to the project — you don’t simply have direct access to the same fonts that are installed on the system, you have to explicitly add a font to your project. If your project has no font resources set up, text drawn to the screen will still render, but oddly and probably not consistently across platforms. So, always define a font resource and make sure that it’s used if you’re drawing text.

To save space, you can define a font resource to include only certain character ranges, such as number digits only, or alphabet characters only, or only the upper case or lower case letters in the alphabet. If you know you won’t be needing certain characters, and are concerned about the size of the game when it is built, go ahead and constrain the range. Otherwise, the default range of 37-128, covering A-z, 0-9, and special characters, is good.

For legal reasons, it’s important to note that fonts are copyrighted, and most need to be licensed for commercial use. There are free fonts out there (google for them) with liberal licensing terms that you may be able to use in your project, if the terms of the license allow.

Of course, you can create your own fonts. Creating your own font is outside the scope of this article, but there are tools you can use to produce your own fonts if you’re crazy enough. It’s probably easier to simply purchase a license for a professionally designed font.

Formatting issues

Alignment

Text alignment is set using the and draw_set_valign() functions. Use GameMaker’s built-in font align constants {fa_left, fa_center, fa_right, fa_top, fa_middle, fa_bottom} as arguments to these functions to keep the code readable.

New Lines

To signify a new line in a GML string, use the pound character (#). The GML code

draw_text(x, y, "Hello#World");

would be drawn like so:

Hello
World

You can also use a literal return in your string, but it’ll make your source code look yucky.

draw_text(x, y, "Hello
World");

Would draw to the screen exactly the same as “Hello#World”.

Escape characters

If you’re familiar with strings in programming languages, you know that it gets tricky when using certain characters that are reserved for program syntax or markup. Most languages allow you to “escape” the markup syntax so that you can still use characters normally reserved for markup purposes as literal characters in a string. GML is no exception.

#

What if you want to use a # in a string, and you don’t want it to signify a new line? Use the “#” escape character.

The string "We're \#1!" would be drawn like so:

We’re #1!

Quotes

A matched pair of quotes, single or double, can be used in GML to begin and end a string. If you want quotes to appear as text within a string, you can use the other type of quote to encapsulate them, like so:

my_string = 'This is a single-quoted string.';
my_string = "This is a double-quoted string.";
my_string = 'This is "an example" of a string including double quotes-as-text.';
my_string = "This is 'an example' of a string including single quotes-as-text.";

It gets tricky when you need to have BOTH types of quotes in the same sentence:

my_string = 'Bob said " We shouldn' + "'" + "t."+ '"' ; // Bob said "We shouldn't."

It looks like a mess, but you just have to do a lot of concatenation and quote your quotes with the other type of quote marks.

String concatenation

As with many languages, you can combine two strings together by adding them with the + operator. With number values + adds them; with strings, + concatenates the two strings together, creating a longer string made of the first one and second one stitched together. You can do this with literal string values, or with variables containing strings:

concatenated_string = string1 + string2;
concatenated_string = "Hello " + "World";

But if you try to add a string and a number, you need to tell the program to convert the number into a string. The string() function will convert numeric values to strings, which allows them to be incorporated into a larger string.

health = 100;
draw_string(x, y, "Player1 Health: " + string(health));

GML String functions

We’ve already introduced a few of the more commonly useful ones, but there are many other useful GML string functions. I’m not going to go into each one in depth, but review the official documentation and keep in mind that they’re out there, and can be useful.

One important thing to be aware of with GML strings is that, unlike most other languages, GML strings are 1-indexed, not 0-indexed. This means that when counting the characters that make up the string, the first character is character 1, not character 0.

GML text drawing functions

Mostly I have used draw_text() and draw_text_ext(), but it’s good to know that there are a few more variations on these basic text drawing functions.

  • draw_text
  • draw_text_color
  • draw_text_ext
  • draw_text_ext_color
  • draw_text_ext_transformed
  • draw_text_ext_transformed_color
  • draw_text_transformed
  • draw_text_transformed_color

It might seem like a lot to keep track of, but it’s pretty easy if you remember the following:

draw_text: basic draw text function.

_ext: allows you control over the line spacing and width of the draw area. This means you don’t have to manually handle line breaks by inserting # or return characters in your text.

_transformed: allows you to scale and rotate the drawn text.

_color: allows you to set a color gradient and alpha to the text.

Again, text is always drawn using the current global drawing color, alpha, halign and valign properties. It’s best to set these before drawing to ensure that they are the expected values, using draw_set_color, draw_set_alpha, draw_set_halign, and draw_set_valign functions.

Keep code clean by storing strings in variables

This is perhaps obvious, but it’s often useful to store a string value in a variable, to keep your code neater and easier to read.

draw_string(x, y, "Four score and seven years ago our fathers brought forth on this continent a new nation, conceived in liberty, and dedicated to the proposition that all men are created equal.##Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battlefield of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this.##But, in a larger sense, we can not dedicate, we can not consecrate, we can not hallow this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us—that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion—that we here highly resolve that these dead shall not have died in vain—that this nation, under God, shall have a new birth of freedom—and that government of the people, by the people, for the people, shall not perish from the earth.");

— is a lot harder to read than:

draw_string(x, y, gettysburg_address);

— and moreover, all that text gets in the way of comprehension of what your code is doing. So use variables to store strings, and keep your code looking clean.

draw_text_ext()

While we’re dealing with a very long string, it’s a good opportunity to talk about a function that makes drawing them much easier.

You could manually set line breaks in a long string by sprinkling #’s every N characters or so, but that is laborious and inflexible. It’s better to use the draw_text_ext() function, which allows you to specify a width for the line, and (optionally) also how many pixels should separate lines.

draw_text_ext(x, y, string, vertical_separation, width);

When drawn, the line will automatically break when it reaches the width provided to the function.

Formatting

GameMaker is rather limited in its typographical capability when drawing text to the screen. GameMaker Font resources, unlike an installed font on the system, are a specific size and style only. There’s no bold or italic or other style options available that you can use to modify the font resource. If you want bold or italic, you have to create a new font resource, and use draw_set_font(font) to that resource in order to use it.

This means that if you want to use bold text in a sentence, you need to create a second font resource for the bold font, draw your normal text, then switch fonts to the bold font, and draw the bold text, somehow positioning the two different drawings so that they look like they’re a single block of text. You have to leave a hole in your normal text where the bold word will appear. This is not easy, nor is it generally recommended. If you really want it, and are masochistic enough to put yourself through the trial and error to do it, go ahead. But before too long you’ll probably realize that it’s not worth the effort.

See this script draw_text_rtf which allows you to draw rich text format, originally written by Miah_84 and improved by me.

Special Effects

Scrolling text

Scrolling text is extremely easy to do. The draw_text function must be called by some object, and includes arguments for the x and y where the text will be drawn. Simply change the x and y over time, add you have moving text. The easiest thing to do is to set the instance that is drawing the text in motion.

Typewriter text

Another easy to implement technique is “typewriter text” — that is, displaying a string one character at a time as though it were being typed out.

First, let’s take a string stored in a variable, my_string.

string_length(my_string) will give you the length of my_string.

draw_text(x, y, my_string) would draw the entire string at once. But we want to draw it one letter at a time.

The GML function string_copy(string, index, length) comes in handy here. We can use this instead of string in our draw_text function:

//In the Create Event
typed_letters = 0;
//In the Draw Event
draw_text(x, y, string_copy(my_string, 0, typed_letters);
if (typed_letters < string_length(my_string)) {typed_letters++};

Note that this will type at room_speed characters per second, which at 30 fps is extremely fast. You may want to type slower, in which case you can slow down the function in one of several ways. You can use an alarm to increment typed_letters every N steps, rather than increment it in the Draw event. Or you don’t want to bother with an Alarm event, you could do something like this:

//In the Draw Event
if typed_letters < length {typed_letters+=0.1;}
draw_text(x, y, string_copy(my_string, 0, ceil(typed_letters)));

This would give a typing speed of room_speed/10, or 1 character roughly every 0.33 seconds for a 30 fps room, or 3 characters/second, which is a bit more reasonable. You can adjust this rate to taste.

If you want the text to reset and type over again when the message is completed, you can do this:

if typed_letters < length {typed_letters+=0.1;} else {typed_letters = 0;}

Additionally, you can optionally add code to play a sound with each letter, or start a sound when the typing starts and stop the sound with the full length string has been reached.

Marquee text

The Typewriter Text technique can be modified slightly to draw a scrolling marquee:

//In the Create Event
/*Hint: you may want to pad the end of your marquee string with extra spaces so it 
will scroll all the way off your marquee.*/
my_string = "Some text for your marquee "
start_letter = 0;
marquee_length = 10; // or however many letters in your marquee
type_rate = 3/room_speed; // 3 char per second
marquee_scrolling = true;
//In the Draw Event
if marquee_scrolling{
 draw_text(x, y, string_copy(my_string, start_letter, ceil(start_letter + marquee_length)));
 start_letter += type_rate;
 if (start_letter > string_length(my_string)) start_letter = 0;
}

Blinking text

Blinking is annoying in web pages, but can be a very useful effect in games. Blinking attracts the eye, and can get attention where it’s needed. Of course, blinking can be done with any graphical element, not just text.

Blinking is just turning on the drawing and then turning it off on a cycle, using a timer, such as an Alarm Event.

//In the Create Event
blink = true; //(or false, if you want the initial state to be off)
blink_steps = room_speed/2; //for a 1 second blink cycle. Set this value to suit.
//In the Alarm[0] Event
blink = !blink; //toggles the blink from on to off or vice versa.
alarm[0] = blink_steps; //re-sets the alarm so it keeps blinking
//In the Draw Event
if blink {/*do the draw stuff*/}

The above code gives a 50% “duty cycle” (the blink is “on” 50% of the time, “off” 50% of the time). It’s possible to vary the duty cycle in a variety of interesting ways…

//In the Create Event
blink = true; //(or false, if you want the initial state to be off)
blink_on_steps = room_speed/2;
blink_off_steps = room_speed/4;
//In Alarm[0]
if blink {alarm[0] = on_steps;} else {alarm[0] = off_steps;}
blink = !blink;

This blink code will result in a blink that stays on for 0.5 seconds, and blinks off for 0.25 seconds.

Even more sophisticated blink periods can be achieved using math functions rather than a static value. Setting alarm[0] = irandom(10) would result in a random flicker. Think of creative ways to use other math functions to create interesting effects. If you come up with a good one, share your code by posting a comment to this article.

Yet another way to flicker or blink text is through varying alpha. Or by switching colors. Or even size.

One last way to blink is to toggle the state of the visible boolean in the instance.

visible = !visible;

One thing to keep in mind, though, is that an instance that is not visible will not be checked for collisions. Also visible applies to the entire object’s Draw event, so it is all or nothing. Still it is a simple way to draw or not draw an object.

What next?

If you’re familiar with other programming languages, you may be disappointed at the limits of the built-in functions for manipulating strings. There are a lot of things you can do more easily in other languages than in GML, unfortunately. Since GML only has two data types, strings are extremely important, but because games tend to focus more on graphics, sound, and interface, the average GameMaker developer can get by with the string functions that do exist, for the most part.

There are a number of useful GML scripts for doing more advanced things with strings that have been collected at gmlscripts.com. Many of the functions built in to more mainstream programming languages can be found there.

GameMaker tutorial: Elegant instance_change() in your state machine

In GameMaker, a commonly used technique is to build a system made up of a several objects to represent an entity in your game, such as the player or enemy, in various states, such as idle, dead, shooting, jumping, running, climbing, and so forth. This is what is known as a Finite State Machine pattern.

When the time is right in the game, we change an instance from one state object to another by using the powerful instance_change() function. Instance_change() takes the instance and transforms it into a new type of object. Its Event behaviors will change to those defined by the new object type, but its old properties (object variables) will remain the same as before, allowing the instance to retain its variables with their current values.

The instance_change() function takes two arguments: object, the object the instance will turn into, and perform_events, a boolean which controls whether the new object’s Create event will be performed or not.

Normally, the Create event is where an object initializes its variables and initiates its default behavior. When we’re dealing with a State Machine comprised of a number of objects, this can become problematic, however. Some code in the Create Event is initialization code that we may only want to execute one time, to set up the instance when a brand new instance is created, while other code in the Create event is behavioral and we may need to execute whenever an existing instance reverts back into that state again. Thus, the perform_events argument in the instance_change() function isn’t adequate for this situation — it’s too all or nothing.

For example, let’s say I have a generic object for an enemy, oEnemy. I want some visual variety to this enemy, so I’ve created a few different sprites for it. In the Create Event, I want to randomly choose one of those sprites to be the sprite for this instance. But if the instance changes into another state object, and then reverts back, if I call the Create Event, it will randomly choose a new sprite. I don’t want this, as it ruins the illusion of continuity — I need that instance to retain its sprite. But I do need the Create Event to run, whenever it re-enters this state, because I’m using it to set the instance in motion.

So, how can I elegantly select which lines of code I want to run in the Create Event?

Conditional blocks

This is the least elegant solution, but you could use if to check whether a variable exists or has a value. For example:

if sprite_index == -1 {sprite_index = choose(sprite1, sprite2, sprite3);}

This is inelegant because it adds lots of lines of code that only need to be run one time (when a brand new instance is created) but need to be checked potentially many times (any time that instance changes back into the object state). It also only checks certain, specific things, case by case. As I continue to build the state machine, I may end up introducing more features which require initialization, which would necessitate more checks, further bloating the code. I always want to write the least amount of code needed, both for reasons of performance and maintainability.

Move one-time code to an init state object.

The more elegant solution is to recognize that initialization is its own state, and we need to separate it out from the other states in the state machine. We can create an oEnemy_init object, put our one-time initialization code into it, and then the final step in the Create Event for the init object would be to change the object into the default state.

None of the other states in the state machine should put the instance back into the init state, thereby guaranteeing that the init code only executes once. Now your code is neatly separated, your states objects in your state machine are as simple as can be.

Tutorial: Building a Game Maker Extension

[Update 1/13/2014: See the official GameMaker documentation and this MSDN blog entry for how to build GM Extensions directly inside of GM:Studio. The GM Extension Builder tool that I explain how to use in this article will build GEX that can work with GM 7, 8, 8.1, and GM:Studio. As long as the GML used in the extension is compatible with the version of GameMaker that the extension is added to, the extension should work. ]

One of the nice things about Game Maker is that it is extensible. Developers can make their code more re-usable by converting their GML scripts to Game Maker Extensions. Once the .gml code is packaged in a .gex extension, you can import the extension into Game Maker and use the functions it provides in any project with ease. This means over time you can build up an entire library of re-usable functions that you can bring into your projects, saving you time and allowing you to focus on building new stuff instead of re-implementing the same basic things again and again. (more…)

4 quick GML coding tips

When writing scripts in Game Maker Language projects, I have come to realize a couple things that I want to share for anyone else who might be working on GML projects:

GML parsing is a bit loose. This makes the language fault tolerant, which is nice for newbie programmers who don’t need to get beaten up for not following strict syntax. But by enabling you to get away with imprecise syntax, it lets you get in to trouble that isn’t easy to detect.

Strict syntax is your friend, if you have it as an option in the language you’re using, I recommend following it as soon as you’re comfortable. Strive to get comfortable as quickly as possible. Unfortunately, GML does not have a strict mode…so I have the following tips to offer:

  1. Scripts (sometimes referred to as “programs” in the official Game Maker documentation) are supposed to begin and end with curly braces. The interpreter is forgiving if you don’t do this. But you should always do it.
  2. GML terminates statements with a semi-colon. The semi-colon is semi-optional, but I recommend using them wherever you intend a line of code to end, so that the interpreter doesn’t have to do extra work guessing that for you. Doing so will make it look like you know Pascal, C, or Java more than you know VB, which is enough reason to do it;) (Usually a statement is more or less the same thing as a line of code in your script file, but some structures may incorporate blocks of code, such as loops or branches.)
  3. Strings in GML can include line break characters (there’s no escaping with \n or using a character code like CRLF, like there is in most languages), so if you want to have a string with a line break in it, you simply hit the enter key and put a literal line break in your string. The interpreter handles this OK since the string is bounded by double or single quotes, but it’s still a weird thing about the language that they don’t really explain adequately in the documentation. If you’re not using semi-colons where you intend to end a line, it can get confusing to look at a multi-line string declaration that incorporates the line break as part of the string.
  4. It’s easy to not scope your variables appropriately without realizing it. GML allows global vars, and has two kinds of locality: locality with respect to an instance of an object, and locality with respect to a script. You shouldn’t use globals unless you really need to; according to the language doc they are slower to access than local variables. I haven’t noticed any difference that I can measure, but I’m sure that it is something that adds up, and at any rate proper scoping is a good habit to get into.When I refactored my project to pull drag-n-drop code out and replace it with scripts that were more re-usable, this caused some of my instance variables to turn into script variables. I had to go back and turn them into instance variables once I discovered that this had happened, and caused some issues with the way the code was executed by the interpreter.If you’re using variables in a script that were not declared in the object somewhere (normally the best place for this is in the object’s create() event), and you are declaring the variable in the script, but you want to make it an instance-local variable, you can do so. The code to do this is:

    obj_MyObject.MyLocalInstanceVar

    That dot between obj_MyObject and MyLocalInstanceVar is actually an operator. Knowing this is nifty, but I am not prepared to expound on why just yet.

Keep reading the language specification doc! Every time I go back to it and read, I pick up something I didn’t know, or refine something I thought I knew. One of the really nice things about GML is that it’s a small enough language that you can pick it up and do things with the basic features right away, without needing or being overwhelmed by all the other stuff that you’ll discover as you continue to progress as a developer. And there are enough built-in features in GML that you don’t have to spend a lot of time figuring out how to build sophisticated stuff out of primitives all by yourself.

The more I work in GML, the more respect and appreciation I gain for it. It is not the purest language, nor is it the most powerful, nor is the development environment as rich and sophisticated as a “serious” IDE like Visual Studio or Eclipse, but it is extremely accessible for a non-programmer to pick up and start working with and being effective quickly.

Yummy GameMaker Goodness…

Good technical documentation is a beautiful, beautiful thing. Almost as good as bug-free code.

Ultimate DdD to GML Converter

It occurred to me recently that my Actions could be easier to understand and debug if I refactored to convert as much of it from Drag-and-Drop actions into GML scripts. It’s a LOT easier to understand a script call to “Player_Eats_Fish” than it is to read a dozen or more DnD actions that do “Player Eats Fish” and figure out what they’re doing. Plus, you can call the scripts elsewhere if you need to.

So I started doing this, and realized that there were certain things that I didn’t know how to do. Reading the language reference in the GameMaker Help helped, but at times I still got confused… Then I googled and found this. UDnD2GML does a nice job of converting Drag and Drop actions into valid and correct GML. It’s actually written in GameMaker, too; that’s right, it’s a GameMaker project that converts GameMaker drag-n-drop actions into GML. Very slick! When you need to work out a bit of tricky syntax, or are dealing with some function you don’t use a whole lot, it’s indespensible.

Drag and Drop Icons and Their GML Equivalents for Version 7.0

Basically the same thing, only a big hypertext reference document. I liked it so much, I printed it to PDF format and am keeping it with my other GameMaker docs. Although this is for GML7, there doesn’t seem to be a whole lot that has changed in GML8. Could be a bit clearer in places, and incomplete in some regards (I had to use UDND2GML to figure out how to apply instance_destroy() to other; this document was silent on that point.)

Official GameMaker 8 Help File as a PDF

Not hard to find by any means, but if you don’t have it, it’s the best place to start. A lot nicer than searching through the Help Menu index.