GameMaker Getting Object Variable With No Instance

jo-thijs

Member
I'm using GM2, and with the nice macro features, one can "replace" any bit of information by any bit of code.
Code:
#macro Enemy.count global.EnemyCount
// I can now use Enemy.count in the game, and at compile time it will be replaced by global.EnemyCount.
I agree it's just eye-candy, but it makes my eyes happy when I read my code.
That doesn't work though, you cannot use periods in macro names.
GM will interprete it as though you defined "Enemy" as ".count global.EnemyCount".

This sounds like you're misunderstanding instantiation in GMS as a whole. Code placed in the object form are not constants as such, and none of the values will exist if there are no instances of the objects.

I read this whole thread twice and still seem to be misunderstanding the issue. It seems a bit like you're trying to apply something from another language that isn't really applicable at all.

Are you trying to access variables set in a code form in an event of an object that is never created? None of those events are performed if the instance never exists.

Why wouldn't you use global values or just create a controller object that handles these "static fields"?
Yes, that's what he's trying to do.

He wants to associate a value "gold_buy" to some objects, so that the value only depends on the object index.
For example, buying item 1 will cost 100 gold, buying item 2 will cost 250 gold.
In java, this would conceptually correspond to static variables.

He then obtains an object index in some variable "obj" and wants to retrieve the associated "gold_buy" value.
This is where the analogy with java fails.
This is also why just using global variables won't suffice.

He also wants to organize his code in a specific way though.
He doesn't like putting the values of "gold_buy" in 1 spot, but wants to have the values be declared in proximity to the objects they relate to (in their create events for example).
Hence, he doesn't like the controller solution, as the values would be defined somewhere outside the objects they relate to.

I believe it would be best to just have a global variable "global.gold_buy_map" that contains a ds_map that maps object indices to their respective "gold_buy" values,
to have a script "scr_associate_gold_buy(object, value)" that checks if the global variable has been initialized and initializes it with a newly created ds_map if not and then adds the new association to it.
Finally, using gml_pragme with "global" as first argument, he can call this script in the create event of all the relevant objects to make the associations in exactly te way he wants it to be organized.
The only disdvantge is that he'd be working with something of the form "global.var_name[?'obj']" or by using a script for it instead of using "obj.var_name".
This doesn't seem like a bad trade off though.

There are multiple tricks to know if the global variable has been initialized in GM:S 2.
First of all, there is just a function whoms purpose is just that, so that can be used.
Alternatively (I don't know if it's better), there's some trick with arrays that can be used.
Code:
global.inited[1] = 0;
if global.inited[0] == 0 {
    // initialize your other global variables
    global.inited[0] = 1;
}
 
A

Ampersand

Guest
Your explanation is both an excellent solution as well as a decent example as to why it's often easier to learn to work with the data at hand rather than to find a way to pretend like you're using another language. To each his own though, I suppose!
 
L

lisa7306

Guest
Yeah, I'll tinker with the grid and array. Thanks for the help.
 

jo-thijs

Member
I just wanted to add this if someone in the future would ever want to use my last suggestion in GameMaker:Studio 1 where gml_pragma doesn't exist.

You can reserve a "user defined event" containing all the gml_pragma code.
You can then add an object to your game that just serves to execute gml_pragma code.
In its create event, it iterates over all objects (you can put this object at the bottom of the resource tree and iterate over all indices from 0 up to its own object index).
For every object index iterated over, it executes their "user defined event" through event_perform_object.
The object then proceeds to either destroy itself or do nothing but being persistent.
This object would then be placed in the first room of your project and the create events would be ordered so that this object's create event gets executed first.

Yeah, I'll tinker with the grid and array. Thanks for the help.
Hi and welcome to the GMC!

We're glad we could help.
 

AriesGames

Member
Maybe there is no need for me to comment on this thread. But I can't help myself.

Why would you want to do that this way? There are like ten other ways to do this, which are easier to implement, some maybe even faster. O.O

The structural behavior of GML, the relation between objects and instances, are there for a reason. What I mean by that, it is build this way for a very strict reason.

It's like trying to reinvent the wheel on a car that has better wheels already.
Yes you could probably write a script that makes a value of a variable be connected to a certain object index. But why would you want to do that?
That's why parenting and object-instance relation exist. For that exact reason. >.<

Sorry if I offended other users, coming this from my "mouth", but just the idea bugs my mind, sorry...hehe...
 

jo-thijs

