GM:S 1.4 Instance_nearest BUT not me?

Discussion in 'Programming' started by MIchael PS, Jul 16, 2018.

  1. MIchael PS

    MIchael PS Member

    Joined:
    Aug 12, 2017
    Posts:
    95
    Hi!!!

    I use instance_nearest to check for an object. But the object I am searching for is the same object type as the object calling the "instance_nearest". So it finds itself as the nearest object. How can I fix it so that it checks for all the others instances instead of its own? (Note that I can't -don't want to- make it a different object)

    Thank you for your time,
    Michael
     
  2. warbo

    warbo Member

    Joined:
    Jul 5, 2016
    Posts:
    96
    Can you not use "ID"
     
    MIchael PS likes this.
  3. Kyon

    Kyon Member

    Joined:
    Jun 27, 2016
    Posts:
    469
    These are some scripts I found for you on google, haven't tested it but looks fine! :)


    #1 A function that returns the nth nearest instance. Simply input 2 to get the nearest instance excluding yourself:
    Code:
    ///instance_nth_nearest(object, x, y, n);
    
    var arg_obj = argument[0];
    var arg_x = argument[1];
    var arg_y = argument[2];
    var arg_n = argument[3];
    
    var list = ds_priority_create();
    arg_n = clamp(arg_n, 1, instance_number(arg_obj));
    var nearest = noone;
    
    with (arg_obj)
    {
    ds_priority_add(list, id, distance_to_point(arg_x, arg_y));
    }
    
    repeat (arg_n)
    {
    nearest = ds_priority_delete_min(list);
    }
    
    ds_priority_destroy(list);
    return nearest;
    

    #2:
    Code:
    //instance_nearest_notme(x, y, obj) 
    var xx, yy, obj, nearest; xx = argument[0]; yy = argument[1];
    obj = argument[2];
    nearest = noone;
    dist = -1;
    for (ii=0; ii<instance_number(obj); ii+=1) {
          var o, d; 
          o = instance_find(obj, ii);
          d = point_distance(xx, yy, o.x, o.y);
          if (o != id) {
                   if (nearest == noone || d < dist) { nearest = o; dist = d; }
          }  
    }
    return nearest;
    
     
  4. MIchael PS

    MIchael PS Member

    Joined:
    Aug 12, 2017
    Posts:
    95
    Thank you I think it will help!!
     
  5. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    4,549
    I'm not a fan of the data structure churn in #1 (which is necessary in the general case but unnecessary for your minimum-only use case) or the instance_find() loop in #2. This is what I'd do:
    Code:
    ///instance_nearest_notme(x, y, obj)
    {
    var inst_nearest = noone,
        dist_nearest = undefined;
    with (argument2) {
      if (id != other.id) {
        var dist = distance_to_object(other);
        if (inst_nearest == noone || dist < dist_nearest) {
          inst_nearest = id;
          dist_nearest = dist;
        }
      }
    }
    return inst_nearest;
    }
    
    This is a direct adaptation of the not-me and lowest property value patterns from my with Block Recipe Cards article.
     
    Bentley, Pfap and VagrantWhaleGames like this.
  6. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,902
    Other than an aversion to having to choose some questionably arbitrary distance, why did you make your code be be concerned with if no instance was found yet? With short circuiting, the code will be super fast on the first instance, but from the second instance onward it will then have to check both expressions rather than just the distance-based expression. The distance expression is relevant for all instances checked, but the noone expression is only relevant for one instance only.
     
    Bentley likes this.
  7. BattleRifle BR55

    BattleRifle BR55 Member

    Joined:
    Jun 24, 2016
    Posts:
    971
    There's also a simple method by moving the calling instance:
    Code:
    /// instance_nearest_notme();
    
    x += 100000; var _ins = instance_nearest(x-100000,y,object_index); x -= 100000;
    
    if (_ins != id)
    return _ins;
    return noone;
     
    Bentley likes this.
  8. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    948
    You could just put after the check stage, if id != other.id
    Ah no, sorry that doesn't work with instance nearest

    I'd do it with "with", and manually measure the distance, and then add that if id != other.id check

    Or, check that the distance is not 0, cus itself will be 0 away from itself, obv,
    ah but that doesnt really work with that function,
    the instance_nearest function is really designed around different object types checking each other,
    I think if your gonna use this function, you need to make the calling instance a different object to the ones its checking for.. If you dont want that just do it manually with point_distance
     
    Last edited: Jul 17, 2018
  9. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    4,549
    That's because I have no information on the scale of distances in the original poster's project. I've seen once someone on the old GMC breaking the magic distance of 100000 on instance_nearest() with a huge room, and I stopped taking it for granted.

    Having said that, there are certain bounds that you can place on the starting value if certain conditions are known. For example, if everything will always be within room boundaries, point_distance(0, 0, room_width, room_height) is the theoretical max distance. If you want a slight margin outside room boundaries or just something computationally cheaper than the preceding, room_width+room_height would do as well.
     
    Joe Ellis likes this.
  10. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    948
    Thats kind of clever cus room_width+room_height is more than the distance from 0,0 to room_width, room_height, its a good rough and cheap approximation

    its something like 0.5656 for diagonal stuff
     
    Last edited: Jul 17, 2018
  11. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,902
    Well I'd default to $ffffffff or $ffffffffffffffff, but i guess someone could find a way to break even that.
     
  12. Bentley

    Bentley Member

    Joined:
    Jun 18, 2017
    Posts:
    800
    Thought I'd contribute. Wrote it fast so don't be too harsh.
    Code:
    var nearest_inst, nearest_dist, dist;
    
    nearest_inst = noone;
    nearest_dist = -1;
    
    with (object_index)
    {
        if (id != other.id)
        {
            dist = point_distance(x, y, other.x, other.y);
         
            // First instance in the with loop
            if (nearest_inst == noone)
            {
                nearest_inst = id;
                nearest_dist = dist;
            }
            else
            {
                if (dist < nearest_dist)
                {
                    nearest_inst = id;
                    nearest_dist = dist;
                }
            }
        }
    }
    
     
    Last edited: Jul 17, 2018

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice