GMS 2 Create a object away from others

Discussion in 'Programming' started by Roalinn, Feb 10, 2019.

  1. Roalinn

    Roalinn Member

    Joined:
    Jul 13, 2017
    Posts:
    35
    I want to create a object on random position then create other but minimum distance between first and second is 64 pixel. then create other object .minimum distance between first and third, second and third is 64 pixel.
    how i check a distance between object and all objects.
     

    Attached Files:

  2. Captain_ArrowWound

    Captain_ArrowWound Member

    Joined:
    Jan 19, 2019
    Posts:
    29
    A way to this would be to make to objects. Maybe something like object circle spawner none and object circle spawner there, just names. Place both of them into your world. Object circle spawner none would check if there are no circles placed down, if there are none then it would randomly spawn a circle. Your next object, object circle spawner there would check if any circles are placed down. If there are circles placed down it will spawn a circle at least 64 pixels away from any other circles.
     
  3. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    4,028
    If they are all the same object type or share the same parent, combine instance_nearest() with point_distance().
    Code:
    var xx, yy, inst_nearest;
    do {
      xx = irandom(room_width);
      yy = irandom(room_height);
      inst_nearest = instance_nearest(xx, yy, object);
    } until (inst_nearest == noone || point_distance(xx, yy, inst_nearest.x, inst_nearest.y) >= 64)
    instance_create_layer(xx, yy, layer, object);
    
     
    Bentley and SnotWaffle Studios like this.
  4. TheSly

    TheSly Member

    Joined:
    Jan 16, 2017
    Posts:
    852
    This will work, even though it's kind of brute force.
    Code:
    var xx, yy, num, attempts = 0, list = ds_list_create();
    var accuracy = 10000;    //how many iterations, to ensure coverage
    var dis = 64;            //gap between objects
    var obj = o_object;      //object to create
    
    xx = random(room_width);
    yy = random(room_height);
    var inst = instance_create_depth(xx, yy, depth, obj);
    
    do {
        with(inst) {
            //check for a collision within a circular distance
            num = collision_circle_list(x, y, dis, obj, false, true, list, false);
    
            if num > 0 {
                //collision found, so try another location
                x = random(room_width);
                y = random(room_height);
                attempts++;
            } else {
                //no collision, create another and reset count
                var inst = instance_create_depth(x, y, depth, obj);
                attempts = 0;
            }
        }
    } until attempts > accuracy;
    
    //destroy last one, as it didn't find a spot
    instance_destroy(inst);
    ds_list_destroy(list);
    
     
    Last edited: Feb 11, 2019
    Bentley likes this.
  5. NightFrost

    NightFrost Member

    Joined:
    Jun 24, 2016
    Posts:
    1,757
    If you want to get technical, google about poisson-disc sampling. You can see a graphical representation how it works over here.
     
    Bentley, Bayesian and TheSly like this.
  6. Bayesian

    Bayesian Member

    Joined:
    Sep 13, 2016
    Posts:
    402
    This is really fun to watch
     
  7. TheSly

    TheSly Member

    Joined:
    Jan 16, 2017
    Posts:
    852
    That poisson-disc sampling(pds) is really interesting, and was something I was toying with when writing my first solution, although I didn't know the name of it, I had thought of the concept. So going back and reworking it more like pds, this method is more efficient then what I posted above. It creates an object, and then checks the min distance in a circle all around it, creating objects where it can, then removes itself from further checks. This is repeated a few times, depending on room size until no more spots are available. I also tried doing it with ds_queues, so we don't loop through excluded objects, but in the end, using with() was more efficient according to time checks.

    Code:
    var xx, yy, dis, num, list = ds_list_create(), iterations, obj = o_object, inst, start;
    dis = 64;            //gap between objects
    xx = room_width/2;
    yy = room_height/2;
    inst = instance_create_depth(xx, yy, depth, obj);
    inst.include = true;
    iterations = ceil((sqrt(sqr(room_width/2) + sqr(room_height/2)))/dis)*2;
    repeat(iterations) {
        with(obj) {
            if include {
                start = random(360);
                for (var i = 0; i < 360; i+=3) {
                    xx = x + lengthdir_x(dis, start + i);
                    yy = y + lengthdir_y(dis, start + i);
    
                    //check for a collision within a circular distance
                    num = collision_circle_list(xx, yy, dis, obj, false, true, list, false);
                    if num == 0 and xx > 0 and xx < room_width and yy > 0 and yy < room_height {
                        //no collision, create another
                        inst = instance_create_depth(xx, yy, depth, obj);
                        inst.include = true;
                    }
                }
                include = false;        //remove this object from further checks    
            }
        }
    }
    ds_list_destroy(list);
    
     
    Last edited: Feb 12, 2019

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice