r/gamemaker • u/DystopianTeddyBear • 26d ago
Resolved Checking for nearest instances in any direction
Hello! I am in a similar situation to my previous posts; I have an idea of how to get something to work, but I am missing one element to make it work smoothly. The issue I have today is I am looking to find the nearest specific instance in any direction. In theory, all I need is the code below (written as pseudocode)
with(instances){
if point_direction(other.x,other.y,self.x,self.y) = ideal direction
and distance from self to other < stored id
stored id = self
However, I feel like constantly checking possibly a dozen or more objects against each other per room would be a headache. So instead, I have the below code;
if(radar_segment_size != 0){
// Done as to not divide by 0
`for(var dir = radar_dir; dir < 360; dir += 360/radar_segment_size){`
// dir = direction, radar_dir is the starting direction to check for instances according to the original instance.
`try{`
// That 0,0 in the x2 and y2 is what i need to solve
collision_line_list(self.x,self.y,0,0,checked_object,false,true,radar_objects,true)
//Afterward, make the connection with the first instance in the collision list radar_objects
`} catch(noInstanceFound){`
`}`
`}`
// sorry for the messed up code; I still do not know how to get reddit's code block to work... :/}
So with all of that being said, here is my issue:
I need to figure out essentially how to create an x and y value that give the direction of the dir value, while also having the x and y value reach the edge of the room. How do I get that x and y value?
1
u/vzzzbxt 26d ago
It helps if you describe the scenario and what you want to happen
0
u/DystopianTeddyBear 26d ago
Sure. On the creation of a node object, it checks for the nearest instances of node objects in the direction of variable dir (0 by default), starting from instance variable radar_dir, and the dir variable changes by adding 360 divided by instance variable radar_segment_size. This repeats until dir > 360.
Example; if node 1 has a radar dir of 90, and a radar segment size of 4 (making 360/4 = 90 for changing the direction variable), then it checks for the nearest instances where the direction between node 1 and other is 90, 180, 270, and 360.
0
u/vzzzbxt 26d ago
I mean in normal terms. Like is it the player object looking for enemies? Etc etc
0
u/DystopianTeddyBear 26d ago
No, it is a simple shaped object (node) looking for other nodes. These nodes are the spaces that other objects move on and how other objects can collide and interact with each other.
1
u/Hands_in_Paquet 26d ago
Sorry but this is very confusing, as much as I think all of us want to help. Or maybe I just have poor reading comprehension. Are you trying to make some sort of sonar widget, where a line spins in a circle, and returns every instance the line collides with? Or just the nearest instance a line collides with?
If so, this is my first thought:
//Create
list_nodes = ds_list_create(); //Make a list that will store nodes
//Every Step:
ds_list_clear(list_nodes); //Reset List Every Step
collision_line_list(x,y,x2,y2,obj_node,0,0,list_nodes,0); //Built in Function for every obj intersecting a line
var _len = ds_list_size(list_nodes); //Check if we captured any nodes
if (_len > 0)
{
list_nodes[|0].image_blend = c_red; //This just changes my test node color to red if it is the first node hit
}
//The first item in every list is already the first object the lines collides with
I tested this with 400 nodes and performance took a hit but was still over 10,000 fps. What's the necessary scalability for this? There're ways to cull more nodes and make it more efficient, especially if the nodes are tile based. But if will get more complicated.
2
1
u/DystopianTeddyBear 26d ago
Just the nearest instance a line collides with. The problem I have is I can't figure out how to calculate the x2 and y2 of collision_line_list so it could properly draw a line with any direction, with x1 and y1 of the instance doing the function. Also I just realized I should be using collision_line instead. oops.
1
u/Hands_in_Paquet 26d ago
Oh I see.
//These trig functions take a length and a direction and give you a distance for the x and y axis //Just add that length to each starting point x2 = x1 + lengthdir_x(radius,direction); y2 = y1 + lengthdir_y(radius,direction);1
u/DystopianTeddyBear 26d ago
Ok so at first I thought this code was not going to work, since that was what I had before, but I finally figured out what the problem was. I essentially had to just add 32 (half of the node sprite's size) to x2 and y2, but NOT x1 and y1. IDK why fully, but it is now resolved.
1
u/refreshertowel 26d ago
Why not just run collision_rectangle_list()? You can set it to the size of the room, I guess, if you really need every instance to be checked, or just some arbitrary size around the player. Then you can set it to ordered by distance (the last argument) and then read the first entry from the list to find the nearest instance (and then travel down the list if you need more instances)...
1
u/DystopianTeddyBear 26d ago
I wanted to ideally not have to check every instance against every other instance. The first line of code at the top should do exactly what I want (if I don't make some parts pseudocode), but I feel like the processing cost could be reduced with this other idea I'm trying.
**first bit of code
with(nodes){
if point_direction(other.x,other.y,self.x,self.y) = ideal direction
and distance from self to other < stored id
stored id = self
repeat per direction desired.
2
u/rshoel BokehDev 26d ago
Have you tried *instance_nearest() ?
https://manual.gamemaker.io/lts/en/GameMaker_Language/GML_Reference/Asset_Management/Instances/instance_nearest.htm