ENIGMA Forums

Outsourcing saves money => Programming Help => Topic started by: intygamer on April 20, 2014, 11:04:42 am

Title: Not able to set or get userdefined variables with unique values for instances.
Post by: intygamer on April 20, 2014, 11:04:42 am
I am making a Civilization game.  Predefined variables like image_blend and sprite_index and x and y values work fine.

Variables that I define for the instances do not.  Like max_moves, which all instances take the value of last instance that was created for max_moves.  if I define the first 8 instances with 1 and the last with 3.  All instances with take the value of 3 for max_moves.

Here is my code.
Code: [Select]
------ Properties ------

Name: obj_unit
Parent: <no parent>
Sprite: <no sprite>
Mask: <same as sprite>
Visible: true
Solid: false
Depth: 0
Persistent: false
Total Lines of Code: 188

------ Events ------

  Create (21 Lines Of Code) :
0 Execute a piece of code (21 Lines)
**** BEGIN ****
//t0_list = ds_list_create();

var team;
var max_moves;
var ap;
var hp;

moves = 0;
//max_moves = 1;

var inst;

up = 0;  //unit pointer
sc = true;  //self control

image_speed = 0;
image_index = 0;

ng = 30;
grid = 30;
kp = false;
**** END ****

  Normal Step (7 Lines Of Code) :
0 Execute a piece of code (7 Lines)
**** BEGIN ****
if(sc = true)
{
with (obj_unit) {image_index = 0;}
inst = ds_list_find_value(t0_list,up);
inst.image_index = 1;
sc = false;
}
**** END ****

  Game Start (108 Lines Of Code) :
0 Execute a piece of code (108 Lines)
**** BEGIN ****
t0_list = ds_list_create();

//---------------------------------------Team 0

unit = instance_create(200,100,obj_unit); //Creates Unit at given position

unit.team = 0; //Team variable is set to [0]
unit.image_blend = c_yellow; //Team color is set to [yellow]
unit.sprite_index = spr_settlers; //Spawns [Unit X]
unit.max_moves = 1;
unit.ap = 1;
unit.hp = 10;

ds_list_add(t0_list,unit);

unit = instance_create(200,200,obj_unit); //Creates Unit at given position

unit.team = 0; //Team variable is set to [0]
unit.image_blend = c_yellow; //Team color is set to [yellow]
unit.sprite_index = spr_warrior; //Spawns [Unit X]
unit.max_moves = 1;
unit.ap = 5;
unit.hp = 20;

ds_list_add(t0_list,unit);

unit = instance_create(200,300,obj_unit); //Creates Unit at given position

unit.team = 0; //Team variable is set to [0]
unit.image_blend = c_yellow; //Team color is set to [yellow]
unit.sprite_index = spr_horsemen; //Spawns [Unit X]
unit.max_moves = 1;
unit.ap = 10;
unit.hp = 30;

ds_list_add(t0_list,unit);

//---------------------------------------Team 1

unit = instance_create(400,100,obj_unit); //Creates Unit at given position

unit.team = 1; //Team variable is set to [0]
unit.image_blend = c_red; //Team color is set to [yellow]
unit.sprite_index = spr_settlers; //Spawns [Unit X]
unit.max_moves = 1;
unit.ap = 1;
unit.hp = 10;

ds_list_add(t0_list,unit);

unit = instance_create(400,200,obj_unit); //Creates Unit at given position

unit.team = 1; //Team variable is set to [0]
unit.image_blend = c_red; //Team color is set to [yellow]
unit.sprite_index = spr_warrior; //Spawns [Unit X]
unit.max_moves = 1;
unit.ap = 5;
unit.hp = 20;

ds_list_add(t0_list,unit);

unit = instance_create(400,300,obj_unit); //Creates Unit at given position

unit.team = 1; //Team variable is set to [0]
unit.image_blend = c_red; //Team color is set to [yellow]
unit.sprite_index = spr_horsemen; //Spawns [Unit X]
unit.max_moves = 1;
unit.ap = 10;
unit.hp = 30;

ds_list_add(t0_list,unit);

//---------------------------------------Team 2

