GameMaker Quick #macro question

untune

Member
Hi all

Manual is light on info - does the #macro command evaluate and store the result of a function, or just replace any mentions of it in the code with a call to the function?

I can't figure out if I'm actually saving any processing time by using macros such as

#macro RADIANS_POS_90 degtorad(90)

I tried creating a temporary var and doing

radiansDegrees = degtorad(90); #macro RADIANS_POS_90 radiansDegrees;

but whenever I test a variable against it in code, I get errors and malformed assignments, it ddoesn't seem to like the brackets around "if" statements
 
  • Wow
Reactions: Mut
D

dannyjenn

Guest
The manual says that macros are "pre-compiled," so I'm guessing that macros are the Studio equivalent to constants.

In general, you cannot set a constant to the value of a variable because the constants are handled at compiletime whereas the functions are initialized at runtime. You can, however, set the constant to degtorad(90), and it will not need to call the degtorad() function every time since the value is replaced just one time (when the program is compiled). I'm guessing GameMaker is no different.
 

GMWolf

aka fel666
The manual says that macros are "pre-compiled," so I'm guessing that macros are the Studio equivalent to constants.

In general, you cannot set a constant to the value of a variable because the constants are handled at compiletime whereas the functions are initialized at runtime. You can, however, set the constant to degtorad(90), and it will not need to call the degtorad() function every time since the value is replaced just one time (when the program is compiled). I'm guessing GameMaker is no different.
No, Macros get replaced with its constant.
In fact, they are very lenient and will allow you to do some wacky things, like having 1/2 completed statements.

if you have #macro RAND random(1), RAND will return a new random number every time it's used.
 
D

dannyjenn

Guest
Oh, I see. So they save you some typing but they don't really save on CPU?

What about when the macro is just a number rather than a function call? Any idea on whether it would take up any RAM (like a variable would)?
 

GMWolf

aka fel666
Oh, I see. So they save you some typing but they don't really save on CPU?

What about when the macro is just a number rather than a function call? Any idea on whether it would take up any RAM (like a variable would)?
No it's all done at compile time. So it doesn't use ram like a variable.
But don't use them for performance reasons. Use them for code cleanliness
 
Basically, macros work like copy and paste. Eg:

#macro my_string "hello world"

Show_message (my_string);

Becomes:

Show_message ("hello world");

.... as if you had typed it out yourself.

I also use it to create shortcut function names, like this:

#macro msg show_message

msg (my_string);

And yes, you can add almost whatever you want in macros and they will work as expected.
 

Yal

šŸ§ *penguin noises*
GMC Elder
But don't use them for performance reasons. Use them for code cleanliness
^That. So much that.

Macros also lets you get code completion and color-coding for things, but unlike enums can have any value (strings, decimals, etc), so they also work like constants would work in a normal programming language like C.
 

GMWolf

aka fel666
I like to use them to wrap global variables a lot. Initialize them using the 'global' pragmatic command.
 
C

CedSharp

Guest
I like to use them to wrap global variables a lot. Initialize them using the 'global' pragmatic command.
You mean something like this?
Code:
global.my_global = "test";
#macro my_global global.my_global
Can't you just do that instead?
Code:
globalvar my_global;
my_global = "test";
I don't think there is much of a difference since they both use 2 lines, but it will show up as global variable
in the intellisense while the other shows as a macro :)
 

GMWolf

aka fel666
You mean something like this?
Code:
global.my_global = "test";
#macro my_global global.my_global
Can't you just do that instead?
Code:
globalvar my_global;
my_global = "test";
I don't think there is much of a difference since they both use 2 lines, but it will show up as global variable
in the intellisense while the other shows as a macro :)
Yeah but I don't like globalvar...
 

samspade

Member
And it has been deprecated in GMS2, so should not be used.
It was deprecated? I don't think this is true. I use it regularly. Even the GMS 1 manual says it is included for backwards compatibility only and that it shouldn't be used, but the only reason it gives is that it is easy to confuse variables. I prefer globalvar over global. because it makes my variable names so much longer. I use all caps for globalvar (e.g. globalvar HELLO, WORLD; HELLO = "hello"; WORLD = "world"; ) and have never gotten them confused. Is there some other reason to not use globalvars?
 
Last edited:
It was deprecated? I don't think this is true. I use it regularly. The GMS 1 manual does say it is included for backwards compatibility only and that it shouldn't be used, but the only reason it gives is that it is easy to confuse variables. I prefer globalvar over global. because it makes my variable names so much longer. I use all caps for globalvar (e.g. globalvar HELLO, WORLD; HELLO = "hello"; WORLD = "world";) and have never gotten them confused. Is there some other reason to not use globalvars?
From the manual:
The second method for creating global variables is to declare them as such using the globalvar declaration, much as you would a local variable using the var declaration.

IMPORTANT! The globalvar declaration is deprecated and only supported for legacy purposes. You should always use the global. identifier to mark global variables.
https://docs2.yoyogames.com/source/_build/3_scripting/3_gml_overview/6_scope.html
Just open the section about Global Variables and scroll down to find globalvar.

It's just like that score, health, lives is also listed as deprecated and only there for legacy purposes.
 

samspade

Member
From the manual:

https://docs2.yoyogames.com/source/_build/3_scripting/3_gml_overview/6_scope.html
Just open the section about Global Variables and scroll down to find globalvar.

It's just like that score, health, lives is also listed as deprecated and only there for legacy purposes.
Well, that's nearly the same language as GMS1. Hopefully it's just there to scare people away from it as it is way easier and nicer to use than the global. prefix. (Unless there's some code reason for it - I'd rather the nice stuff not get taken away because it can confuse people.)
 
