GML Coding Fundamentals in GML Tutorial Series

samspade

Member
GM Version: GMS 2.2.5 and 2.3
Target Platform: All
Download: Github Repository 2.2 and Github Repository 2.3
Links: YouTube Playlist

Summary:
A GML tutorial series focused on the basics of coding in (unsurprisingly) GML. It is updated for 2.3 (almost). All of the videos will be posted below but here are links to various playlists from the series:
Introduction:

Tutorial:

 
Last edited:

FrostyCat

Redemption Seeker
Some suggestions:
  • DO NOT use curly/smart quotes in code. The compiler won't recognize these as string delimiters.
  • Collapse or reduce the height of the output console. It may get in your way for future tutorials that have more code at once.
  • Increase the font size in the code editor.
  • For this tutorial, I recommend also demonstrating what happens if you mistype a variable name, say cut out or change a character in the variable name. This is another common cause of "variable not set" errors that rookies complain about on the Q&A.
 

samspade

Member
Some suggestions:
  • DO NOT use curly/smart quotes in code. The compiler won't recognize these as string delimiters.
  • Collapse or reduce the height of the output console. It may get in your way for future tutorials that have more code at once.
  • Increase the font size in the code editor.
  • For this tutorial, I recommend also demonstrating what happens if you mistype a variable name, say cut out or change a character in the variable name. This is another common cause of "variable not set" errors that rookies complain about on the Q&A.
