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

GameMaker random spawning without overlap

zim32

Member
I am having trouble keeping my randomly spawned objects from overlapping I tried to have it check for collison with other instances using if object at and having it change x coordinate until it gets one that won't collide but i doesn't seem to work nothing spawns anymore my noob attempt looks like this
num_objects = 8

repeat ( num_objects){

var _x = irandom(room_width)
var _y = 700
var l3654631B_0 = instance_place(obj_spikes.x, obj_spikes.y, obj_spikes);
if ((l3654631B_0 > 0))
{
while ((l3654631B_0 > 0)) {
var _x = irandom(room_width)
var _y = 700 // code here
}

instance_create_layer(_x, _y, "Instances",obj_spikes) // replace "my_object_here" with the real name of your object.
}
}
 

2Dcube

Member
This while loop:
Code:
while ((l3654631B_0 > 0)) {
var _x = irandom(room_width)
var _y = 700 // code here
}
will loop forever once it starts, because l3654631B_0 is never changed. So if it is bigger than 0, it never becomes 0 or less, and the loop continues....forever....and ever...

While loop pseudo code:
Code:
while (this expression is true)
{
   keep_doing_this_code()
}
Also why do you name a variable l3654631B_0 ? Seems difficult to type...
 

zim32

Member
This while loop:
Code:
while ((l3654631B_0 > 0)) {
var _x = irandom(room_width)
var _y = 700 // code here
}
will loop forever once it starts, because l3654631B_0 is never changed. So if it is bigger than 0, it never becomes 0 or less, and the loop continues....forever....and ever...

While loop pseudo code:
Code:
while (this expression is true)
{
   keep_doing_this_code()
}
Also why do you name a variable l3654631B_0 ? Seems difficult to type...
i just dragged and dropped the if object at then converted to gml and cut and pasted since the if ((l3654631B_0 > 0)) came from that i thought that meant since it was supposed to be checking if the instances were colliding with each other that
]while ((l3654631B_0 > 0)) {
var _x = irandom(room_width)
var _y = 700 // code here
}[/code]
would change the x variable until it didn't collide with the other instances
 
Well you want to basically just check to ensure that you are not overlapping another object of whatever type you don't want to overlap (you could check for free space as well)... anyway I would suggest based on the previous messages it is something like

Code:
// create event
randomize();

var object_count = 10;
var yy = 700; // this is here because we won't change it