I'm hoping that by saying it is deprecated, it will be removed some time in the future by YYG. Perhaps it won't exist in the next version of GMS (v3 onwards) as they have given plenty of warning to not use it. I just don't understand why people like using it when global.<variablename> exists, because this:
This (deprecated) declaration would be used as follows:

globalvar food;
food = 5;

Once declared in this way that variable "food" is now considered global and requires no global. prefix - which also means that it's a lot harder to identify global variables in your code and it's also much easier to get variable overlap as you use the same variable name in different objects or from extensions that you've installed.
I personally think that the global.<variablename> is much tidier, and safer. But each to their own preference.
 

samspade

Member
I'm hoping that by saying it is deprecated, it will be removed some time in the future by YYG. Perhaps it won't exist in the next version of GMS (v3 onwards) as they have given plenty of warning to not use it. I just don't understand why people like using it when global.<variablename> exists, because this:


I personally think that the global.<variablename> is much tidier, and safer. But each to their own preference.
I guess. I suppose I could always use the macro idea to do: #macro G global and then do G.FOOD = 5;
 
C

CedSharp

Guest
I guess. I suppose I could always use the macro idea to do: #macro G global and then do G.FOOD = 5;
If you're gonna create a macro and like using global var, you can literally just make
Code:
global.food = 5;
#macro FOOD global.food
It just sucks that they are going to remove globalvar. For one, that means no more intellisense about global variables, unless they start with global.
My code will end up looking like this:
Code:
var glob1, glob2, glob3;
glob1 = global.global_value_01;
glob2 = global.global_value_02;
glob3 = global.global_value_03;

if(glob1 && (glob2 < glob3)) return glob1 + glob3;
I would hate to have to write:
Code:
if(
    global.global_value_01 && (
         global.global_value_02
      <  global.global_value_03
    )
) {
    return
         global.global_value_01
      +  global.global_value_03
}
 

Yal

šŸ§ *penguin noises*
GMC Elder
It just sucks that they are going to remove globalvar. For one, that means no more intellisense about global variables, unless they start with global.
My code will end up looking like this:
Code:
var glob1, glob2, glob3;
glob1 = global.global_value_01;
glob2 = global.global_value_02;
Kinda feels like there's no point in prepending an extra "global" if you're enforced to use one anyway, why not call those stuff like global.value_01 and so on? Also, you could have a macro g that represents the text global and then you could call it g.value_01, right? IMO the only time where it's helpful to keep a variable name short is if you use it so often you can't ever forget what it's for, all the other time it's not worth the trouble cutting off legibility to save space. I dug through some 6-months-old code yesterday that I'd kept compact and I had to draw a graph to tell what everything represented because I'd forgotten what the variable names were abbreviations of.
 
C

CedSharp

Guest
Kinda feels like there's no point in prepending an extra "global" if you're enforced to use one anyway, why not call those stuff like global.value_01 and so on? Also, you could have a macro g that represents the text global and then you could call it g.value_01, right? IMO the only time where it's helpful to keep a variable name short is if you use it so often you can't ever forget what it's for, all the other time it's not worth the trouble cutting off legibility to save space. I dug through some 6-months-old code yesterday that I'd kept compact and I had to draw a graph to tell what everything represented because I'd forgotten what the variable names were abbreviations of.
The main point of my last post is that 'global.variablename' is not a simple variable access, it's an object's property access.

The the fact the name contains 'global' is irrelevant. I was expressing my discontentment with prefixing a variable with 'global.' because it feels like I'm accessing an object's property. Forcing us to add '.global' for global variable is the same as forcing us the use uppercase letters or anything else. It's a methodology which limits a programmer like me from applying his own conventions. I've always used globalvar for global variables because I need values that can change, otherwise I would've used constants.

Now being able to define macros is nice and all, but that shouldn't be how I create my global variables.
In my code, if I see 'VARIABLE' I know it's global. If I see 'variable' I know it's an instance variable, and if I see a one-letter variable or one prefixed with an underscore '_var' or 'c' I know it's a local variable.
I've used 'globalvar' since GM 8.0 and I don't see a good valuable reason for it to be removed. If they remove 'globalvar' they should also remove 'var' then, they fall under the same category.

Why do we not use 'local.variableName' for local varaibles ? They are pushing a specific convention in GML which I do not like.
I'm not saying they are wrong, I just believe switching to 'global.variablename' is a pain in the butt :|

The kind of code I use is similar to this:

Code:
// ext_init()
globalvar EXT;
EXT = ds_map_create();

EXT[? "colors"] = ds_map_create();
EXT[? "fonts"] = ds_map_create();

// ext_add_color( name, value )
var _colors, _colorName, _colorValue;
_colorName = argument[0];
_colorValue = argument[1];

_colors = EXT[? "colors"];
_colors[? _colorName] = _colorValue;

// ext_get_color( name )
var _colors, _colorName;
_colorName = argument[0];

_colors = EXT[? "colors"];
if(ds_map_exists(_colors, _colorName)) return _colors[? _colorName];
return c_black;
As you can see, adding 'global.' prefix in there would just polute the code with 'global.EXT' and that would be a pain. The user of those script usually never will need to access EXT ever. I mainly use that to store settings for my assets and other stuff. I don't want to start to use 'global.' in my projects.

Anyways, the time it took for GM2 to come out since GM1.4, I don't think we'll see any GM3 before a couple years, so at least I don't need to care about that for now.
 
Last edited:

Rob

