GML Check for object like "with obj.var"

S

Sylveax

Guest
Hi all
So I've been starting to create an AI, that should be able to have "teams". Every object, that uses the AI, contains a "team" variable. What I want to do now is to check for instances that contain the variable "team", and if this variable isn't the same as the checking instances "team", to aim at this instance.
I tried:
Code:
target = instance_nearest(x,y,all.team2)
direction = point_direction{x,y,target.x,target.y}
image_angle = direction
I can't seem to figure out how to do this. I would appreciate any and all help.
 

BlueBurn

Member
What about this ?
Code:
target = instance_nearest(x, y, obj_players);
if (target != noone and target.team != team)
{
direction = point_direction{x, y, target.x, target.y}
image_angle = direction
}
 

Bingdom

Googledom
Put this inside a script. Avoid using this too much, it can become resource intensive.
Code:
var ds = ds_priority_create();
with(obj_ai) if team != other.team ds_priority_add(ds, id, point_distance(other.x,other.y,x,y));
if ds_priority_empty(ds) {target = noone} else target = ds_priority_find_min(ds);
ds_priority_destroy(ds);
It no enemy is found, it will return noone.

What about this ?
Code:
target = instance_nearest(x, y, obj_players);
if (target.team != team)
{
direction = point_direction{x, y, target.x, target.y}
image_angle = direction
}
That only goes for the closest instance, and will have issues with multiple enemies.
 
Last edited:

jo-thijs

Member
That's terrible practice.
Why would you want to check every instance?
Do you have multiple objects you need to check?
If so, then why don't you use parents?
If not, then why would you want to do this anyway?

Create a parent object obj_team_parent with the following as only code:
Create event:
Code:
team = undefined;
Then make this object the parent of every object that has the "team" variable.

You can now do what you asked for as follows:
Code:
var n = noone;
var d, t;
with obj_team_parent
    if team != other.team {
        t = point_distance(x, y, other.x, other.y);
        if n == noone || t < d {
            d = t;
            n = id;
        }
    }

with n
    other.direction = point_direction(other.x, other.y, x, y);

image_angle = direction;
PS:
Doing exactly what you asked for is impossible in GM:S 1.*, but might be possible in GM:S 2.*
However, it remains bad practice anyway.
 

jo-thijs

Member
Well, I got double ninja'd, but I need to address some issues in the replies before me.

What about this ?
Code:
target = instance_nearest(x, y, obj_players);
if (target != noone and target.team != team)
{
direction = point_direction{x, y, target.x, target.y}
image_angle = direction
}
1) The question was to check every object in the project, not just 1 obj_players.
2) You search for the nearest instance of all teams, then you check if that instance is from a different team.
You need to perform the operations in the opposite order.
Now, if there is an enemy close to you, but there is a partner even closer to you, you won't shoot the enemy.
3) What are the curley brackets after point_direction for?
That's unvalid syntax and will throw an error before even running the game.

Put this inside a script. Avoid using this too much, it can become resource intensive.
Code:
var ds = ds_priority_create();
ds_priority_add(ds, noone, 9999999);
with(obj_ai) if team != other.team ds_priority_add(ds, id, point_distance(other.x,other.y,x,y);
return ds_priority_find_min(ds);
ds_priority_destroy(ds);
It no enemy is found, it will return noone.


That only goes for the closest instance, and will have issues with multiple enemies.
1) Again, the question was to check every object in the project, not just 1 obj_ai.
2) Your method doesn't work if the nearest enemy target is further than 9999999 pixels away.
You could have better left the value "noon" out of the queue and checked if the queue was empty before returning a result.
3) Your code creates a memory leak.
You do realize the last line of your script will never get executed as you've put a return statement before it, don't you?
4) Your code is not as performant as mine, as it needs constant reallocation of memory and ignoring that,
it would still perform in a time complexity O( n * log(n) ), whereas my code performs in a linear time O( n ).
I inicate with n the amount of instances searched through by the with structure and assume that with goes through
an instance in constant time and that the priority queues perform in a typical O( log(n) ) time complexity.
 
Last edited:

Bingdom

Googledom
1) Again, the question was to check every object in the project, not just 1 obj_ai.
2) Your method doesn't work if the nearest enemy target is further than 9999999 pixels away.
You could have better left the value "noon" out of the queue and checked if the queue was empty before returning a result.
3) Your code creates a huge memory leak.
You do realize the last line of your script will never get executed as you've put a return statement before it, don't you?
4) Your code is not as performant as mine, as it needs constant reallocation of memory and ignoring that,
it would still perform in a time complexity O( n * log(n) ), whereas my code performs in a linear time O( n ).
I inicate with n the amount of instances searched through by the with structure and assume with goes through an instance in constant time and that the priority queues perform in a typical O (log(n) ) time complexity.
1. I don't know what the main object is called. I usually just have obj_troop and have them fight against each other. That's it
2. I edited the original code, fixed
3. Fixed
Yes, fixed. I didn't have the original code with me at the time.
4. I didn't know there was another way. :)
 

jo-thijs

Member
1. I don't know what the main object is called. I usually just have obj_troop and have them fight against each other. That's it
2. I edited the original code, fixed
3. Fixed
Yes, fixed. I didn't have the original code with me at the time.
4. I didn't know there was another way. :)
There are still 2 issues with your code.
1) The variable "target" is better made local: var target = noone;
2) You should return the value of the variable "target" at the end

Or, you could change it to not be a script and say that the result is contained in the variable "target".
 

Bingdom

Googledom
Yes true but I would still use the variable target in many places inside my object, I don't need to assign it to another variable.

Also, it helps to put it as a script because I might want other objects to use it and have the same behaviour, if I was to make adjustments in the future.
 
Top