GameMaker Asteroids in my space shooter are sticking together.

IceTray

Member
I have been following a youtube tutorial called "My First Game" to make a space shooter in drag and drop. I decided it would be cool to have the asteroids bounce off each other when they come in contact so I made a collision event on the obj_asteroid with a set direction variable that changes the direction to 180 degrees with relative checked. They bounce off of each other fine but since they are spawned randomly sometimes the asteroids get stuck inside each other and aren't able to move. Not sure how I would go about fixing this.

The issue:

Asteroid collision:

Asteroid spawning:
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
This happens because the collision event is constantly triggering as every game step the asteroids are in collision. You can avoid this issue completely by making sure that the asteroids don't spawn inside each other, which would require a fairly important re-write of the spawning code, since you'd need to use a "while" action to evaluate if there is a collision at point xx/yy. NOTE! This will require you to set the MASK INDEX of the controller to a sprite so that the collisions can be correctly detected!!! Basically, you do this:


set instance variable "mask" to "spr_Asteroid_Large" (or whatever the largest asteroid sprite is called)
//This next DnD is inside the Repeat loop
create temp variable "_check" and make it "false"
while "_check" is equal to "false"
----generate xx position (as you have it now)
----generate yy position
----if any object is NOT at place xx/yy
--------assign variable "_check" to "true"
create instance at xx/yy
//This goes at the end AFTER everything else
set instance variable "mask" to "-1" (removes the mask sprite again)


Alternatively, you can also use a "while" loop in the collision event to move any instances out of collision (which is simpler!), like this:


// IN THE obj_asteroid COLLISION EVENT
create temp variable "_check" and make it "false"
while "_check" is equal to "false"
----if object "obj_asteroid" is at place "x"/"y" (store the ID of any instance in the temp target variable "_inst")
--------if instance exists "_inst"
------------function call "point_direction", arg0: "other.x", arg1:"other.y", arg2:"x", arg3:"y" - target temp "_dir" (This gets the direction between the x and y positions of the object and the object it is colliding with
------------function call "lengthdir_x", arg0:"1", arg1:"_dir" - target temp "_x"
------------function call "lengthdir_y", arg0:"1", arg1:"_dir" - target temp "_y"
------------set instance variable "x-coordinate" to "x + _x"
------------set instance variable "x-coordinate" to "y + _y"
--------else
------------assign variable "_check" to "true"
// You can then add some extra DnD here to "bounce"


All the code above is doing is moving the instance along the direction between it and the colliding instance until the two are no longer in collision.

Hope that helps!
 

IceTray

Member
This happens because the collision event is constantly triggering as every game step the asteroids are in collision. You can avoid this issue completely by making sure that the asteroids don't spawn inside each other, which would require a fairly important re-write of the spawning code, since you'd need to use a "while" action to evaluate if there is a collision at point xx/yy. NOTE! This will require you to set the MASK INDEX of the controller to a sprite so that the collisions can be correctly detected!!! Basically, you do this:


set instance variable "mask" to "spr_Asteroid_Large" (or whatever the largest asteroid sprite is called)
//This next DnD is inside the Repeat loop
create temp variable "_check" and make it "false"
while "_check" is equal to "false"
----generate xx position (as you have it now)
----generate yy position
----if any object is NOT at place xx/yy
--------assign variable "_check" to "true"
create instance at xx/yy
//This goes at the end AFTER everything else
set instance variable "mask" to "-1" (removes the mask sprite again)


Alternatively, you can also use a "while" loop in the collision event to move any instances out of collision (which is simpler!), like this:


// IN THE obj_asteroid COLLISION EVENT
create temp variable "_check" and make it "false"
while "_check" is equal to "false"
----if object "obj_asteroid" is at place "x"/"y" (store the ID of any instance in the temp target variable "_inst")
--------if instance exists "_inst"
------------function call "point_direction", arg0: "other.x", arg1:"other.y", arg2:"x", arg3:"y" - target temp "_dir" (This gets the direction between the x and y positions of the object and the object it is colliding with
------------function call "lengthdir_x", arg0:"1", arg1:"_dir" - target temp "_x"
------------function call "lengthdir_y", arg0:"1", arg1:"_dir" - target temp "_y"
------------set instance variable "x-coordinate" to "x + _x"
------------set instance variable "x-coordinate" to "y + _y"
--------else
------------assign variable "_check" to "true"
// You can then add some extra DnD here to "bounce"


All the code above is doing is moving the instance along the direction between it and the colliding instance until the two are no longer in collision.

Hope that helps!
I really appreciate the help it's very useful. I am very new to game maker though and I'm not sure I completely understand. Would it be possible for you to create this code in GameMaker and screenshot it? If not that's fine. I'm just not sure how to do your second part that moves the asteroids out of the way. I attempted the first part that changes their spawning but it didn't seem to work. Most likely I did it wrong. Here's what I got.

 
Top