Member
I'm hoping that by saying it is deprecated, it will be removed some time in the future by YYG. Perhaps it won't exist in the next version of GMS (v3 onwards) as they have given plenty of warning to not use it. I just don't understand why people like using it when global.<variablename> exists, because this:


I personally think that the global.<variablename> is much tidier, and safer. But each to their own preference.
For my 2 cents, I didn't start using globalvar till my last game and I like it a lot. I just use g_ as a prefix so I know it's a global var. A lot easier and less cluttered than global. as previously mentioned.

I do try and stay away from too many global vars though. If I can't use it in the future it won't be a big deal hopefully.
 

GMWolf

aka fel666
was expressing my discontentment with prefixing a variable with 'global.' because it feels like I'm accessing an object's property.
Yoy are in fact accessing an instance variable. There is an interint global instance used for global variables and global pragmas.

O should point out using global should be very rare. Most of the time the variables are better suited to be in a system instance.
 

JackTurbo

Member
My favourite use of macros is for array/ds_grid references. Like say you have a 2D array for character stats called statsTable.

Instead of doing something like:
hp = statsTable[0,1];
str = statsTable[0, 2];

You can set up macros for what each row/column represent.
hp = statsTable[NAME, HP];
str = statsTable[NAME, STR];

Much easier to remember and read later on.
 

GMWolf

aka fel666
My favourite use of macros is for array/ds_grid references. Like say you have a 2D array for character stats called statsTable.

Instead of doing something like:
hp = statsTable[0,1];
str = statsTable[0, 2];

You can set up macros for what each row/column represent.
hp = statsTable[NAME, HP];
str = statsTable[NAME, STR];

Much easier to remember and read later on.
InprefI using enums myself. Doesn't clog up the namespace, and automatically gets assigned integers.
 
C

CedSharp

Guest
Yoy are in fact accessing an instance variable. There is an interint global instance used for global variables and global pragmas.

O should point out using global should be very rare. Most of the time the variables are better suited to be in a system instance.
Creating an instance, with lots of different properties (instance variables) and lots of automation (step event, alarms, draw event, collision, masks, etc)
seems stupid and a waste of resources to me. I much rather store anything that isn't an instance or related to an instance inside a variable that does just that: store a value.

Here is an illustration: A 'setting' doesn't move. A setting doesn't need to be updated every step event. A setting cannot collide with another object. A setting doesn't need to be drawn. A setting is just a group of values. For that, I don't think it's worth wasting huge chunks of memory just to have 'color' and 'font' stored in an instance called 'Settings'.

To me that's as dumb and stupid as renting a house, heating it and paying electricity just to store your baseball cap in the wardrobe. Instead, I agree that most of the time you will wear the cap on your own head. But there are times where you do not need to do so, and as such you need a place where you can store it. A bag is a perfect place to put your cap when you don't wear it. You can put stuff in it, and take it back, or change it's content. Yet you don't need to pay a rent or pay electricity to keep it heated.

My illustration might not be the best, but that's how I see 'instances' vs 'variables' in GameMaker. A global variable is basically a bag that is magically always accessible, for me or for another person in the world.

A 'system instance' which has a 'hold alll the variables' goal is basically just another 'global.' prefix. It's still a global variable and is still accessible from any instances. You are just doing global variable the wrong way by creating an instance to hold them, which is, in my opinion, bad.

'globalvar' or the 'global' prefix are the "right" way of doing global variables in GameMaker no questioning that. And even if 'global' is an actual instance in GameMaker, that doesn't change the fact that I want to access a variable but it feels like accessing an instance property, which is wrong in the first place, since by definition a global variable does NOT belong to an instance, it's available to all and every instances at all time.

The notion that "global variables" should be very rare is wrong. The actual thing to keep in mind is that variables that are directly linked to an instance should not be made global. For example, instead of creating the global varaible "health_player" and "health_boss" you should instead create the instance variable "health" for each of them.

But take another example: I have dialog boxes, and each of them has a set of settings that can be accessed by name. Would you duplicate all those 'names' in every single instances?

