• 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!

[SOLVED]instance_nearest workaround

Mr Errorz

Member
so I've got these turret objs,
often times, more than one of them in a room.
I want to determine which one is nearest to the player obj,
but I don't want to calculate it in the player obj,
but rather in the turret obj itself.

so, say I have 4 instances of the same turret obj in a room,
how do I determine which one is nearest?
 

Jeremy

Member
First of all, why do you want to not do it inside the player object?
You could easily use the with statement inside the turret object, but I'm guessing you're not looking for this?
What are you trying to do?
- Jeremy
 
T

TimothyAllen

Guest
Well you could just simply do:
if (id == instance_nearest(player.x, player.y, object_index))
// do

But its not efficient. Its best to do this in some kind of controller object. If you do it in the turrent you are going to run this code N times where n is the number of turrets... and thats just redundant. So, i suggest having some sort of turret controller that will determine the nearest turret and then notify that turret to do what ever action you want.
 

Mr Errorz

Member
because I have approx 20 different kinds of turrets [shooting in different directions, different timing etc.],
and I want just the nearest one to the player [of every unique type] to play a shoot sound when shooting.
so, I want each turret type to determine which one is closest to the player.
 

Mr Errorz

Member
let me try and give a more of a visual example.

so, in this screen shot, there are 2 types of turrets [highlighted red or green],
all six of them are instances of the same object, differentiated by code given to then in the room editor, that "tells" them which type are they.
and what I want to get is the instance of each type that's nearest to the player.
so in this case, the nearest "red" type and the nearest "green" type.

refRef.png
 

Jeremy

Member
You could do this from the players object.

Player object Step:
Code:
var nearestTurret = instance_nearest(x,y,oTurret); //Grab the nearest turret
var red = -1; //Is the nearest turret red? 0 for NO, 1 for YES

with(nearestTurret){                 //With the nearest turret
     playSounds = true;              //Allow it to play sounds
     if(turretType=="Red"){          //Check for it's type
          red = 1;                   //Nearest turret is RED
     }else{
          red = 0;                   //Nearest turret is GREEN
     }
}

var n; //We'll use this variable to iterate

if(red==1){                          //Nearest turret was red, so look for green
     for (n = 2; nearestTurret.TurretType=="Red"; n += 1){ //iterates till it finds
          nearestTurret = instance_nth_nearest(x,y,obj,n); //nearest green turret
     }

}else{                               //Nearest turret was green, so look for red
     for (n = 2; nearestTurret.TurretType=="Green"; n+=1){ //iterates till it finds
          nearestTurret = instance_nth_nearest(x,y,obj,n); //nearest red turret
     }
}

with(nearestTurret){            //With the nearest second type of turret
     playSounds = true;         //Allow it to play sounds
}
This will set the variable 'playSounds' to true for the nearest 'red' and the nearest 'green' turret.
It utilizes the nifty instance_nth_nearest() script from gmlscripts.

It won't disable them once the player triggered them however!
You can put something like playSounds == false; in the begin Step of oTurret to remedy this.
- Jeremy

EDIT: I read over the fact that you have 20 different turrets,
instead of just the red and green one from the example...
You should be able to modify the code using switch statements to achieve this,
I think you get the idea now.
 
Last edited:

Mr Errorz

Member
You could do this from the players object.

Player object Step:
Code:
var nearestTurret = instance_nearest(x,y,oTurret); //Grab the nearest turret
var red = -1; //Is the nearest turret red? 0 for NO, 1 for YES

with(nearestTurret){                 //With the nearest turret
     playSounds = true;              //Allow it to play sounds
     if(turretType=="Red"){          //Check for it's type
          red = 1;                   //Nearest turret is RED
     }else{
          red = 0;                   //Nearest turret is GREEN
     }
}

var n; //We'll use this variable to iterate

if(red==1){                          //Nearest turret was red, so look for green
     for (n = 2; nearestTurret.TurretType=="Red"; n += 1){ //iterates till it finds
          nearestTurret = instance_nth_nearest(x,y,obj,n); //nearest green turret
     }

}else{                               //Nearest turret was green, so look for red
     for (n = 2; nearestTurret.TurretType=="Green"; n+=1){ //iterates till it finds
          nearestTurret = instance_nth_nearest(x,y,obj,n); //nearest red turret
     }
}

with(nearestTurret){            //With the nearest second type of turret
     playSounds = true;         //Allow it to play sounds
}
This will set the variable 'playSounds' to true for the nearest 'red' and the nearest 'green' turret.
It utilizes the nifty instance_nth_nearest() script from gmlscripts.

It won't disable them once the player triggered them however!
You can put something like playSounds == false; in the begin Step of oTurret to remedy this.
- Jeremy

EDIT: I read over the fact that you have 20 different turrets,
instead of just the red and green one from the example...
You should be able to modify the code using switch statements to achieve this,
I think you get the idea now.
Thanks!

I ended up using a controller for each type of turret to solve it in the end,
but I might switch to this solution.
 
The way I would handle this problem is roughly as follows:

1) Each turret type would have some sort of unique ID, for example sake, we'll say they have string ids. So "turret_red" and "turret_green". This would be assigned to the turrets at creation.

2) In the Begin Step Event, each turret will measure it's distance from the player and register it with a control object. The control object would then check a data structure for that turret type (for this example, a ds map), which holds the current closest distance as well as the instance id of the current "winner". If the newly registered instance is closer, the data is replaced for that turret type.

3) By the time the normal Step Event rolls around, the data structure in the control object will be populated with the closest instance of each type. The turrets can the request if it is the closest one and react from there.

4) On the End Step Event, the control object clears the data structure, then everything starts over again next frame.

Using this method, you only need one control object for all types. It's a tad complicated, but also a fairly clean method, in my opinion anyway.
 

Mr Errorz

Member
The way I would handle this problem is roughly as follows:

1) Each turret type would have some sort of unique ID, for example sake, we'll say they have string ids. So "turret_red" and "turret_green". This would be assigned to the turrets at creation.

2) In the Begin Step Event, each turret will measure it's distance from the player and register it with a control object. The control object would then check a data structure for that turret type (for this example, a ds map), which holds the current closest distance as well as the instance id of the current "winner". If the newly registered instance is closer, the data is replaced for that turret type.

3) By the time the normal Step Event rolls around, the data structure in the control object will be populated with the closest instance of each type. The turrets can the request if it is the closest one and react from there.

4) On the End Step Event, the control object clears the data structure, then everything starts over again next frame.

Using this method, you only need one control object for all types. It's a tad complicated, but also a fairly clean method, in my opinion anyway.
sounds like a good way of handling that,
might try it out.
Thanks.
 
Top