Legacy GM [SOLVED]Instance nearest

A

Andrea N

Guest
Hi all,
I have one object enemy and more object player (multiplayer game).
Obj_enemy have to follow the nearest player, but only if a variable of obj_player is true. For example inside obj_player variable "follow_me"= true or false.
Now i have to check from obj_enemy step event:
If instance_exists(obj_player){
If (obj_player.follow_me == true){
player_to_follow=instance_nearest(x,y,obj_player);
move_towards_point(player_to_follow.x,player_to_follow.y,speed);}
Else{player_to_follow=0;
Obj_enemy.speed=0;}
}else{player_to_follow=0;
Obj_enemy.speed=0;}

When obj_enemy is following obj_player, and i change the obj_player.follow_me variable, obj_enemy stops to follow obj_player, and it's ok! But if obj_player are more than one, i need to follow the other obj_player.follow_me = true; !
How can i find the instance_nearest(x,y,obj_player.follow_me==true)???
I hope i explained myself, thanks
 

MIchael PS

Member
Just do that:

Code:
If instance_nearest(obj_player).follow_me == true
    {
        ...
    }
EDIT: Oh I actually misunderstood what you asked for! Sorry...
 
Last edited:

Simon Gust

Member
It's not that easy unfortunately.
You can use a with statement to go through every player object, check if their follow variable is true, then find the nearest one.
Code:
var player_to_follow = noone;
var distance = 1000000000;
var xx = x;
var yy = y;

with (obj_player)
{
    if (follow_me)
    {
        var my_dis = point_distance(x, y, xx, yy);
        if (my_dis < distance)
        {
            player_to_follow = id;
            distance = my_dis;
        }
    }
}

if (player_to_follow != noone)
{
    var player_x = player_to_follow.x;
    var player_y = player_to_follow.y;
    var spd = min(point_distance(x, y, player_x, player_y), 3.0); 
    move_towards_point(player_x, player_y, spd);
}
I also advise reading this
https://forum.yoyogames.com/index.php?threads/with-block-recipe-cards.25326/
and this
https://forum.yoyogames.com/index.php?threads/whats-the-difference-objects-and-instances.29005/
 
if you ganna use instance_nearest you need to deactivate the instance in a loop.
something like this, I'm in my phone so I'm not 100% about the syntax

while true {
o = instance_nearest(x,y,obj_player)
if o == noone || o.follow_me == true {
break
} else {
deactivate_instance(o)
}
}
activate_all(obj_player)
if o != noone {
//follow
}
 
A

Andrea N

Guest
It's not that easy unfortunately.
You can use a with statement to go through every player object, check if their follow variable is true, then find the nearest one.
Code:
var player_to_follow = noone;
var distance = 1000000000;
var xx = x;
var yy = y;

with (obj_player)
{
    if (follow_me)
    {
        var my_dis = point_distance(x, y, xx, yy);
        if (my_dis < distance)
        {
            player_to_follow = id;
            distance = my_dis;
        }
    }
}

if (player_to_follow != noone)
{
    var player_x = player_to_follow.x;
    var player_y = player_to_follow.y;
    var spd = min(point_distance(x, y, player_x, player_y), 3.0);
    move_towards_point(player_x, player_y, spd);
}
I also advise reading this
https://forum.yoyogames.com/index.php?threads/with-block-recipe-cards.25326/
and this
https://forum.yoyogames.com/index.php?threads/whats-the-difference-objects-and-instances.29005/

I tried your script and i added some changes:

if (instance_exists(obj_player)){
var player_to_follow = noone;
var distance = 500;
var xx = x;
var yy = y;
var enemyRoom = npcRoom;

with (obj_player)
{
var my_dis = point_distance(x, y, xx, yy);

if (enemyRoom == playerRoom)
{
if (my_dis > distance)
{
player_to_follow = noone;
}
else
{
if (my_dis < distance)
{
player_to_follow = id;
//distance = my_dis;
}
}
}
}


if (player_to_follow != noone)
{
var nearest_player_to_follow = instance_nearest(x,y,player_to_follow);
//var player_x = nearest_player_to_follow.x;
//var player_y = nearest_player_to_follow.y;
//var spd = min(point_distance(x, y, nearest_player_to_follow.x, nearest_player_to_follow.y), 1);
move_towards_point(nearest_player_to_follow.x, nearest_player_to_follow.y, 1);
npcxx=x;
npcyy=y;
}
else{x=npcxx;
y=npcyy;}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

I added the line "var nearest_player_to_follow = instance_nearest(x,y,player_to_follow);" because with your script, when i have more than one player near the obj_enemy and both obj_player have "my_dis < distance",(so both obj_player have "player_to_follow = id;") ,
if obj_enemy is following obj_player(1) and another obj_player(2) running, and the last become the nearest, obj_enemy stops to move until obj_player(1) comes back to be the nearest obj_player!

So i thought to use "instance_nearest"! But i get an error:

FATAL ERROR in
action number 1
of Step Event0
for object obj_npc:

Variable <unknown_object>.y(1, -2147483648) not set before reading it.
at gml_Object_obj_npc_StepNormalEvent_1 (line 35) - move_towards_point(nearest_player_to_follow.x, nearest_player_to_follow.y, 1);

But i use this :
if (player_to_follow != noone)
{ .....code.....}

So, why this error??
 
A

Andrea N

Guest
if you ganna use instance_nearest you need to deactivate the instance in a loop.
something like this, I'm in my phone so I'm not 100% about the syntax

while true {
o = instance_nearest(x,y,obj_player)
if o == noone || o.follow_me == true {
break
} else {
deactivate_instance(o)
}
}
activate_all(obj_player)
if o != noone {
//follow
}
Thanks, but i need the instances always active so i can't use this
 
A

Andrea N

Guest
Just do that:

Code:
If instance_nearest(obj_player).follow_me == true
    {
        ...
    }
EDIT: Oh I actually misunderstood what you asked for! Sorry...
Yes i can do as you wrote, like this:

var player_to_follow = instance_nearest(x,y,obj_player);
if (player_to_follow.playerRoom == npcRoom){move_towards_point(player_to_follow.x, player_to_follow.y, 1);}

BUT, if the "instance_nearest(x,y,obj_player) have variable "playerRoom != npcRoom", I have to discard it, and i have to find the nearest obj_player ONLY IF it have "playerRoom = npcRoom";

Do you understand now?
 
Deactivating and activate a instance in the same code wont affect the game in anyway.
The only problem it can cause is if you do other stuff with deactivating instance which can collide with this code.
But you can fix that by adding them to a list and then activate every instance in that list when you're done.
 
A

Andrea N

Guest
Deactivating and activate a instance in the same code wont affect the game in anyway.
The only problem it can cause is if you do other stuff with deactivating instance which can collide with this code.
But you can fix that by adding them to a list and then activate every instance in that list when you're done.
Thanks, your solution works perfectly, but there must be another way, and i hope to find it!
 
instance_nearest simply return the nearest instance. you can't do any other checks directly with that function. you can either (as I showed) deactivate the instance to return a new instance the next time you run the function, or move the instance away (x += 999999) to also return a new instance then move back all the found instances (X -= 999999).

or you would have to make up your own system as @Simon Gust showed. which is probably the better choice since it only have to check each instance once. instance_nearest have to check all instances once for every time it run.
 
Top