GameMaker How does everyone make bullet collisions?

N

nuro0o

Guest
Hi!

Recently I tried creating a space game but noticed most of my bullets are passing through certain areas of the collision mask.
I was wondering how does everyone make these collisions? Is there a better way to do it than using the GMS collision?

Could it be that my resolution is the problem? 1920x1080*

I'm fairly new and this is something I have been stuck on for awhile.
 
Sometimes I just use a mask that overlaps the transparent areas of the object's sprite or the hit box. Precise collisions or small hit boxes can make things weird.
 
If you're bullet is moving fast, it's entirely possible that it will move over any given collision mask in a single step.

Let's use an example: The bullet is at an x position of 100, moving to the right. There's a wall that is 10 pixels thick at an x position of 140 (both the bullet and the wall are at the same y coordinate). The bullet is moving at 30 pixels a frame. In the next frame, the bullet moves 30 pixels to the right and is at an x position of 130. It performs a collision check, the wall is not there (the wall is at x position 140, remember). The next frame, the bullet moves 30 pixels and is at an x position of 160. The wall is at x=140 with a width of 10, so it stretches between 140 and 150 x. The bullet has performed a collision check at 130 and 160 x, so clearly it's not going to register a collision with the wall...The question is how do we get it to actually understand that it has skipped the wall? The usual answer is to check all the points between where the bullet is and where it's going to be in the next frame using a loop:
Code:
var next_x = round(x+xspd); // Find where the bullet will be in the next frame
var current_x = round(x); // And where it currently is
while (current_x-next_x != 0) { // Loop until there is no gap remaining between current_x and next_x
   if (position_meeting(current_x,y,obj_wall)) { // Check to see if there is a wall object at the current_x and y coordinates
      break; // If there is, break out of the loop
   }
   current_x += sign(xspd); // If there is no collision, increment current_x by either 1 or -1 depending on whether xspd is positive or negative
}
x = current_x; // Once the loop has finished, set x to the current_x variable, which will either set it at to the side of obj_wall if there is a collision or wherever the bullet should be if there is no collision
Of course, there's a million little variations on the above that you could do. There's also other methods, for instance, using collision_line instead of manually calling a loop yourself, but this is the general gist: Instead of just moving at a certain speed and checking where that speed would put you each frame, check each position along the path you are going to take and adjust what happens based on those collision checks.
 
N

nuro0o

Guest
If you're bullet is moving fast, it's entirely possible that it will move over any given collision mask in a single step.

Let's use an example: The bullet is at an x position of 100, moving to the right. There's a wall that is 10 pixels thick at an x position of 140 (both the bullet and the wall are at the same y coordinate). The bullet is moving at 30 pixels a frame. In the next frame, the bullet moves 30 pixels to the right and is at an x position of 130. It performs a collision check, the wall is not there (the wall is at x position 140, remember). The next frame, the bullet moves 30 pixels and is at an x position of 160. The wall is at x=140 with a width of 10, so it stretches between 140 and 150 x. The bullet has performed a collision check at 130 and 160 x, so clearly it's not going to register a collision with the wall...The question is how do we get it to actually understand that it has skipped the wall? The usual answer is to check all the points between where the bullet is and where it's going to be in the next frame using a loop:
Code:
var next_x = round(x+xspd); // Find where the bullet will be in the next frame
var current_x = round(x); // And where it currently is
while (current_x-next_x != 0) { // Loop until there is no gap remaining between current_x and next_x
   if (position_meeting(current_x,y,obj_wall)) { // Check to see if there is a wall object at the current_x and y coordinates
      break; // If there is, break out of the loop
   }
   current_x += sign(xspd); // If there is no collision, increment current_x by either 1 or -1 depending on whether xspd is positive or negative
}
x = current_x; // Once the loop has finished, set x to the current_x variable, which will either set it at to the side of obj_wall if there is a collision or wherever the bullet should be if there is no collision
Of course, there's a million little variations on the above that you could do. There's also other methods, for instance, using collision_line instead of manually calling a loop yourself, but this is the general gist: Instead of just moving at a certain speed and checking where that speed would put you each frame, check each position along the path you are going to take and adjust what happens based on those collision checks.
Thank you very much!
 
R

Ratsha

Guest
Alternatively, if you want to go a more advanced route, you can the hitscan method I explain here:
It really depends on the type of game you want to develop.
 
N

nuro0o

Guest
Alternatively, if you want to go a more advanced route, you can the hitscan method I explain here:
It really depends on the type of game you want to develop.
Thanks this is really helpfull also i'm making a rogue like space game. Everything is going well except the collision or hitscan in that matter. Thanks alot!
 
N

nuro0o

Guest
This is super embarrassing, but I noticed the collisions were actually working. But the objects had the wrong mask for some reason (Not same as sprite). But I learned alot from the videos.

I thank everyone for their input! Thank you!
 

vdweller

Member
If you want the precise spot the bullet collides with something that stops it, and in order to reduce iterations across a large distance you can also employ the shish-kebab trick:

Jump ahead 16 times
If collision, jump back 8 times (half of the previous)
If not collision, jump ahead 4 times
If collision, jump back 2 times
etc etc

You can do this in a loop and it can work with collision_line. It can be a bit tricky, I'm posting this more for the future visitor to consider rather than a direct suggestion.
 
Top