repeat(object_count) {
  var xx = random(room_width); // between 0 - room_width
  var times = 3;

  while(place_meeting(xx, yy, obj_obj_spikes) {
    // while there are spikes at our current location, try again
    xx = random(room_width);
    times -= 1; // ensure there is a way out of the loop

    if(times <= 0) {
      break; // we couldn't find an opening, so break out of while loop keeping the xx position
    }
  }

  instance_create_layer(xx, yy, "Instances", obj_spikes);

}
Please note I didn't try this out, just what comes to my mind and there could probably be some syntax errors.
 

zim32

Member
Well you want to basically just check to ensure that you are not overlapping another object of whatever type you don't want to overlap (you could check for free space as well)... anyway I would suggest based on the previous messages it is something like

Code:
// create event
randomize();

var object_count = 10;
var yy = 700; // this is here because we won't change it

repeat(object_count) {
  var xx = random(room_width); // between 0 - room_width
  var times = 3;

  while(place_meeting(xx, yy, obj_obj_spikes) {
    // while there are spikes at our current location, try again
    xx = random(room_width);
    times -= 1; // ensure there is a way out of the loop

    if(times <= 0) {
      break; // we couldn't find an opening, so break out of while loop keeping the xx position
    }
  }

  instance_create_layer(xx, yy, "Instances", obj_spikes);

}
Please note I didn't try this out, just what comes to my mind and there could probably be some syntax errors.
yeah there was a syntax error forgot a ) but fixing the syntax error didn't get it work for me also why is is it obj_obj
 

zim32

Member
okay i seem to have sort of got it working there's still overlap but never as much as before
i did this
randomize()

var object_count = 6
var yy = 700

repeat(object_count) {
var xx = random(room_width);
while (position_meeting(xx, yy, obj_spikes)) {
xx = random(room_width)
}
instance_create_layer(xx, yy, "Instances", obj_spikes)
}
anyone know how to improve it
 
J

Jdown79

Guest
could you not patch this by just running a check for collision after spawn?

obj_spikes
step
if place_meeting(with obj_spikes) instance_destroy()
This would remove both, but if your spawn loop works properly and quickly you'd never know

IDK I'm a novice as well haha.
 

zim32

Member
well position_meeting works based on the collision mask, so if your mask isn't going all the way, that could explain why you have overlap still. So you can either use that, or expand it into something with point_in_rectangle
okay making the collsion mask bigger does seem to help but i am having to make the mask way to big for the results i am getting it doesn't make sense it seems to be allowing a certain amount of overlap between collison mask
 

zim32

Member
Alright my last attempt :p

So basically I created a spike, and a generator. Then in the generator I am using collision_rectangle to see if there are any obj_Spike's within the given rectangle. If there is, then it tries again, for a maximum of 10 tries. Finally in the end, if it was indeed an empty space, then it will place a spike at that location, if it does not, then it skips it (failed 10 times).

Code:
// create event of generator

randomize();

var sprite_padding = 10; // two pixels left and right
var spr_width = 32 + sprite_padding; // numbers came from sprite itself
var spr_height = 16;
var yy = 448;

var number_of_spikes = 20;

var tries = 5;
var instance = noone;
var xx = 0;

repeat(number_of_spikes) {
    xx = random(room_width);
    instance = collision_rectangle(xx - spr_width, yy - spr_height, xx + spr_height, yy + spr_width, obj_Spike, false, true)
    tries = 10;
 
    while(instance != noone) {
        show_debug_message("Found spike inside box, trying again: " + string(tries));
     
        // try again
        xx = random(room_width);
     
        // update collision
        instance = collision_rectangle(xx - spr_width, yy - spr_height, xx + spr_height, yy + spr_width, obj_Spike, false, true)
     
        // remove a try
        tries -= 1;
     
        if(tries < 0) {
            // we tried a lot, but break out
            break;
        }
    }
 
    // did we find an empty space?
    if(instance == noone) {
        instance_create_layer(xx, yy, "Instances", obj_Spike);
    }
}
Image Preview
 

zim32

Member
Alright my last attempt :p

So basically I created a spike, and a generator. Then in the generator I am using collision_rectangle to see if there are any obj_Spike's within the given rectangle. If there is, then it tries again, for a maximum of 10 tries. Finally in the end, if it was indeed an empty space, then it will place a spike at that location, if it does not, then it skips it (failed 10 times).

Code:
// create event of generator

randomize();

var sprite_padding = 10; // two pixels left and right
var spr_width = 32 + sprite_padding; // numbers came from sprite itself
var spr_height = 16;
var yy = 448;

var number_of_spikes = 20;

var tries = 5;
var instance = noone;
var xx = 0;

repeat(number_of_spikes) {
    xx = random(room_width);
    instance = collision_rectangle(xx - spr_width, yy - spr_height, xx + spr_height, yy + spr_width, obj_Spike, false, true)
    tries = 10;
 
    while(instance != noone) {
        show_debug_message("Found spike inside box, trying again: " + string(tries));
    
        // try again
        xx = random(room_width);
    
        // update collision
        instance = collision_rectangle(xx - spr_width, yy - spr_height, xx + spr_height, yy + spr_width, obj_Spike, false, true)
    
        // remove a try
        tries -= 1;
    
        if(tries < 0) {
            // we tried a lot, but break out
            break;
        }
    }
 
    // did we find an empty space?
    if(instance == noone) {
        instance_create_layer(xx, yy, "Instances", obj_Spike);
    }
}
Image Preview
thanks so much it seems to work but i had to shrink my sprite to get it to no overlap which i was going to do eventually anway but i wonder if that's all i had needed to do for a while now
 
Top