Member
Maybe there is no need for me to comment on this thread. But I can't help myself.

Why would you want to do that this way? There are like ten other ways to do this, which are easier to implement, some maybe even faster. O.O

The structural behavior of GML, the relation between objects and instances, are there for a reason. What I mean by that, it is build this way for a very strict reason.

It's like trying to reinvent the wheel on a car that has better wheels already.
Yes you could probably write a script that makes a value of a variable be connected to a certain object index. But why would you want to do that?
That's why parenting and object-instance relation exist. For that exact reason. >.<

Sorry if I offended other users, coming this from my "mouth", but just the idea bugs my mind, sorry...hehe...
I don't think you offended anyone.

The idea isn't that crazy though.
You want to know how much gold some item will cost before you place that item (an item could be a tower in a tower defense game).
You'll have to specify this price somewhere, but ideally it must be specified before instances of that item are created.
You could specify the prices of all buildings in some controller object together,
but then you'd have to remind yourself to keep updating the controller object every time you add or remove an item object to or from your project.
It might be more convenient to specify the price of the items in the code of the items themselves.
 

AriesGames

Member
@jo-thijs
What you are saying is true, I wanted to tell you the controller thing before reading it you specified about it. Well if that's the case...
Hence I am using my controller object as a global spawner I don't think I can forget about it when I create a new item.
But yea you're right, that's just how I see things. Even further, I had once a problem I wasn't finding a value because it wasn't specified in the controller.
I got confused and searched it like a madman. This depends very much on organization view of each person.
That happened because I didn't specify a global strict place for values to be stored in.
You create multiple objects and let's just say you forget to put a value in the most logical place, you end up later searching it like nuts.

But I am sure not one of those people who would just create scripts to help with storing values.
If you follow your way, I am not saying it's a bad one, then each entity in your game is it own controller.
That just seems like a mess from my perspective...
 
G

GreenWolfGames

Guest
Could you potentially just place all of the objects you want to reference in an invisible layer and then duplicate that layer into all of the different rooms. (although I'm not totally sure if you can duplicate layers like that). Then you'd be able to access the information whenever you want, and only go through the trouble of instantiating it once? (Unless I'm missing something)
 
C

CedSharp

Guest
Just create global values prefixed with object name, or use global data structures. Objects in GameMaker are not directly accessible, you work with handles (instance id).

It is not possible to create a static field in an object you don't even have access to.
 

jo-thijs

Member
Could you potentially just place all of the objects you want to reference in an invisible layer and then duplicate that layer into all of the different rooms. (although I'm not totally sure if you can duplicate layers like that). Then you'd be able to access the information whenever you want, and only go through the trouble of instantiating it once? (Unless I'm missing something)
That's basically Ghost in the IDE's suggestion, only he automated it through code.

Just create global values prefixed with object name, or use global data structures. Objects in GameMaker are not directly accessible, you work with handles (instance id).

It is not possible to create a static field in an object you don't even have access to.
That's basically my suggestion, but with less structure.
 
C

CedSharp

Guest
my moral is, if its moving and doing stuff, its an instance, if not, its an array
how about data structures? (ds_* scripts)

Also, op is asking how to read a value from an object instead of an instance. He wants the equivalent of static properties in classes in other languages.

Say you have object 'oEnemy' and instance 'enemy1, enemy2, enemy3'.
He wants to be able to do something like 'oEnemy.count++' in the create event of an instance so that after creating 3 instances, 'oEnemy.count' is 3.

For some random reason, he doesn't like the idea of that 'count' variable being inside another object because it doesn't feel right with him. The answer to this post is that static fields do not exists and you can't avoid creating an instance or a global variable if you want to store information.
 
G

greenystone

Guest
+1 for static properties

That's what I'm missing too, instead of messing with global variables, you can have clear visibility of statics: they relation in object hierarchy and still visible from anywhere. Global variables are ok, but mostly I would replace it with something related to object if possible.
 
C

CedSharp

Guest
You can simply access instance variable like if they were static values. The only thing currently impossible in GameMaker is accessing anything from an object if there is no instance.

Code:
// Create Event
var _maxCount=0;
with(object_index) _maxCount = max(count, _maxCount);
with(object_index) count = _maxCount+1;
The above piece of code finds the largest count variable in all instances (there should be only one instance, the current one, which doesn't have the latest value since it was just created) and then set all instance's count variable to +1. This isn't straightforward but does the same result.
 
Top