Thanks for the comments. I'll start re-recording the videos once I get a better recording set up and implement these changes then. I've made notes in the slides (although the smart quotes note will get added to the data type tutorial and I'll just make sure not to demonstrate it wrong in variables basics).
 

Yal

šŸ§ *penguin noises*
GMC Elder
Collapse or reduce the height of the output console. It may get in your way for future tutorials that have more code at once.
To add onto this suggestion: pull the output console into a dock on the left or right side, mentioning how you can move the tabs around to suit your workflow... and then later point out how the new vertical layout lets you see much more output at once (which is useful if there's an error, because the error text is usually buried under a dozen or so bookkeeping lines like "not stopping steam since it's not started" - if you don't need to scroll to find the error, it's more painless to fix it).

(This works really well with Frosty's other suggestion about showing what happens if you mistype a variable name, since now you have an error to show off!)
 

samspade

Member
Code Style:


This finishes up the group of subjects I had prepared, so it'll probably be next weekend by the time I put more up. As always, let me know what you think, what things could be improved, if you have questions and so on. My guess is that I will do one more batch and then probably redo some of the earlier videos.
 

FrostyCat

Redemption Seeker
Congratulations on your induction into the offical Learn pages. Hopefully rookies won't overlook them for not doing anything flashy or holding their hand on their "dream game".

I have taken a look at the videos you posted since the turn of the year. Here is my opinion on the finer points of each topic:

Data Types
  • enums are actually not a distinct type in GMS 2, just an additional syntax for declaring 64-bit integer constants. If you use typeof() on any enum value, you get int64.
  • Hexadecimals are actually just the literal syntax for int64, again not a distinct type. The actual type is 64-bit integer (int64).
  • It may be helpful to note common sources of non-acceptable quotes for strings, such as rich-text word processors (e.g. Word), copy-and-pastes from PDFs that have not been sufficiently reviewed, or typing aids and IDEs designed for natural language.
  • There is a rift between "fake" Booleans and "genuine" Booleans in GMS 2, which gets unmasked when typeof() and is_bool() are used on them. You can read more about it here and here. This issue won't affect rookies much, but will start becoming a problem when serialization and type-checking get involved.
  • This particular video will likely have to be redone to accommodate lightweight objects and functions for GMS 2.3.
Using the Manual
  • It is of utmost importance to know how to read individual Manual pages once you've found them, and that's a major omission in this video. On the Q&A, I often link Manual pages for rookies, only for them to talk back to me saying they don't know how to read it. At the very least, they should understand what sections there are on a typical entry page (description, syntax/parameters, returns, example) and what purpose each serves.
  • For novices, it is absolutely crucial that they learn what NOT to look for in the Manual. It is a reference for definitions, and definitions only. A lot of them write off the Manual because they have inappropriate expectations from the manual (e.g. full tutorials and background knowledge). That are still Google material on the most part. In particular, novices should be encouraged to not restrict themselves to GM-specific resources for background theory on things like trigonometry and networking.
  • The built-in search tab is pretty marginal due to its need for exact wording matches. For general searches, I usually just go on Google and type <query> site:docs2.yoyogames.com. That only works when I'm using the latest stable version, though. For example, if the GMS 2.3 open beta comes up, I would have to revert to the built-in tabs because the online documentation won't have the new material.
  • Direct lookups can also be brought up with the F1 key when the cursor is over a built-in function/variable. This can be useful for on-the-go laptop setups that don't come with a middle click.
Scope
  • It would be clearer to a novice if you summarize what kinds of context each scope is generally applicable to: Global for shared properties of the environment, instance for non-shared properties of individual instances, local for temporary values.
  • For future tutorials involving for loops and scripts, you should be strict in using local variables for iteration variables and temporary results. Viewing local variables as mainly a nice-to-have memory saver is a disturbing attitude that I don't think this video adequately addresses. I see stuff like this on the GMC all the time, sometimes even from people purporting to be instructors:
    Code:
    for (i = 0; i < 7; i++)
    That i will stick around to clutter up the instance scope at best, and cause unexpected problems like these at worst. And there is next to no community awareness of it.
Enums
  • Note that the enum+array trick will be superceded by structs with the GMS 2.3 upgrade, except for continuing work with legacy code.
Macros
  • Best practice note: Because macros act like copy-and-paste replacements, expressions containing operators should always be enclosed in brackets to avoid unexpected issues later with order of operation. Here is a pathological example:
Code:
#macro foo 1+5
show_message("Foo is " + string(foo)); //6
show_message("Expected 3*foo = 3*6 = 18, got " + string(3*foo)); //8
Code Style
  • Typical tab sizes are 4 and 2. 5 (shown at 1:04) is generally too much.
  • "Loose GML" is one area that I often question coverage of in tutorials, precisely because they come apart at novice-unexpected times. For example, when you talked about "GML Flexibility", you didn't say that the first and third examples will become invalid if there are multiple actions being covered by the if block. I see rookies doing Python-esque stuff on GML all the time and then whine about code not working.
Conditional Statements
  • It may be useful as an appendix to show what conditional statements look like as written in Allman style.
  • It should be mentioned that else should always be used over the if (A) { ... } if (!A) { ... } anti-pattern. Rookies do the latter quite frequently and cause a load of unexpected problems down the road.
 
Last edited:

samspade

Member
Congratulations on your induction into the offical Learn pages. Hopefully rookies won't overlook them for not doing anything flashy or holding their hand on their "dream game".

I have taken a look at the videos you posted since the turn of the year. Here is my opinion on the finer points of each topic:

Data Types
  • enums are actually not a distinct type in GMS 2, just an additional syntax for declaring 64-bit integer constants. If you use typeof() on any enum value, you get int64.
  • Hexadecimals are actually just the literal syntax for int64, again not a distinct type. The actual type is 64-bit integer (int64).
  • It may be helpful to note common sources of non-acceptable quotes for strings, such as rich-text word processors (e.g. Word), copy-and-pastes from PDFs that have not been sufficiently reviewed, or typing aids and IDEs designed for natural language.
  • There is a rift between "fake" Booleans and "genuine" Booleans in GMS 2, which gets unmasked when typeof() and is_bool() are used on them. You can read more about it here and here. This issue won't affect rookies much, but will start becoming a problem when serialization and type-checking get involved.
  • This particular video will likely have to be redone to accommodate lightweight objects and functions for GMS 2.3.
Using the Manual
  • It is of utmost importance to know how to read individual Manual pages once you've found them, and that's a major omission in this video. On the Q&A, I often link Manual pages for rookies, only for them to talk back to me saying they don't know how to read it. At the very least, they should understand what sections there are on a typical entry page (description, syntax/parameters, returns, example) and what purpose each serves.
  • For novices, it is absolutely crucial that they learn what NOT to look for in the Manual. It is a reference for definitions, and definitions only. A lot of them write off the Manual because they have inappropriate expectations from the manual (e.g. full tutorials and background knowledge). That are still Google material on the most part. In particular, novices should be encouraged to not restrict themselves to GM-specific resources for background theory on things like trigonometry and networking.
  • The built-in search tab is pretty marginal due to its need for exact wording matches. For general searches, I usually just go on Google and type <query> site:docs2.yoyogames.com. That only works when I'm using the latest stable version, though. For example, if the GMS 2.3 open beta comes up, I would have to revert to the built-in tabs because the online documentation won't have the new material.
  • Direct lookups can also be brought up with the F1 key when the cursor is over a built-in function/variable. This can be useful for on-the-go laptop setups that don't come with a middle click.
Scope
  • It would be clearer to a novice if you summarize what kinds of context each scope is generally applicable to: Global for shared properties of the environment, instance for non-shared properties of individual instances, local for temporary values.
  • For future tutorials involving for loops and scripts, you should be strict in using local variables for iteration variables and temporary results. Viewing local variables as mainly a nice-to-have memory saver is a disturbing attitude that I don't think this video adequately addresses. I see stuff like this on the GMC all the time, sometimes even from people purporting to be instructors:
    Code:
    for (i = 0; i < 7; i++)
    That i will stick around to clutter up the instance scope at best, and cause unexpected problems like these at worst. And there is next to no community awareness of it.
Enums
  • Note that the enum+array trick will be superceded by structs with the GMS 2.3 upgrade, except for continuing work with legacy code.
Macros
  • Best practice note: Because macros act like copy-and-paste replacements, expressions containing operators should always be enclosed in brackets to avoid unexpected issues later with order of operation. Here is a pathological example:
Code:
#macro foo 1+5
show_message("Foo is " + string(foo)); //6
show_message("Expected 3*foo = 3*6 = 18, got " + string(3*foo)); //8
Code Style
  • Typical tab sizes are 4 and 2. 5 (shown at 1:04) is generally too much.
  • "Loose GML" is one area that I often question coverage of in tutorials, precisely because they come apart at novice-unexpected times. For example, when you talked about "GML Flexibility", you didn't say that the first and third examples will become invalid if there is more than action being covered by the if block. I see rookies doing Python-esque stuff on GML all the time and then whine about code not working.
Conditional Statements
  • It may be useful as an appendix to show what conditional statements look like as written in Allman style.
  • It should be mentioned that else should always be used over the if (A) { ... } if (!A) { ... } anti-pattern. Rookies do the latter quite frequently and cause a load of unexpected problems down the road.
Thank you. I appreciate the comments quiet a bit.

The only question I have on the above is regarding data types. The manual lists both as distinct data types. So even if type_of returns int64 I thought it would be better to refer to them as the manual does. Would it be possible for both to be true? e.g. type_of returning int64 but other systems in GML treating them as distinct datatypes in some manner? Either way, I can note this.

I'm still debating the best way to incorporate changes into the videos. Some, I'm going to redo (once 2.3 comes out I'll redo necessary videos and tag older ones with a legacy note). The variable basics video for example I'll probably redo in the next couple weeks. For others I might simply put correction text on the screen or pin a comment with corrections and additions to the video. But I will be working on incorporating all the suggestions I can in the upcoming weeks.
 

FrostyCat

Redemption Seeker
I like this one from a technical standpoint, and thank you for the referral links.

As always, here are my comments:
  • Since GMS 1.2, all case expressions must either be constants or expressions that can evaluate down to a constant at compile time. This important restriction has not been described in the switch video.
  • Consider using = to denote the identities between 3:39-5:25 instead of tables. Visually, these can be read 2 ways (row-wise and column-wise), and one of those ways is wrong.
  • Consider including definitions in your end-of-video summaries going forward (e.g. && returns true if both operands are true, false otherwise). This helps reinforce understanding, especially in longer videos where important content are spaced farther apart in time.
 

Toque

Member
Nice videos. I find the red text harder to read against black. I like that they are simple.
 
Last edited:

samspade

Member
Two new (short) videos.

An introduction to loops:


Repeat loops:


I do have one question which perhaps someone can answer here. In the repeat loop video I have the following code:

Code:
repeat (3) {
    show_debug_message("Hello World");
}
Despite clicking the button to step the debugger line by the line, the debugger runs all three lines immediately. I assumes this has something to do with how repeat loops are compiled, but I'm not sure.
 
I do have one question which perhaps someone can answer here. In the repeat loop video I have the following code:

Code:
repeat (3) {
    show_debug_message("Hello World");
}
Despite clicking the button to step the debugger line by the line, the debugger runs all three lines immediately. I assumes this has something to do with how repeat loops are compiled, but I'm not sure.
I'm sure it's related to how GM handles them internally. A decent workaround would be to put a breakpoint in the repeat loop with F9. The debugger will pause on every iteration.
 

samspade

Member
I'm sure it's related to how GM handles them internally. A decent workaround would be to put a breakpoint in the repeat loop with F9. The debugger will pause on every iteration.
That is actually not true. It will stop only once and print out all three lines.
 
These are my notes from the first two videos in the series. I'm going to make flash cards out of these and commit them to memory, but I wanted to check that they're both accurate and complete before I so so... Anything in CAPS is a "Vocabulary Word."
 

Attachments

samspade

Member
These are my notes from the first two videos in the series. I'm going to make flash cards out of these and commit them to memory, but I wanted to check that they're both accurate and complete before I so so... Anything in CAPS is a "Vocabulary Word."
Mostly yes. I'm not sure what the operator means in the list under variable, so I can't say for that, and for numbers I'm not sure what is meant by Double/Int. The manual says:

"All real numbers are stored as double-precision floating point values or integer values, and the compiler will optimise where possible (for example, 0.0 will be optimised to the integer value of 0). When dealing with any value that is not an integer, you may experience slight rounding errors due to the nature of floating point maths. For more information on this and other number related functions, please see: GML Reference - Real Numbers. NOTE: On the HTML5 target, all real numbers are doubles."

I take this to mean the following. On the HTML5 platform all numbers are double-precision floating point values. On other operating systems all numbers are either double-precision floating point values OR integers (and for the most part GML determines this behind the scenes and you don't control it). But doubles are not the same as ints. If I was unclear on this in the video, let me know and maybe I'll add some additional links or a text pop up or something.
 
Mostly yes. I'm not sure what the operator means in the list under variable, so I can't say for that, and for numbers I'm not sure what is meant by Double/Int. The manual says:
I think I was attempting to make a list of other "vocab words" that I'll need to know later.

Operator was in reference to things like < > and = which are called "assignment operators" if I'm not mistaken...? (it's very likely that I am.)

"All real numbers are stored as double-precision floating point values or integer values, and the compiler will optimise where possible (for example, 0.0 will be optimised to the integer value of 0). When dealing with any value that is not an integer, you may experience slight rounding errors due to the nature of floating point maths. For more information on this and other number related functions, please see: GML Reference - Real Numbers. NOTE: On the HTML5 target, all real numbers are doubles."
I thought I'd seen "DOUBLE" and "DOUBLE/INT" somewhere before (perhaps a SQL Database or a GM extension) but it seems that was a figment of my imagination.

Good catch. Thank you.

I take this to mean the following. On the HTML5 platform all numbers are double-precision floating point values. On other operating systems all numbers are either double-precision floating point values OR integers (and for the most part GML determines this behind the scenes and you don't control it). But doubles are not the same as ints. If I was unclear on this in the video, let me know and maybe I'll add some additional links or a text pop up or something.
Gotcha. Thanks for the clarification.

Alright-y then. I'm going to commit these to memory now, and once I'm able to rattle them off in the middle of the grocery store... I'll move onto the next video.
 
Operator was in reference to things like < > and = which are called "assignment operators" if I'm not mistaken...? (it's very likely that I am.)
Not quite. The assignment operator would be '='. You can think of it like English:, we are assigning a value to a variable. E.g.
Code:
//Assign the value 100 to the variable health.
var health = 100;
var bean = "baked";
Anytime we're assigning a value in the operation, it's an assignment operator. So =, +=, *=, etc, would all be assignment operators.

The other two you listed there are called comparison(or relational) operators, and we use them when we want to compare values. E.g.
Code:
//compare the variable health against the value 50
if health < 50 { }

if bean != "baked" { }

if health == 100 {}
GML can be a bit confusing because I think it allows you to use '=' for comparison, too. Eg..
if health = 100
But I'd generally encourage you to avoid using one '=' for comparison, and just use '=='. '==' is the standard comparison operator for most languages.

Different people use different lingo to describe these: Some people call comparison operators Relational operators,
(Lastly, AND(&&), OR (||) and NOT(!) are called Logical Operators.. and there are a few more operator types if you want a little further reading)
 
Not quite. The assignment operator would be '='. You can think of it like English:, we are assigning a value to a variable. E.g.
Code:
//Assign the value 100 to the variable health.
var health = 100;
var bean = "baked";
Anytime we're assigning a value in the operation, it's an assignment operator. So =, +=, *=, etc, would all be assignment operators.

The other two you listed there are called comparison(or relational) operators, and we use them when we want to compare values. E.g.
Code:
//compare the variable health against the value 50
if health < 50 { }

if bean != "baked" { }

if health == 100 {}
GML can be a bit confusing because I think it allows you to use '=' for comparison, too. Eg..
if health = 100
But I'd generally encourage you to avoid using one '=' for comparison, and just use '=='. '==' is the standard comparison operator for most languages.

Different people use different lingo to describe these: Some people call comparison operators Relational operators,
(Lastly, AND(&&), OR (||) and NOT(!) are called Logical Operators.. and there are a few more operator types if you want a little further reading)
That was really helpful. Thank you so much. :)
 

samspade

Member
New video up on For Loops. I had a couple issues with sound on this one, but hopefully it won't be that bad. I'm going to do another video on for loops in the future, but not right away. Also, I've run out of prepared slides, so videos will probably slow down to 2-3 per week instead of 4-5 as I've got to spend some time creating the slides.

 

samspade

Member
New video on the Error Message. Somehow 9 minutes. Apologize for the smallness of the error message texts. Someday I'll use software that lets me zoom.

 

Bearman_18

Fruit Stand Deadbeat
You're teaching newcomers the difference between an object and an instance? Yeesss. Good on you. Keep it up.
 

samspade

Member
New video on Object Events:


Edit: Tutorial update

I'm switching to two videos weekly and try to keep the uploads consistent on Wednesday and Saturday. If I can build up enough of a backlog of slides and prepared material I might increase it.

The series itself should be a little over half done. However, most of the remaining topics are more complex or advanced. The biggest one by far is the data structures section. That is probably going to be 8 videos on the built in data structures and if I haven't burned out on it another 3-5 on custom data structuresā€”enough to be its own series but I think data structures are glossed over so much that I want to include it.

After that There's about a half-dozen random videos and there's a couple topics I want to do an additional video for (e.g. for loops, and loops in general).

I didn't realize how many videos I would decide to do when I started. But its been a lot of fun so far.
 
Last edited:

samspade

Member
New video on Event Order:


Two important notes. First, when I refer to instance variables I'm referring to "Object Variables" created from the object variables tab, not all instance variables. Sorry for being unclear about this. See the bottom of this page for more: https://docs2.yoyogames.com/source/_build/2_interface/1_editors/objects.html. Second, I often reference other events, when I do this I'm referring to all the events (e.g. alarms, key presses, etc.) that exist but don't have an order specified for them in the manual. For example, you can figure out when the alarm events run on your computer, but you shouldn't rely on that specific order for the reasons discussed in the tutorial.

Also, I've decided that with possibly a few exceptions, pinning sticky notes to videos is the way I'm going to correct error or clarify things at this point. Once the series is done I will probably re-record videos that have had serious errors, omissions, or technical problems. But I'm also going to have to add new videos for 2.3 so I might just clarify things that way as well.
 
Last edited:
Top