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

Line connected dots

6

66Gramms

Guest
Hello!
I'm trying to reproduce something i saw on a cool website (check it out anotalk.hu to understand(it's the background)) So I made a few dots (like 200) and gave them random direction and speed. Now to connect them i used a collision circle but collision circle is dumb and picks 1 instance in the circle and then keep checking only that. To fix that I made a ds list then I add an instance to the list, deactivate it (so it won't be checked again) and keep doing it until collision circle returns noone. If this happens I activate all the instances again from the list, it looks like this:
Code:
draw_circle(x, y, 3, false);    //I don't use a sprite just draw a "dot" like this

var dots = collision_circle(x, y, length, obj_dots, false, true); //Checking for the instance in the radious

if (dots != noone)
{
    ds_list_add(list, dots);    //Save it for later in a ds list

    if (distance_to_point(mouse_x, mouse_y) <= distance)    //Check if mouse is close to the dots
    {
        draw_line(x, y, dots.x, dots.y);                    //If it is then the dot draw a line to the closer dots
    }
    instance_deactivate_object(dots);                       //Then deactivate it
} else {                                                    //if dots returns noone
    for (var i = 0; i < ds_list_size(list); i++)            //Add them back
    {
        instance_activate_object(ds_list_find_value(list, i));  //By reactivating them
        ds_list_delete(list, i);                                //And deleting them from the list
    }
}
Now this works pretty cool expect for the dots flashing up and diasapiring. I think it happens because as they are doing the code above, they deactivate each other. Also I want them to bounce back when they leave the room, what is the best way to do that? I think using GM-s built in bounce stuff is not a good idea with 200+ instances. Also I leave a dropbox link to the project so you can see it on the work. Thanks for any help in advance! https://www.dropbox.com/s/edy3r6l6hmnaz46/dots.gmz?dl=0
 

obscene

Member
First, collision_circle is overkill for this. It's used to check for sprite collisions and is slow. Since you're checking in a circular area for a point, it's the same as using point_distance < some_value.

Second, I don't think instances are activated/deactivated in-line, but instead that is applied at the end of the step. I could be wrong, however it's irrelevant because you could do this easier...

Code:
if (point_distance(x,y,mouse_x, mouse_y) < distance)
 {
 var xx=x;
 var yy=y;
 with (obj_dots)
   {
   if (point_distance(x,y,xx,yy) < length)
    {
    draw_line(x,y,xx,yy);
    }
   }
 }
That should do the whole thing right there!

Now that will be a LOT of point_distance calls so personally I think I'd attempt to do this in an alarm (Staggered so only a few points are doing the check any given step) and store the IDs of connected points in an array.
 

NightFrost

Member
As how to stagger the checks, throw all the IDs into a ds queue and handle maybe a tenth of its (original) length per step. Only when the queue is empty, repopulate it with the IDs. All the potential connections would then be checked in ten steps or a sixth of a second, meaning you don't even notice. Staggering creates a problem though since the code draws the line only after a distance check. The points needs to remember, in an array or something, which IDs it is connecting to while queue is handled and draw them separately, and forget the connections when the queue is repopulated for a new pass.

You could also check if the target point already connects to the source point so you can skip the point distance check. However if there's a large amount of points and relatively few of them actually connect, checking for existing connections may waste more time than skipping a few point distance calls saves. Sometimes, pointlessly running an operation a few times is faster than constantly checking if running it actually is necessary.
 
6

66Gramms

Guest
First, collision_circle is overkill for this. It's used to check for sprite collisions and is slow. Since you're checking in a circular area for a point, it's the same as using point_distance < some_value.

Second, I don't think instances are activated/deactivated in-line, but instead that is applied at the end of the step. I could be wrong, however it's irrelevant because you could do this easier...

Code:
if (point_distance(x,y,mouse_x, mouse_y) < distance)
 {
 var xx=x;
 var yy=y;
 with (obj_dots)
   {
   if (point_distance(x,y,xx,yy) < length)
    {
    draw_line(x,y,xx,yy);
    }
   }
 }
That should do the whole thing right there!

Now that will be a LOT of point_distance calls so personally I think I'd attempt to do this in an alarm (Staggered so only a few points are doing the check any given step) and store the IDs of connected points in an array.
The only problem with that is point_distance returns the length of the line not any instance ID-s :) Also ds list is an array.
 

NightFrost

Member
I just realized the solution I proposed to fix flashing lines couldn't work. The lines are lost when the list of connections is wiped, and then need to wait until a new point distance check re-establishes the connection. You actually need two lists: one that contains the final results of previous pass through all point distance checks and is used to draw the lines; and a second list that is under construction by the current pass. Although, the whole staggering process is only necessary if your unstaggered code is eating significant amounts of CPU you'd rather use on something else.
 

obscene

Member
The only problem with that is point_distance returns the length of the line not any instance ID-s :) Also ds list is an array.
You don't need a function to return the ID. You are using "with." The ID is the ID ;)

other.id_array[0]=id;

Arrays are MUCH MUCH faster than a ds_list.
 
Top