No, I rather store them in one location which is available to all of them (that's what a global variable is for) and access it from there.

Such example refers to what I shown before: colors and fonts.
Each dialog object has a 'color' and a 'font' instance variable. But the values themself are called from ds_maps like this: COLORS[? "blue"]. That specific map position contains $FFAAAA;

Why do I need to use names to access colors? That's irrelevant, but you can check CTB on the market place to see why.

Anyways, my point here is that there are times where global variables make sense, and in those situations I don't want to store them inside another instance since that would be a very stupid waste of resources. For that same specific reason, I feel it's weird to access a variable that isn't inside an instance via the dot notation since that's exactly how you access instance variables.

My code would drastically change from this keyword removal and that might even make me stop use GameMaker. There are things which shouldn't be changed an the way global variables are currently setup in GameMaker is one of those things I really don't want to see change.

There is 'var', there is 'globalvar', that's consistent to me.
Remove one, and you should remove the other. They are a pair.
Remove only one, and you lose consistency, and make people like me unhappy.
 
Last edited:

GMWolf

aka fel666
Creating an instance, with lots of different properties (instance variables) and lots of automation (step event, alarms, draw event, collision, masks, etc)
seems stupid and a waste of resources to me. I much rather store anything that isn't an instance or related to an instance inside a variable that does just that: store a value.

Here is an illustration: A 'setting' doesn't move. A setting doesn't need to be updated every step event. A setting cannot collide with another object. A setting doesn't need to be drawn. A setting is just a group of values. For that, I don't think it's worth wasting huge chunks of memory just to have 'color' and 'font' stored in an instance called 'Settings'.

To me that's as dumb and stupid as renting a house, heating it and paying electricity just to store your baseball cap in the wardrobe. Instead, I agree that most of the time you will wear the cap on your own head. But there are times where you do not need to do so, and as such you need a place where you can store it. A bag is a perfect place to put your cap when you don't wear it. You can put stuff in it, and take it back, or change it's content. Yet you don't need to pay a rent or pay electricity to keep it heated.

My illustration might not be the best, but that's how I see 'instances' vs 'variables' in GameMaker. A global variable is basically a bag that is magically always accessible, for me or for another person in the world.

A 'system instance' which has a 'hold alll the variables' goal is basically just another 'global.' prefix. It's still a global variable and is still accessible from any instances. You are just doing global variable the wrong way by creating an instance to hold them, which is, in my opinion, bad.

'globalvar' or the 'global' prefix are the "right" way of doing global variables in GameMaker no questioning that. And even if 'global' is an actual instance in GameMaker, that doesn't change the fact that I want to access a variable but it feels like accessing an instance property, which is wrong in the first place, since by definition a global variable does NOT belong to an instance, it's available to all and every instances at all time.

The notion that "global variables" should be very rare is wrong. The actual thing to keep in mind is that variables that are directly linked to an instance should not be made global. For example, instead of creating the global varaible "health_player" and "health_boss" you should instead create the instance variable "health" for each of them.

But take another example: I have dialog boxes, and each of them has a set of settings that can be accessed by name. Would you duplicate all those 'names' in every single instances?

No, I rather store them in one location which is available to all of them (that's what a global variable is for) and access it from there.

Such example refers to what I shown before: colors and fonts.
Each dialog object has a 'color' and a 'font' instance variable. But the values themself are called from ds_maps like this: COLORS[? "blue"]. That specific map position contains $FFAAAA;

Why do I need to use names to access colors? That's irrelevant, but you can check CTB on the market place to see why.

Anyways, my point here is that there are times where global variables make sense, and in those situations I don't want to store them inside another instance since that would be a very stupid waste of resources. For that same specific reason, I feel it's weird to access a variable that isn't inside an instance via the dot notation since that's exactly how you access instance variables.

My code would drastically change from this keyword removal and that might even make me stop use GameMaker. There are things which shouldn't be changed an the way global variables are currently setup in GameMaker is one of those things I really don't want to see change.

There is 'var', there is 'globalvar', that's consistent to me.
Remove one, and you should remove the other. They are a pair.
Remove only one, and you lose consistency, and make people like me unhappy.
here is a scenario:

you have a game with a time limit. When the time reaches 0, the game ends.
You then decide to add another end condition; a maximum score. easy enough so far.

But now you want to have just the time limit, or just the maximum score. Still pretty easy: you add an if statement.

but what if you now want both? a combination of many different conditions, etc... it quickly makes you code unmanageable.

But what if instead you had one time limit object, and a score limit object, etc. you can just instantiate them as needed. neat.
 

GMWolf

aka fel666
There is 'var', there is 'globalvar', that's consistent to me.
oh no, do you advocate the use of globalvar?

var and global var are very, very different.
var only "polutes" the local scope. No issues here, there is no alternative to that.
globalvar will interfere with your whole entire codebase! it will propagate through your scopes.
Using globalvar means any instance varaibles with the same name get messed up, even, in some cases, local vars with same name!
 
C

CedSharp

Guest
oh no, do you advocate the use of globalvar?

var and global var are very, very different.
var only "polutes" the local scope. No issues here, there is no alternative to that.
globalvar will interfere with your whole entire codebase! it will propagate through your scopes.
Using globalvar means any instance varaibles with the same name get messed up, even, in some cases, local vars with same name!
I don't advocate the use of globalvar, I advocate a CORRECT use of globalvar.
Like I mentioned, I follow the usual conventions when I code.

All my global variables are upper case and hence should never conflict with normal underscored lowercase variable names.
I also use only variables to which I ALWAYS want to have a reference to, not when they are temporary.

And that argument has no value for someone who uses 'global.variable' since it does the same thing.
'var' and 'globalvar' are exactly the same. They polute the exact same way, and they have the same issues.
Their lifespan is different, that's the only difference between them.
 

GMWolf

aka fel666
They polute the exact same way,
they dont.
var polutes the local scope. thats ok, its normal variable behaviour.
globalvar polutes the entire codebase. Huge problem when working with imported code. GM may not even give compile errors, you will just get very, very hard code to debug.
Using Upper case on global vars may aleviate the problem, but if a piece of imported code chooses to use the same variable name... eh, not much you can do but refactor the entire codebase.

Really that's a flaw with GML's design...
 
C

CedSharp

Guest
here is a scenario:

you have a game with a time limit. When the time reaches 0, the game ends.
You then decide to add another end condition; a maximum score. easy enough so far.

But now you want to have just the time limit, or just the maximum score. Still pretty easy: you add an if statement.

but what if you now want both? a combination of many different conditions, etc... it quickly makes you code unmanageable.

But what if instead you had one time limit object, and a score limit object, etc. you can just instantiate them as needed. neat.
But then, your point where you need to do a combination would be a nightmare.
In that specific scenario, there is no best solution. In my opinion, you're wasting resources with your instances.

In a scenario like yours, all I need are 2 variables and an enum:

conditions = a list of all the different scripts to execute for each condition. They return true or false.
condition_list = a list of all the ID of the conditions I want to meet. Perhaps only condition 0 and 4 ?
Conditions = an enum in which instead of using IDs like 0 and 4 I use 'Conditions.TimeLimit' and 'Conditions.MaxScore'.

In this case, conditions and Conditions would be global, since through the game they would always be the same. Only need to 'create' them once.
And 'condition_list' would be an instance variable created in the instance that manages the room or the current level.
 
C

CedSharp

Guest
they dont.
var polutes the local scope. thats ok, its normal variable behaviour.
globalvar polutes the entire codebase. Huge problem when working with imported code. GM may not even give compile errors, you will just get very, very hard code to debug.
Using Upper case on global vars may aleviate the problem, but if a piece of imported code chooses to use the same variable name... eh, not much you can do but refactor the entire codebase.

Really that's a flaw with GML's design...
var and global are exactly the same to me.

Here is an example:

Code:
// Global Scope
var1
{
    // Instance Scope
    var2
    {
         // Script or Piece of Code in an event
         var3
    }
}
With just this simple illustration, you'll clearly see that they are the exact same, just 'a higher level'.
A globalvar is poluting the 'local' code of the GAME.
An instance variable is poluting the 'local' code of an INSTANCE.
A local variable is poluting the 'local' code of a SCRIPT (a piece of code basically)

There is no fundamental difference between how they work. It's just that once inside a scope, you can't access it outside that scope.
A var in a script cannot be accessed in the instance. An instance var cannot be accessed in the Game scope, but the opposit is true.
You can access globals in instances and in scripts. You can access instance vars in scripts.

They all work the same, they are all just 'variables' they are just defined at different level.

But instead, take this example:
Code:
// Global instance
{
     var1
}

// Player instance
{
    var2
    something = global.var1
}
See how a global variable prefixed with 'global.' is NOT the same thing?
It is defined inside it's own specific special treated scope, it's special exceptional instance.
And you're telling me you want to remove 'globalvar' and use 'global' instead?

I'm not talking about if yes or not you should use globals or not. I'm talking about if yes or no
prefixing one with 'global.' should be forces upon developers or not.
 

GMWolf

aka fel666
But then, your point where you need to do a combination would be a nightmare.
In that specific scenario, there is no best solution. In my opinion, you're wasting resources with your instances.

In a scenario like yours, all I need are 2 variables and an enum:

conditions = a list of all the different scripts to execute for each condition. They return true or false.
condition_list = a list of all the ID of the conditions I want to meet. Perhaps only condition 0 and 4 ?
Conditions = an enum in which instead of using IDs like 0 and 4 I use 'Conditions.TimeLimit' and 'Conditions.MaxScore'.

In this case, conditions and Conditions would be global, since through the game they would always be the same. Only need to 'create' them once.
And 'condition_list' would be an instance variable created in the instance that manages the room or the current level.
well, that was one example, but it gets more complex sometimes, with multiple events, etc.

Also instances are not so expensive you cannot spare a few to create these systems. we are not using 1970s mainframes anymore.
 
C

CedSharp

Guest
well, that was one example, but it gets more complex sometimes, with multiple events, etc.

Also instances are not so expensive you cannot spare a few to create these systems. we are not using 1970s mainframes anymore.
I'm not talking about using 'too much resources' I'm talking about wasting some.
An instance in GameMaker is extremly expensive in terms of what it does in the background.
An empty object in game maker does so much you wouldn't believe it.

As someone who wants to write code which I truely control and know what is going on, I dislike the idea of creating an instance to hold one or multiple values if that instances
won't be drawn, do collision or need updates of any type.
 

GMWolf

aka fel666
See how a global variable prefixed with 'global.' is NOT the same thing?
It is defined inside it's own specific special treated scope, it's special exceptional instance.
And you're telling me you want to remove 'globalvar' and use 'global' instead?
I barely use global myself. (I use named instances)

A globalvar is poluting the 'local' code of the GAME.
you have little control over what other pieces of code share that scope. Think assets, working in teams, etc
Very hard to determine if variable is already in use.
An instance variable is poluting the 'local' code of an INSTANCE.
You have some control over what other code shares that scope. When working in teams, document your objects.
Somewhat easy to see what variables are in use, unless a ton of scripts are used.
A local variable is poluting the 'local' code of a SCRIPT
you have full control over what code shares that scope.
Even when working in teams, or using many assets, its trivial to see what variables are used. The IDE even helps you identifie them.
 

GMWolf

aka fel666
As someone who wants to write code which I truely control and know what is going on, I dislike the idea of creating an instance to hold one or multiple values if that instances
won't be drawn, do collision or need updates of any type.
Yeah, I get that too. But when i need to think about this my first instinct is to shy away from engines which do this inherently.
For instance, does it not bother you that even with the YYC, all your variables are wrapped in objects? (I want to say the're not even always on the stack! but i would have to check that last one)
 
C

CedSharp

Guest
I barely use global myself. (I use named instances)


you have little control over what other pieces of code share that scope. Think assets, working in teams, etc
Very hard to determine if variable is already in use.

You have some control over what other code shares that scope. When working in teams, document your objects.
Somewhat easy to see what variables are in use, unless a ton of scripts are used.

you have full control over what code shares that scope.
Even when working in teams, or using many assets, its trivial to see what variables are used. The IDE even helps you identifie them.
A sprite is usually prefixed with 'spr_' so it should almost never conflict, same for sounds, rooms, objects, etc.
That's a GameMaker convention. Not following it is your choice but not an argument.

If you work in a team but do not follow a convention, then your team is broken.
In the big vast world of programming, a lot of working and proved conventions exists specially because of those 'name clashing' issues.

Global variables usually have upper case or camel case naming to show they are 'big', 'always available'.
Private instance properties usually have an '_' to denote they are belonging to the class the code is executing in.
Normal (local) variables have no special treatment.

Now in GameMaker, you can't rename the existing properties, and since they don't use underscore you're stuck with using what is available.
But you can simply reverse the logic: local variable can instead be underscored.

I personaly use camel case for my instance variables and rarely use small variable names: conditionList, winningConditions, etc.

this allows me to re-use existing gamemaker variables if I want: imageXScale, imageSpeed, hSpeed.

Here is what I use for conventions:
Global variables are uppercase: TTE_SETTINGS = ds_map_create()
Enum variables are capitalized: TTESetting.Color, TTESetting.Font
Instance variables are 'normal': x, y, size, canDie
Local variables are 'underscored' or 1 char: i, j, _collidedInstanceID, _lastTimeInSeconds

All resources are prefixed by 3 letter of that resource:
sprites: spr_
sounds: snd_
scripts: scr_
objects: obj_
rooms: rm_ (the only exception, uses 2 letters instead)

Using that, global variables aren't poluting at all, they don't affect me, and anyone else who reads my code knows without having to trace back what
each varaibles is used for. This is how you work in teams, not by using instances to store global values instead of using a proper global variable.
 

GMWolf

aka fel666
A sprite is usually prefixed with 'spr_' so it should almost never conflict, same for sounds, rooms, objects, etc.
assets, as in libraries. you dont know what they chose to name their variables.

If you work in a team but do not follow a convention, then your team is broken.
so what, every time i declare a variable i should notify the whole team? what if we both need a global TIME variable?
 
C

CedSharp

Guest
assets, as in libraries. you dont know what they chose to name their variables.


so what, every time i declare a variable i should notify the whole team? what if we both need a global TIME variable?
1. If an asset doesn't follow any conventions, I would not use that asset. For the same reason you wouldn't buy a blue banana with red spots,
I wouldn't download/use a library that can't correctly use variables.

2. If 2 people in the same team developping the same game/program end up with 2 time the same global variable name, there is a huge problem
in the planning of the game and/or people on the team have no clue how and when to use a global variable.


I think you are misunderstanding me. I am not saying you should use global variables all the time. I'm saying that there is no reason not to use them.
They do their job the same way an instance variable does it. You do have to know how and when you should use a global variable tho.
 

GMWolf

aka fel666
I wouldn't download/use a library that can't correctly use variables.
there are a few conventions for naming variables in GM. none of which are used by any significant number of people...

If 2 people in the same team developping the same game/program end up with 2 time the same global variable name, there is a huge problem
in the planning of the game and/or people on the team have no clue how and when to use a global variable.
not really: there is a huge problem with the planning of the language.

I think you are misunderstanding me. I am not saying you should use global variables all the time. I'm saying that there is no reason not to use them.
They do their job the same way an instance variable does it. You do have to know how and when you should use a global variable tho.
oh yeah, they have a few, specific uses. but most of the time variables belong to some sort of system.
 
C

CedSharp

Guest
not really: there is a huge problem with the planning of the language.
What do you mean "planning of the language" ? If 2 people on the same team end up using the exact same global variable for different purpose, either they have no clue how to correctly name a variable, either that variable should be inside an instance and not a global variable. I can't imagine a single use case where you would use 2 time the varaible time. You'd end up with 'TimeLimit' and 'RunTime' for exmaple, not just randomly 2 time 'Time'.

there are a few conventions for naming variables in GM. none of which are used by any significant number of people...
Could you please link me to a page or a document that shows that what you are saying is true? I strongly believe the opposit because people who start usually follow the documentation,
and that tool is FULL of conventions. You can, for instance, see the spr_ prefixing in there.


oh yeah, they have a few, specific uses. but most of the time variables belong to some sort of system.
That means that those varaibles aren't global variables. Like I just mentioned, there is a difference between blindly using global variables and knowing how to use them.
 

GMWolf

aka fel666
Could you please link me to a page or a document that shows that what you are saying is true? I strongly belie
ve the opposit because people who start usually follow the documentation,
and that tool is FULL of conventions. You can, for instance, see the spr_ prefixing in there.
no resource naming is clear, there are two conventions:
old school: spr_* obj_* etc
and more recently: sSomething oSomething etc

But as for variable and script naming?
for scripts, some use snake_case, others use camelCase. snake_case is better IMO as it matches gm built in functions.

local vars has three conventions: snake_case, _underscore_prefixed and camelCale. (i like snake_case)

instance vars are usually snake_cased or camelCased. (I like to camelCase)

globalvars - no idea actually. but apparently CAPS

global. - no idea either, tends to be camelCase or snakeCase.

I dont have any resource to back me up other than using GM for a couple years and reading through a lot of assets and other people code.
What do you mean "planning of the language" ? If 2 people on the same team end up using the exact same global variable for different purpose, either they have no clue how to correctly name a variable, either that variable should be inside an instance and not a global variable. I can't imagine a single use case where you would use 2 time the varaible time. You'd end up with 'TimeLimit' and 'RunTime' for exmaple, not just randomly 2 time 'Time'.
so we can agree: GM users overuse global variables and would often be better off putting them in singletons. (or something close to a singleton instance).

You'd end up with 'TimeLimit' and 'RunTime' for exmaple, not just randomly 2 time 'Time'.
what if you are both working of a branch without a TIME globalVar.
you are working on an animation system, and feel like a global TIME variable to represent time in seconds since start of game would be useful.

teammate is working on a High Score system and uses a global TIME variable to track the actual time, in hours and seconds, so that it can be recorded when you reach a new high score...

they are both good uses of the TIME variable name, but when it comes to merging...

In my opinion this is when its best to use system instances. The first use of TIME is better suited to be in an Animation system object.
 
C

CedSharp

Guest
no resource naming is clear, there are two conventions:
old school: spr_* obj_* etc
and more recently: sSomething oSomething etc

But as for variable and script naming?
for scripts, some use snake_case, others use camelCase. snake_case is better IMO as it matches gm built in functions.

local vars has three conventions: snake_case, _underscore_prefixed and camelCale. (i like snake_case)

instance vars are usually snake_cased or camelCased. (I like to camelCase)

globalvars - no idea actually. but apparently CAPS

global. - no idea either, tends to be camelCase or snakeCase.

I dont have any resource to back me up other than using GM for a couple years and reading through a lot of assets and other people code.

so we can agree: GM users overuse global variables and would often be better off putting them in singletons. (or something close to a singleton instance).


what if you are both working of a branch without a TIME globalVar.
you are working on an animation system, and feel like a global TIME variable to represent time in seconds since start of game would be useful.

teammate is working on a High Score system and uses a global TIME variable to track the actual time, in hours and seconds, so that it can be recorded when you reach a new high score...

they are both good uses of the TIME variable name, but when it comes to merging...

In my opinion this is when its best to use system instances. The first use of TIME is better suited to be in an Animation system object.
1. I am not saying MY conventions are THE conventions, I'm saying that poluting namespace is solved by conventions.

2. Often be better put off... NO. NO. You use global variables when a global variable should be used, you use instance variable when an instance variable should be used.
To use instance variables inside global objects instead of a global object is the same as creating global variables for instance variables. You're using it wrong. I'm not saying you should use global variable more,
I'm saying the whole argument you're having with me is not about why initial point but about you hating global variables. Don't use globals if you don't like them, but don't force the idea that they are wrong on others.

3. One of the biggest fundamental programming hidden rules is that you should always use descriptive variable names.
So if you use 'time' globally, you should be able to say, without a doubt, what time refers to, even if you aren't the one who coded it.
If I would see 'Time' in a game wich tracks achievements, for example, I'd have no clue what time refers to since it could literally be the time for any task in the game.
If you can't understand a global's use by it's name, then that variable isn't descriptive enough and you failed in naming it. Global or not, it's just a failure.
 

GMWolf

aka fel666
I am not saying MY conventions are THE conventions, I'm saying that poluting namespace is solved by conventions.
I'm saying a library could be using another convention.
I actually got screwed over more than once by libraries that make liberal use of globalvar, global. or even just instance varaibles.
Yeah, they are bad libraries, but GML is somewhat to blame.
Its why i try to use globals a little as possible. so that my code wont polute other peoples.

To use instance variables inside global objects instead of a global object is the same as creating global variables for instance variables.
The instance here will serve as a guard. A sort of namespace if you will.
Think of static variables in other languages. But here we use an instance instead.

I'm saying the whole argument you're having with me is not about why initial point but about you hating global variables. Don't use globals if you don't like them, but don't force the idea that they are wrong on others.
Ok but then those people go off to make libraries and... yeah...

If I would see 'Time' in a game wich tracks achievements, for example, I'd have no clue what time refers to since it could literally be the time for any task in the game.
well, yeah...
but iAnimation.time is clearly time for the animation system. (iAnimation is how name instances in room editor.)

yes you could also have global.animation_time or globalvar ANIMATION_TIME.
but iAnimation.time is far neater IMO: it regroups your animation variables under a single instance scope.

at this point its a matter of taste, but i can tell you using instances like this will reduce clashes far more effectively, whilst making clear what the lifetime of the variable is, and what group of objects are expected to operate on it.

Then again, I really like the Actor Action model i proposed, and many people seem to disagree with my liberal use of instances there too. Apparently having variable access take 2x as long is unacceptable...
 
C

CedSharp

Guest
I'm saying a library could be using another convention.
I actually got screwed over more than once by libraries that make liberal use of globalvar, global. or even just instance varaibles.
Yeah, they are bad libraries, but GML is somewhat to blame.
Its why i try to use globals a little as possible. so that my code wont polute other peoples.


The instance here will serve as a guard. A sort of namespace if you will.
Think of static variables in other languages. But here we use an instance instead.


Ok but then those people go off to make libraries and... yeah...


well, yeah...
but iAnimation.time is clearly time for the animation system. (iAnimation is how name instances in room editor.)

yes you could also have global.animation_time or globalvar ANIMATION_TIME.
but iAnimation.time is far neater IMO: it regroups your animation variables under a single instance scope.

at this point its a matter of taste, but i can tell you using instances like this will reduce clashes far more effectively, whilst making clear what the lifetime of the variable is, and what group of objects are expected to operate on it.

Then again, I really like the Actor Action model i proposed, and many people seem to disagree with my liberal use of instances there.
The downside of using your method is that unless I make the instance persistent, it won't truely be global, and as per my previous argument, that'd be a huge waste of resources.
It's not bad, it's simply not how I've learned to code.

Grouping values inside a 'group name' can be achieved with data structures like I mentionned earlier, and if you really want to use names for them you have enums and/or macros.

Code:
globalbar Animations;
enum Animation {
    Time,
    Speed,
    Type  
}

enum Animationtype {
    Type1,
    Type2,
    Type3
}

Animations = ds_list_create();
Animations[| Animation.Time] = 10;
Animations[| Animation.Speed] = 1;
Animations[| Animation.Type] = AnimationType.Type2;
No instances, they are grouped, and well made use of global variables. No waste of resources and No naming clashing.
Now note I re-used Animation as a name, I have no idea why you would name something Animation only, since that's so vague,
I'm just denoting my point to you. The way to do things makes the difference.

And as I mentionned, a bad library that has potential name clashing in it doesn't have its place in my project.
An asset should always prefix it's resources by the asest prefix. for example my CTB asset has all script prefixed by ctb_ this way there will never be any clashing.
Unless you use the same prefix as me.
 

GMWolf

aka fel666
The downside of using your method is that unless I make the instance persistent, it won't truely be global, and as per my previous argument, that'd be a huge waste of resources.
It's not bad, it's simply not how I've learned to code.

Grouping values inside a 'group name' can be achieved with data structures like I mentionned earlier, and if you really want to use names for them you have enums and/or macros.

Code:
globalbar Animations;
enum Animation {
    Time,
    Speed,
    Type 
}

enum Animationtype {
    Type1,
    Type2,
    Type3
}

Animations = ds_list_create();
Animations[| Animation.Time] = 10;
Animations[| Animation.Speed] = 1;
Animations[| Animation.Type] = AnimationType.Type2;
No instances, they are grouped, and well made use of global variables. No waste of resources and No naming clashing.
Now note I re-used Animation as a name, I have no idea why you would name something Animation only, since that's so vague,
I'm just denoting my point to you. The way to do things makes the difference.

And as I mentionned, a bad library that has potential name clashing in it doesn't have its place in my project.
An asset should always prefix it's resources by the asest prefix. for example my CTB asset has all script prefixed by ctb_ this way there will never be any clashing.
Unless you use the same prefix as me.
wow... you store variables in lists now?
I mean, if it was to be able to keep them in a single data unit, lie a struct, the sure...
but what you just wrote... that...its just goes against every programming principle out there! remind me why you are using GM again?
 
I use Ced's naming conventions, but I've never had a use for a global variable. Everything ends up in instances with me.

I also liberally use instances to execute code and then kill themselves, which I think is the Actor Action model *Fel is talking about. For me, it's all about easy to read, write, and change code. If I was worrying about the performance hit from an instance holding a variable, I sure as hell wouldn't be using GameMaker, haha! I'm a one man team. Who has time to worry about that kind of stuff? :'D

Edit: that *GMWolf is talking about, sorry. I know people by avatar moreso than by name I guess, haha!
 
Last edited:
C

CedSharp

Guest
wow... you store variables in lists now?
I mean, if it was to be able to keep them in a single data unit, lie a struct, the sure...
but what you just wrote... that...its just goes against every programming principle out there! remind me why you are using GM again?
I used a list to avoid adding a 2nd index and only to demonstrate something, I usually store finite data in grids.
I was demonstrating the grouping concept without the use of instances, but if this is how you treat it, then I see no reason to continue.
I clearly understand now that you didn't try to understand my point and instead felt attacked by my argument.
That was not the intention and I am sorry if I offended you in any way.

I wasn't saying that the way you store your values is wrong, I was merely pointing that global variables have their use and make sense, there is no need to 'avoid' them.
You felt the need to prove me wrong and I do not understand why, so I will let you have the privilege of thinking you are right.

All that to say, I do not like the idea of the keyword 'globalvar' being deprecated in favor to 'global' prefixed global variables.
 

GMWolf

aka fel666
I wasn't saying that the way you store your values is wrong, I was merely pointing that global variables have their use and make sense, there is no need to 'avoid' them.
And I was 'merely' pointing out why there is a need to avoid using them. But clearly you where offended by that?
globalvars and global. are not wrong, they just introduce problems that can easily be avoided.

But the whole using a list or a Grid. That I must object to. I really, really dont think its a good idea to use them that way.
I felt the need to 'prove' you wrong because this is a forum, and other people will be reading these. And i really do not want to see more code using such patterns.
If only because it means more code written that way to read when helping people on here. And trust me, I have read a LOT of code like that!
I remember in the GM8 days, using a global grid to emulate structures was used a lot! It was a massive pain.

I have more than once seen people on this very site get errors because of conflicting variables (Though, mostly between local and instance scopes). So I tend to recommend people stay away from globals as much as possible, and dedicate instances instead.

I clearly understand now that you didn't try to understand my point and instead felt attacked by my argument.
hence the conversation ender.
 
C

CedSharp

Guest
And I was 'merely' pointing out why there is a need to avoid using them. But clearly you where offended by that?
globalvars and global. are not wrong, they just introduce problems that can easily be avoided.

But the whole using a list or a Grid. That I must object to. I really, really dont think its a good idea to use them that way.
I felt the need to 'prove' you wrong because this is a forum, and other people will be reading these. And i really do not want to see more code using such patterns.
If only because it means more code written that way to read when helping people on here. And trust me, I have read a LOT of code like that!
I remember in the GM8 days, using a global grid to emulate structures was used a lot! It was a massive pain.

I have more than once seen people on this very site get errors because of conflicting variables (Though, mostly between local and instance scopes). So I tend to recommend people stay away from globals as much as possible, and dedicate instances instead.


hence the conversation ender.
How is using a "data structure" bad for "structuring" "data" ?
Using a grid to store information in a 2d structure is what it's meant for if I'm not mistaken.

I agree that it wasn't the best for a ds_list use case. A ds_list is more suited when the amount of entries is unknown before they are added into it or if it needs to be dynamic and add/remove items.

In the case of storing properties, the amount of properties are usually well known before the creation of the structure and so a ds_grid is more suited than a list, even if just using one dimention.

But I don't understand why you say it's a wrong usage of structures.
 
Top