• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Legacy GM [solved] A question about using 'WITH'

Hi.

I am trying to set up an object so that, if it falls under certain conditions, it has certain pieces of information already stored under local variables when accessed later in a for loop by another object.

The idea is that, rather than a lot of calls for a permanent variable, it has it beforehand within the event, and presumably is less costly.

I can get this to work in part, but for some reason it only works with one instance. You can ignore most of the code, as it's basically seeing if two rectangles are in contact. I can see when they are active, as I've set them to change colour.

Code:
with (is_mine)
{
was_bullet_coll = true;
single_path_pos = floor(path_position * single_path_num);
if bbox_bottom > cur_top
{
var side_top = y - radius;
var side_bot = room_height;
var side_left = self_left_side;
var side_right = self_right_side;
var self_volume = side_right - side_left * (side_bot - side_top);

var min_vol = min(self_volume, other_volume);
switch (min_vol)
{
case self_volume:
var min_left = side_left;
var min_top = side_top;
var min_right = side_right;
var min_bot = side_bot;
var max_left = new_left;
var max_top = new_top;
var max_right = new_right;
var max_bot = new_bot;
break;
case other_volume:
var min_left = new_left;
var min_top = new_top;
var min_right = new_right;
var min_bot = new_bot;
var max_left = side_left;
var max_top = side_top;
var max_right = side_right;
var max_bot = side_bot;
break;
}

if rectangle_in_rectangle(min_left, min_top, min_right, min_bot, max_left, max_top, max_right, max_bot)
{
was_bullet_coll = false;
var self_path = mine_path;
}
}
}

for (var path_point = is_bullet_step; path_point < bullet_path_num; path_point++)
{
path_x = path_get_point_x(bullet_path, path_point);
path_y = path_get_point_y(bullet_path, path_point);
instance_create(path_x,path_y, obj_pointer);

new_left = path_x - is_bull_width;
new_top = path_y - is_bull_width;
new_right = path_x + is_bull_width;
new_bot = path_y + is_bull_width;

with (is_mine)
{
if !was_bullet_coll
{
image_blend = c_black; <<<< I can see this happening
new_path_pos = single_path_pos + path_point;
if new_path_pos < single_path_num
{
is_point_x = path_get_point_x(self_path, new_path_pos);
is_point_y = path_get_point_y(self_path, new_path_pos);
instance_create(is_point_x, is_point_y, enemy_mine); <<<< Only happens for one instance. Works with all (that it should) if they call the path through the stored variable, and not the local one
}

if rectangle_in_circle(new_left, new_top, new_right, new_bot, is_point_x, is_point_y, self_radius) != 0
{image_blend = c_red;
other.do_left_mine = true;
was_bullet_coll = true;
}
}
}
}
It is getting the local variable of 'self_path', but only one instance is responding to it. I can see that there are others "active", as their colour changes from the "image_blend = c_black" code, but only one ends up doing their code for the path (creating an object along the path to make the results visible)

It seems to have the local variable held when accessed later, but goes wrong after that. Any ideas why?
 
Last edited:

FrostyCat

Redemption Seeker
You appear to have a with (is_mine) inside a with (is_mine). Indent your code and completely trace out the scoping relationships (i.e. who is self and who is other), then you should see what's wrong.
 
You appear to have a with (is_mine) inside a with (is_mine). Indent your code and completely trace out the scoping relationships (i.e. who is self and who is other), then you should see what's wrong.
You no doubt understand what I'm trying to do, so my apologies if any of this comes across as redundant. But I am not so familiar with the workings of local variables, with, and scripts etc.

A quick example:
I have two objects (object2, and object3)

This script is running in object3, which has only one instance in a room
Code:
var is_y = y;

with (object2)
{
var is_dog = false;
if bbox_bottom > is_y
{
is_dog = true;
}
}

with (object2)
{
if is_dog
{
image_blend = c_black;
}
}
Even though it is within the same script, I am not seeing the local variable held for when the WITH object is accessed the second time. Is that the result it should be?
 

FrostyCat

Redemption Seeker
Why don't you combine the contents of both with blocks if they'll be targeting the same subject anyways?
 

Toque

Member
In the bottom with (object2)

If is_dog .......

If is_dog. What about it? Exists? >100 or what?

I didn’t read through all the code but I would think if is_dog is a variable it should be checked for something ??
 

Evanski

Raccoon Lord
Forum Staff
Moderator
In the bottom with (object2)

If is_dog .......

If is_dog. What about it? Exists? >100 or what?

I didn’t read through all the code but I would think if is_dog is a variable it should be checked for something ??
In game maker if you check if its true you dont need to specify that, gm will read it as if is_dog == true
its not a good practice to do, but in gml it works (im not advocating it)

This also works in reverse with if !is_dog
 
Last edited:

curato

Member
In game maker if you check if its true you dont need to specify that, gm will read it as if is_dog == true
its not a good practice to do, but in gml it works (im not advocating it)