unit = instance_create(600,100,obj_unit); //Creates Unit at given position

unit.team = 2; //Team variable is set to [0]
unit.image_blend = c_blue; //Team color is set to [yellow]
unit.sprite_index = spr_settlers; //Spawns [Unit X]
unit.max_moves = 1;
unit.ap = 1;
unit.hp = 10;

ds_list_add(t0_list,unit);

unit = instance_create(600,200,obj_unit); //Creates Unit at given position

unit.team = 2; //Team variable is set to [0]
unit.image_blend = c_blue; //Team color is set to [yellow]
unit.sprite_index = spr_warrior; //Spawns [Unit X]
unit.max_moves = 1;
unit.ap = 5;
unit.hp = 20;

ds_list_add(t0_list,unit);

unit = instance_create(600,300,obj_unit); //Creates Unit at given position

unit.team = 2; //Team variable is set to [0]
unit.image_blend = c_blue; //Team color is set to [yellow]
unit.sprite_index = spr_horsemen; //Spawns [Unit X]
unit.max_moves = 3;
unit.ap = 10;
unit.hp = 30;

ds_list_add(t0_list,unit);

with (obj_unit) {move_snap(grid,grid);}
**** END ****

  press <Space> (1 Lines Of Code) :
0 Execute a piece of code (1 Lines)
**** BEGIN ****
moves = 0;
**** END ****

  press <Page Up> (3 Lines Of Code) :
0 Execute a piece of code (3 Lines)
**** BEGIN ****
up +=1;
if(up > (ds_list_size(t0_list) - 1)) {up = 0;}
sc = true;
**** END ****

  press <Page Down> (3 Lines Of Code) :
0 Execute a piece of code (3 Lines)
**** BEGIN ****
up -=1;
if(up < 0) {up = (ds_list_size(t0_list) -1);}
sc = true;
**** END ****

  press <Left> (10 Lines Of Code) :
0 Execute a piece of code (10 Lines)
**** BEGIN ****
if(kp = false)
{
if(moves < inst.max_moves)
{
inst.x -=ng;
move_snap(grid,grid);
moves +=1;
kp = true;
}
}
**** END ****

  press <Up> (11 Lines Of Code) :
0 Execute a piece of code (11 Lines)
**** BEGIN ****
if(kp = false)
{
if(moves < inst.max_moves)
{
inst.y -=ng;
move_snap(grid,grid);
moves +=1;
kp = true;
}
}

**** END ****

  press <Right> (10 Lines Of Code) :
0 Execute a piece of code (10 Lines)
**** BEGIN ****
if(kp = false)
{
if(moves < inst.max_moves)
{
inst.x +=ng;
move_snap(grid,grid);
moves +=1;
kp = true;
}
}
**** END ****

  press <Down> (10 Lines Of Code) :
0 Execute a piece of code (10 Lines)
**** BEGIN ****
if(kp = false)
{
if(moves < inst.max_moves)
{
inst.y +=ng;
move_snap(grid,grid);
moves +=1;
kp = true;
}
}
**** END ****

  release <Left> (1 Lines Of Code) :
0 Execute a piece of code (1 Lines)
**** BEGIN ****
kp = false;
**** END ****

  release <Up> (1 Lines Of Code) :
0 Execute a piece of code (1 Lines)
**** BEGIN ****
kp = false;
**** END ****

  release <Right> (1 Lines Of Code) :
0 Execute a piece of code (1 Lines)
**** BEGIN ****
kp = false;
**** END ****

  release <Down> (1 Lines Of Code) :
0 Execute a piece of code (1 Lines)
**** BEGIN ****
kp = false;
**** END ****

I am just using 1 object obj_unit.  Please let me know what I am doing wrong.

Thanks
Joe

Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: Goombert on April 20, 2014, 02:05:58 pm
Try to disable inheritance.
Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: intygamer on April 20, 2014, 06:57:44 pm
Try to disable inheritance.

I unchecked Object Inheritance in Build/Setting General tab.  That did not work.

