• 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 Difficulties determining the nearest instance in 3D space

P

Prometheus1998_

Guest
I'm trying to create a script that returns the nearest instance in 3-dimensional space, by looping through all active instances of the object, evaluating the distance using the built-in function "point_distance_3d", sorting the ds_grid containing the data so that the smallest distance value is in the [0,1] position, and returning the id saved in the [0,0] position.

Code:
///instance_nearest_3d(x,y,z,obj)
object = argument3;
arg_x = argument0;
arg_y = argument1;
arg_z = argument2;

var instances = ds_grid_create(instance_number( object ),1);

for(var i = 0; i < instance_number( object ); i += 1) {
    var inst = instance_find( object , i);
    var dist = point_distance_3d(inst.x,inst.y,inst.z, arg_x , arg_y , arg_z )
   
    ds_grid_add(instances,0,i,inst.id);
    ds_grid_add(instances,1,i,dist);
}

ds_grid_sort(instances,1,true);

var val = ds_grid_get(instances,0,0);

ds_grid_destroy(instances);

return val;

For ease of testing, I've been using a flat plane, assuming all objects are on the same z-level (z = 0).

The grid I have been using to test has nine objects, arranged like so:

| a b c |
| d e f |
| g h i |

The object running the test starts in the "e" position, but indicates the closest object it tests for is in the "i" position. In addition, despite running in the "Step" event, it only calculates the nearest object once. It behaves exactly the same if I change the "ascending" parameter for ds_grid_sort from true to false.

Replacing the script in the spoiler tags above with the built-in function "instance_nearest" functions exactly the way it should, so I'm reasonably confident the problem is in the ds_grid, either saving the data or sorting it. Given the way it (doesn't) change behavior when switching how it sorts the information in the grid, I'm pretty sure I messed up the sorting. I just can't figure out how, and would appreciate any help that can be provided.
 

Simon Gust

Member
May I ask what the ds grid exactly reads?

Where are the origins placed on these instaces?
Are your arg_x, arg_y, arg_z exactly the x, y and z of the searching instance?
 

TheSnidr

Heavy metal viking dentist
GMC Elder
If you only need the single nearest instance, it's easier to use "with" and store the nearest instance in a variable:
Code:
var dist = 99999;
var nearest = - 1;
with object
{
    var d = point_distance_3d(stuff);
    if (d < dist)
    {
        dist = d;
        nearest = id;
     }
}
return nearest;
 
P

Prometheus1998_

Guest
May I ask what the ds grid exactly reads?

Where are the origins placed on these instaces?
Are your arg_x, arg_y, arg_z exactly the x, y and z of the searching instance?
By origins, do you mean the exact x and y value of the object that the sprite is drawn from?
They are procedurally placed, centered on the player object.

The ds_grid's 0 column contains the "id" variable of each object, the 1 column contains the calculated distance.

Arg_x, arg_y, and arg_z are the exact coordinates that the script calculates the distance to. It can be the coordinates of the calling function, or it can be some other coordinate entirely.

If you only need the single nearest instance, it's easier to use "with" and store the nearest instance in a variable:
Code:
var dist = 99999;
var nearest = - 1;
with object
{
    var d = point_distance_3d(stuff);
    if (d < dist)
    {
        dist = d;
        nearest = id;
     }
}
return nearest;
Let me know if I understand the concept behind this correctly, please:
First, the code initializes the "dist" variable to an arbitrarily large number that's unlikely to ever come up as a legitimate distance value, and sets the "nearest" variable to -1, which will never be a real id. From there, it executes code in all other instances (looping through by instance number?), calculating the distance between the two points in 3d space. If this distance is shorter than the existing value in the "dist" variable, it sets the "dist" variable to this new value, sets "nearest" to that instance's id, and continues on. The first instance that the code operates through should always overwrite the "dist" and "nearest" variables.
At the end of the "with" construction, the closest instance's id should be stored in the nearest variable. If the "nearest" variable is still -1, there are no valid active instances to be found.
 
Top