This also works in reverse with if !is_dog
I agree. I don't do that or use with. I just don't think they promote readable self documenting code.
 

Evanski

Raccoon Lord
Forum Staff
Moderator
I agree. I don't do that or use with. I just don't think they promote readable self documenting code.
I use with when I need it for certain things like passing values back and fourth, that only the script and object need, but yeah when I was first starting gms I did the whole if a {blah blah}, I cant read that code now, i have no idea what a is
so i dont use that
 

FrostyCat

Redemption Seeker
In the bottom with (object2)

If is_dog .......

If is_dog. What about it? Exists? >100 or what?

I didn’t read through all the code but I would think if is_dog is a variable it should be checked for something ??
In game maker if you check if its true you dont need to specify that, gm will read it as if is_dog == true
its not a good practice to do, but in gml it works (im not advocating it)

This also works in reverse with if !is_dog
Comparing to true and false is the bad practice, stop spreading this nonsense.

First of all, if value == true is absolutely not the same as if value. The first checks for equivalence against true and returns true/false from that, while the second is an implicit typecast (i.e. the >= 0.5 check). If the value is not strictly a Boolean (e.g. collision_line() or rectangle_in_rectangle()), the comparison fails to behave as expected and lots of novices get caught unaware by this.

Secondly, comparing to true and false means you don't see the Boolean value that the == operator gives, and not knowing exactly how expressions are evaluated is a serious defect as a programmer. And in case you think this is a GML-only thing, read these:

Python PEP 8
Don't compare boolean values to True or False using ==.

Yes: if greeting:
No: if greeting == True:
Worse: if greeting is True:
University of Washington, first year CS style guide
Do not compare to 'true'
Never directly compare a value against true – doing so is redundant. That is, never do someExpression == true. Instead, do someExpression instead, which is exactly equivalent.

After all, since someExpression is a boolean, comparing it to a boolean will just produce yet another boolean, which is redundant.
Mozilla coding style guide
Do not compare x == true or x == false. Use (x) or (!x) instead. x == true, in fact, is different from if (x)!

I agree. I don't do that or use with. I just don't think they promote readable self documenting code.
Explain how with blocks discourage self-documenting code. It's only non-self-documenting when you aren't educated in its proper use.
 

curato

Member
Explain how with blocks discourage self-documenting code. It's only non-self-documenting when you aren't educated in its proper use.
I hold a degree in computer science; I think I got it thanks! Knowing how to use them and thinking they are good idea when there are more readable ways to get there and you see post about people confused about them all the time.

I use with when I need it for certain things like passing values back and fourth, that only the script and object need, but yeah when I was first starting gms I did the whole if a {blah blah}, I cant read that code now, i have no idea what a is
so I don't use that
I agree. I am not a fan of them, but really do wish they would stop with in tutorials. It just isn't slick to show off everything you know to assign five variables when you only got one of the objects in the room to start with.
 
Last edited:

Evanski

Raccoon Lord
Forum Staff
Moderator
Comparing to true and false is the bad practice, stop spreading this nonsense.

First of all, if value == true is absolutely not the same as if value. The first checks for equivalence against true and returns true/false from that, while the second is an implicit typecast (i.e. the >= 0.5 check). If the value is not strictly a Boolean (e.g. collision_line() or rectangle_in_rectangle()), the comparison fails to behave as expected and lots of novices get caught unaware by this.

Secondly, comparing to true and false means you don't see the Boolean value that the == operator gives, and not knowing exactly how expressions are evaluated is a serious defect as a programmer. And in case you think this is a GML-only thing, read these:

Python PEP 8

University of Washington, first year CS style guide

Mozilla coding style guide




Explain how with blocks discourage self-documenting code. It's only non-self-documenting when you aren't educated in its proper use.
I always thought that was the other way around, thank you for the info
 

FrostyCat

Redemption Seeker
I hold a degree in computer science; I think I got it thanks!
Guess what, so do I.
Knowing how to use them and thinking they are good idea when there are more readable ways to get there and you see post about people confused about them all the time.
I often see people getting confused about what mod does in mundane pieces of code. Would you then advocate against using mod?

Everything is confusing for someone who is sufficiently ignorant or mis-educated. It makes no sense to say that something isn't self-documenting just because there are people taught the wrong way.
 

curato

Member
I often see people getting confused about what mod does in mundane pieces of code. Would you then advocate against using mod?
mod is awesome. I will leave it at that.

I always thought that was the other way around, thank you for the info
Yeah, it is especially true (no pun intended) in GML since true and false aren't technically a boolean value to the engine.
 
Give a pretty simple example, and still don't get a simple answer......

what is is_dog? a boolean value of 'true' or 'false'

I'm setting it as a local variable in the first WITH block, and then accessing another WITH block to see if the same object still holds that local variable when accessed later in the same event.

Why am I doing that? Uh....because I want to see if I can set up an object to have a local variable prior to accessing it again in a for loop.

If I really have to go into the reason for that:
during the loop it will have to look up a variable holding details of a path. If I can define that as a local variable before going into the for loop, then it has less lookup needed?

I don't know if that has any merit, or if it's possible - hence me asking. If it's dumb: it's dumb. If it's not dumb: is there a reason why it won't work?
 
Why don't you combine the contents of both with blocks if they'll be targeting the same subject anyways?
If I repeatedly look up a path index through a stored variable, is it not better to have it as a local variable within the event? So that is why they are accessed twice.

If so - I am looking at how I can do that within an event where it's using a with reference. As that seems to be your recommendation for accessing other objects, rather than putting them into a list or other data structure that requires a further for loop to go through it.
 

curato

Member
assigning a global variable to a local variable has been shown to have a modest performance increase in the compiled version of the game, but isn't functionally required. Also, if I am understanding correctly, if you assign a local variable once you shouldn't need to check if it is still assigned as long as you running all this code in the same object same event. The only time I have seen need for an extra double check is where I am setting a global in one object that will be needed in another object. In that case you may need some double check code that everything is assigned correctly since in that case both sets of code are running at the same time.
 
assigning a global variable to a local variable has been shown to have a modest performance increase in the compiled version of the game, but isn't functionally required. Also, if I am understanding correctly, if you assign a local variable once you shouldn't need to check if it is still assigned as long as you running all this code in the same object same event. The only time I have seen need for an extra double check is where I am setting a global in one object that will be needed in another object. In that case you may need some double check code that everything is assigned correctly since in that case both sets of code are running at the same time.
This is a local variable in the "with" object, not the object calling the script.

So that, when it is accessed in a for loop by the object running the script, it does not have to constantly look up a stored variable.

But it has to be defined before the calling object does the loop, and then still be present when accessed a second time as the loop is done.
 

FrostyCat

Redemption Seeker
I'm setting it as a local variable in the first WITH block, and then accessing another WITH block to see if the same object still holds that local variable when accessed later in the same event.
You seem to be confusing the roles of local variables with instance variables.
  • Local variables (those declared with var) belong to the current entire piece of code, not to any instance, and they expire at the end of the entire piece of code.
  • Instance variables (those not declared with var) belong to instances, and they persist for as long as the owning instance exists.
Local variables are temporary values, instance variables are properties. Read the Manual entry on scope.

When you did this:
Code:
var is_y = y;

with (object2)
{
var is_dog = false;
if bbox_bottom > is_y
{
is_dog = true;
}
}

with (object2)
{
if is_dog
{
image_blend = c_black;
}
}
You are not giving each object2 instance its own is_dog, you are using a single is_dog local variable and setting that repeatedly. The last instance of object2 that the first with block loops over has the final say on the value of is_dog, and then the second with block sets every object2 instance's colour blending to black according to the single local is_dog. That won't give an individualized result.

This would have given the proper result:
Code:
var is_y = y;
with (object2) {
  if (bbox_bottom > is_y) {
    image_blend = c_black;
  }
}
As for what's wrong with your opening piece of code, you need to know the difference between a nested block and two blocks side by side. Looking at with blocks alone, this is your code in the opening post:
Code:
with (is_mine) {
  ...A...
  with (is_mine) {
    ...B...
  }
}
And this is your code from post #3:
Code:
with (object2) {
  ...A...
}
with (object2) {
  ...B...
}
These two are not at all alike.
  • The first piece of code will attempt to access is_mine.is_mine (given that I don't see var is_mine), but the second piece of code will not attempt to access object2.object2.
  • In B of the first piece of code, other actually refers to is_mine, not the original calling instance (see this post for what happens when with blocks get nested). In both A and B of the second piece of code, other refers to the original calling instance.
This is why I asked you to indent your code and check the nesting. I don't think your nesting is done right, and it's breaking your code. And indenting helps reveal these problems.
 

samspade

Member
I hold a degree in computer science; I think I got it thanks! Knowing how to use them and thinking they are good idea when there are more readable ways to get there and you see post about people confused about them all the time.
with () basically functions like a for each loop with implicit existence checking. It seems incredibly useful and not at all hard to understand - at least it is much easier than many other programming concepts. I'm curious what your alternative is especially for something like checking all instances of a class.

Code:
with (parent) {
     //do a thing
}
 
You are not giving each object2 instance its own is_dog, you are using a single is_dog local variable and setting that repeatedly. The last instance of object2 that the first with block loops over has the final say on the value of is_dog, and then the second with block sets every object2 instance's colour blending to black according to the single local is_dog. That won't give an individualized result.
If I understand this correctly: The with code is accessing the objects, but the local variable is not in relation to them - it is within the event (i.e the "other" object)
 

Toque

Member
In game maker if you check if its true you dont need to specify that, gm will read it as if is_dog == true
its not a good practice to do, but in gml it works (im not advocating it)

This also works in reverse with if !is_dog
Ok. Thanks.
 
Top