Thanks
Joe
 
Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: time-killer-games on April 20, 2014, 07:23:21 pm
I occasionally have issues with custom variables as well and usually declaring them like so fixes the issue for me:
Code: [Select]
//suck my left hairy ball
var fuck, shit, dick, rectum;
fuck=-1;
shit=fuck:
dick=shit;
rectum=dick;
show_message(fuck);
Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: Darkstar2 on April 20, 2014, 08:05:26 pm
I occasionally have issues with custom variables as well and usually declaring them like so fixes the issue for me:
Code: [Select]
//suck my left hairy ball
var fuck, shit, dick, rectum;
fuck=-1;
shit=fuck:
dick=shit;
rectum=dick;
show_message(fuck);

Thanks for the heads up !  :D   Guess we'll all have something to remember when declaring variables ! :P
Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: intygamer on April 21, 2014, 08:16:04 pm
times-killer-games, I could not get your method to work either.

I put
Code: [Select]
var team, max_moves, ap, hp; In the creation event, then tried putting it in Game Start Event at the top.

Then I tried.
Code: [Select]
unit = instance_create(200,100,obj_unit); //Creates Unit at given position
var team, max_moves, ap, hp;
unit.team = 0; //Team variable is set to [0]
unit.image_blend = c_yellow; //Team color is set to [yellow]
unit.sprite_index = spr_settlers; //Spawns [Unit X]
unit.max_moves = 1;
unit.ap = 1;
unit.hp = 10;

ds_list_add(t0_list,unit);

Thanks
Joe
Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: Josh @ Dreamland on April 22, 2014, 07:43:40 am
If that is still giving you trouble, chances are, you aren't using those variables in obj_unit and they're being optimized out. You can argue the behavior is incorrect, but the alternative is disastrous. You can work around it by either referencing them in that object, or declaring them in it with [snip=EDL]local var team, max_moves, ap, hp;[/snip].

Polygone wrote something to work around that, but things tend to get broken, around here.
Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: intygamer on April 22, 2014, 09:01:44 pm
If that is still giving you trouble, chances are, you aren't using those variables in obj_unit and they're being optimized out. You can argue the behavior is incorrect, but the alternative is disastrous. You can work around it by either referencing them in that object, or declaring them in it with [snip=EDL]local var team, max_moves, ap, hp;[/snip].

Polygone wrote something to work around that, but things tend to get broken, around here.

I tryed [snip=EDL]local var team, max_moves, ap, hp;[/snip], the only thing it did was make the instances move 10 grid spaces instead of 1 per move.  All instances still made same amount of moves as the last instance created.

I only have 1 object in this game (obj_unit).  I don't see how they could be optimized out.

Is it possible to make a predefined variable like image_speed or image_index?

Thanks
Joe
 
Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: Josh @ Dreamland on April 25, 2014, 08:20:50 pm
That's what the local keyword does. It moves your declaration into the class scope. From the behavior you describe with the keyword in place, I'd say the code is working as intended, and the problem is more likely to lie in the code that works with those variables locally.
Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: intygamer on April 26, 2014, 06:53:43 pm
That's what the local keyword does. It moves your declaration into the class scope. From the behavior you describe with the keyword in place, I'd say the code is working as intended, and the problem is more likely to lie in the code that works with those variables locally.
Here's some questions to help me get my facts straight.  Sorry not figuring this out.

Question 1:  When creating an instance un = instance_create(200,100,obj_unit);and assigning values to built-in variables and user defined variables using id un.max_moves = 1;. These should be stored in the objects instance id and accessable to the object that created it.  if I have to access it outside the object that created it I would add prefix object_name.instance_id.variable?

Question 2:  The only thing ds_list is storing are the id's for all the instances and the list is global?

Question 3: The id numbers are globally accessable, but if your not coding inside the object that created it, you need to use the oject name prefix in front of dot id?

In Step Event:
Code: [Select]
if(sc = true)
{
with (obj_unit) {image_index = 0;}
un = ds_list_find_value(t0_list,up);        //variable up changes to switch to different instance id
un.image_index = 1;
sc = false;
}
In the step event the id is called from ds_list and put into "un" variable which is used in key events without calling ds_list in those events.
I believe this works because un.image_index changes and un.x and un.y values change correctly in the key events.

