1. Hey! Guest! The 36th GMC Jam will take place between February 27th, 12:00 UTC - March 2nd, 12:00 UTC. Why not join in! Click here to find out more!
    Dismiss Notice
  2. NOTICE: We will be applying a Xenforo update on Tuesday 25th of February. This means that from approximately 10:00 to 14:00 BST the forums will be offline (or possibly longer). Sorry for the inconvenience! Official Announcement here.

Line connected dots

Discussion in 'Programming' started by 66Gramms, Nov 7, 2017.

  1. 66Gramms

    66Gramms Member

    Joined:
    Feb 2, 2017
    Posts:
    23
    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
     
  2. obscene

    obscene Member

    Joined:
    Jun 21, 2016
    Posts:
    2,512
    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.
     
  3. NightFrost

    NightFrost Member

    Joined:
    Jun 24, 2016
    Posts:
    2,102
    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.
     
    66Gramms likes this.
  4. 66Gramms

    66Gramms Member

    Joined:
    Feb 2, 2017
    Posts:
    23
    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.
     
  5. NightFrost

    NightFrost Member

    Joined:
    Jun 24, 2016
    Posts:
    2,102
    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.
     
  6. obscene

    obscene Member

    Joined:
    Jun 21, 2016
    Posts:
    2,512
    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.
     

Share This Page