un.max_moves  Which is user defined only holds the value of the last instance created no matter what i assign the other ones, it will only use the value of the last instance created.

I created obj_text to see what variables are doing.
Code: [Select]
draw_set_font(font_arial);
draw_set_color(c_black);

draw_text(10,50,obj_unit.un.x);
draw_text(10,70,obj_unit.un.y);
draw_text(10,90,obj_unit.un.image_blend);
draw_text(10,110,obj_unit.un.team);
draw_text(10,130,obj_unit.un.max_moves);
draw_text(10,150,obj_unit.un.ap);
draw_text(10,170,obj_unit.un.hp);

Watching text display when switching to different id's,  the predefined variables change between instance id's x,y,image_blend like they are suppose to.  The 4 user defined variables remain at 0 when switching id's team, max_moves, ap, hp.

It seems like I have to do something special for the user defined variables?

I appreicate all your help!

Thanks
Joe



Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: TheExDeus on April 27, 2014, 05:43:06 am
Quote
if I have to access it outside the object that created it I would add prefix object_name.instance_id.variable?
You never add object_name. Instance_id is unique to each instance no matter what object they are. So instance_id.variable will work. object_name usually returns the oldest existing instance, so object_name.instance_id.variable would be like id.someotherid.variable, which is pretty much undefined.

Can you maybe post an example? I just tried adding instances to lists and changing them and it works fine for me.
Try this: https://www.dropbox.com/s/oaiuuppj2htmvnw/unit_test.gmk
Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: Josh @ Dreamland on April 27, 2014, 07:48:41 am
Q1:
By object_name.instance_id.variable, I assume you mean object_name.id.variable. That's the same, though, as saying object_name.variable. Once you have forced . to find you an instance, it has a definite result whose id will only point to itself. So you could just as well say object_name.id.id.id.id.id.id.id.id.variable, but why would you.

When you say obj_unit.x, your call is theoretically ambiguous, because there are probably multiple instances of obj_unit. ENIGMA deals with this by returning the first instance of that object, which won't always be what you want. This is where an ID comes in, which is why you stash the return value of instance_create: an ID of a specific instance of obj_unit. Note that obj_unit.id is the unambiguous ID of the current first instance of obj_unit. Which still isn't that helpful, because it'll remain the first instance (thus being accessible through only the object name) until it's destroyed, and then you don't want to be accessing it.

Q2:
Correct, on both counts. Those IDs won't change (but may be destroyed), and all lists are global.

Q3:
I did my best to explain this in Q1, but I'll clarify here. If you don't have the ID of a specific instance, then there's no way to access the exact instance you want, unless by chance there is only one instance of that particular object or you are always interested in the first. So if all you know is that you want some obj_unit, you don't really know a lot. However, there are methods to access *all* of the instances, as well as to narrow down some particular instance.

You seem to already be aware of the with statement. It lets you iterate over all instances of a given object, one at a time, changing the scope of the statement to each of their scopes as you go. This is the easiest way of accessing all instances.

What you want to access a specific instance with only an object index, normally you want something like the nearest instance or the instance that intersects some point. For those, you'd use instance_nearest and collision_point, respectively. These functions accept an object index and return an ID of some instance of that object.

You can keep lists of instances, as you are doing. But if you already have the ID of some instance, then looking that ID up in the list is probably not what you want to do. Instead of [snip=EDL]un = ds_list_find_value(t0_list,up); un.image_index = 1;[/snip], try just using [snip=EDL]up.image_index = 1;[/snip]. In your code, un is the index of the instance in your list, which is local to your list, while up is how ENIGMA refers to the instance.

That said, you really only need the list of units if there are many lists of units that you want to iterate over. Otherwise, you can iterate over all of them using with, as you are already doing once to zero the image_index values, and you can just use up to access the current instance of interest.
Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: TheExDeus on April 27, 2014, 11:56:12 am
Quote
You can keep lists of instances, as you are doing. But if you already have the ID of some instance, then looking that ID up in the list is probably not what you want to do. Instead of un = ds_list_find_value(t0_list,up); un.image_index = 1;, try just using up.image_index = 1;. In your code, un is the index of the instance in your list, which is local to your list, while up is how ENIGMA refers to the instance.
He doesn't hold instance ID in up. He holds an integer from 0 to ds_list_size(t0_list). So up.image_index won't work. So what he is doing now should theoretically work. And it works in the example I made.

I think he should give an example, because the code he has given is basically the "Object information" and changed it to show several objects. If that is not the case and that really is object information for obj_unit, then the problem is that he has a list in every obj_unit. And then he somehow tries to access it from other obj_units even though only one had it. So he implemented both the unit object and the unit controller object in one object. So I think there is something wrong with the way he implemented the whole thing in just one object.
Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: Josh @ Dreamland on April 27, 2014, 08:20:18 pm
I see. I had GM's find_value and the typical meaning of "find value" confused. I never use Game Maker's data structures; they're kind of terrible.
Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: Goombert on April 27, 2014, 08:21:32 pm
Yes but back in the interpreted days Josh it was well known they were much faster at data sorting then doing it yourself, etc. People usually encouraged their use over arrays.
Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: intygamer on April 27, 2014, 09:36:44 pm
Quote
if I have to access it outside the object that created it I would add prefix object_name.instance_id.variable?
You never add object_name. Instance_id is unique to each instance no matter what object they are. So instance_id.variable will work. object_name usually returns the oldest existing instance, so object_name.instance_id.variable would be like id.someotherid.variable, which is pretty much undefined.

Can you maybe post an example? I just tried adding instances to lists and changing them and it works fine for me.
Try this: https://www.dropbox.com/s/oaiuuppj2htmvnw/unit_test.gmk

obj_unit.un.x I only used this in draw event for obj_text before the modification I made in the attached file.  It would only show 0's for defined variable with un.x.  Prefixing un with the object_name fixed that.  Objects are not global.

I tried to modify old code to make it work with out object_name.id.variable.
Code: [Select]
with (ds_list_find_value(t0_list,obj_unit.up))
{
draw_text(10,50,x);
draw_text(10,70,y);
draw_text(10,90,image_blend);
draw_text(10,110,team);
draw_text(10,130,max_moves);
draw_text(10,150,ap);
draw_text(10,170,hp);
}

Thanks TheExDeus for that example.  I have attach an example for you.  I have modified it using controller object to create instances of obj_unit, like you have in your example.  Now I can see the userdefined values of the last instance with draw event instead of zero.  I still have the same problem, that only value for max_moves is coming from last instance created.

I the example arrow keys move units, pageup and pagedown key cycle threw units, and space bar resets moves back to zero.

Thanks
Joe
   
Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: intygamer on May 01, 2014, 06:43:21 pm
TheExDeus,
Not sure if file attachment works, can't see it when not logged in, so I added a link.  Let me know if you need it in different format.  This is the example you requested.

http://www.mediafire.com/download/fqryepq1knpmjwa/SwitchInstanceUserVariables.gm81 (http://www.mediafire.com/download/fqryepq1knpmjwa/SwitchInstanceUserVariables.gm81)

Thanks
Joe
Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: TheExDeus on May 02, 2014, 10:36:49 am
The bug is that you need to define the same variables in unit's create event as well. Like add these to obj_unit create:
Code: [Select]
team = -1;
max_moves = -1;
ap = -1;
hp = -1;
They can have any value as you will override them in obj_controller. I like to set them to undefined value like -1 so in debug I could find bugs easier.
I guess this is another parser bug as we technically support "Init undefined variables to 0". I think the parser cannot figure out if the variables are defined. In GM you probably would get the "Undefined variable" error. It trows the same error in ENIGMA as well. You should define variables before using them.
Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: intygamer on May 02, 2014, 02:14:45 pm
The bug is that you need to define the same variables in unit's create event as well. Like add these to obj_unit create:
Code: [Select]
team = -1;
max_moves = -1;
ap = -1;
hp = -1;
I declared the variables like you said and now the userdefined variables work.   (Y)

Thank you very much!  :)
And thanks to everyone that helped.
Joe
Title: Re: Not able to set or get userdefined variables with unique values for instances.
Post by: Goombert on May 03, 2014, 01:30:15 pm
Josh will fix these issues with his new compiler.