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

GML NEED Collision help!

mrredleg0

Member
I have a problem. In my game you can fire bombs to blow up walls. Everything is working great except for the collisions. The bomb is colliding but its sticking through the walls. Here is a example. https://pasteboard.co/IAh9lV7.png
My code is simply this:

if (place_meeting(x,y,obj_solid))
{
vspeed = 0;
hspeed = 0;
}

I cant figure out whats wrong. Any help would be greatly appreciated!
 

TsukaYuriko

☄️
Forum Staff
Moderator
Depending on the speed of your bombs, they may be moving partially into the wall before stopping. Any speeds other than 1 will not be pixel-perfect. If you want the precision for such speeds, either implement custom movement that moves instances on a pixel-by-pixel basis and stops at collisions as you already implemented, or move bombs backwards step by step after stopping their movement until they are no longer colliding (and therefore not stuck in the wall anymore).
 

mrredleg0

Member
Depending on the speed of your bombs, they may be moving partially into the wall before stopping. Any speeds other than 1 will not be pixel-perfect. If you want the precision for such speeds, either implement custom movement that moves instances on a pixel-by-pixel basis and stops at collisions as you already implemented, or move bombs backwards step by step after stopping their movement until they are no longer colliding (and therefore not stuck in the wall anymore).
First of all, thanks for replying! Second of all, I get the theory of what your saying but I have no idea how to implement it.
 

TheouAegis

Member
Code:
if (place_meeting(x,y,obj_solid))
{
   while (place_meeting(x,y,obj_solid))
   {
      vspeed -= min(sign(vspeed),vspeed);
      hspeed -= min(sign(hspeed),hspeed);
   }
   vspeed = 0;
   hspeed = 0;
}
I think
 

Bentley

Member
Code:
if (place_meeting(x,y,obj_solid))
{
   while (place_meeting(x,y,obj_solid))
   {
      vspeed -= min(sign(vspeed),vspeed);
      hspeed -= min(sign(hspeed),hspeed);
   }
   vspeed = 0;
   hspeed = 0;
}
I think
Whaoh, kinda of cool. Is that for subpixel movement. For example: you're 0.2 pixels into a wall:
Code:
x -= min(0.2, 1);
is that what you were going for? Very cool. Never seen that.
 

Tony Brice

Member
place_meeting is used to check if you would be colliding with something at the coordinates you specify.

In your code you are checking the location where your object already is rather than the position it would be going to on the next frame.
So your solution would be to work out how many pixels in the current direction your object will move the next time it updates and check if a collision would occur at that spot. If it does then stop the movement at that point.
 

curato

Member
I would think you would check the place_meeting before you move then it would never be at a stuck location. Then if you want pixel perfect then you would check progressively smaller moves until one works then move there.

Edit: also if you are using hspeed and vspeed to move an object I would just set hspeed and vpeed to zero in the collision event and call it done. that place_meeting is more for manually moving objects
 
Last edited:

TheouAegis

Member
Whaoh, kinda of cool. Is that for subpixel movement. For example: you're 0.2 pixels into a wall:
Code:
x -= min(0.2, 1);
is that what you were going for? Very cool. Never seen that.
UPDATE: Don't use these codes, they still set speed to 0

You made me realize there was serious flaw with that code. lol. His code is post-collision, mine was mixing post- with pre-collision code. Woops. I was writing it with this in mind:

Code:
if (place_meeting(x+hspeed,y+vspeed,obj_solid))
{
   while (place_meeting(x+hspeed,y+vspeed,obj_solid))
   {
      var n = min(1,abs(vspeed);
      vspeed -= sign(vspeed) * n;
      n = min(1,abs(hspeed);
      hspeed -= sign(hspeed) * n;
   }
}
The original code would have been more like
Code:
if (place_meeting(x,y,obj_solid))
{
   while (place_meeting(x,y,obj_solid))
   {
     x -= sign(hspeed);
     y -= sign(vspeed);
  }
   vspeed = 0;
   hspeed = 0;
}
Not sure if the vspeed/hspeed=0 bit still needed to be in, but whatever. In this case, the fractional speeds shouldn't matter much. This code would need to be in the End Step event, otherwise there'd be a 1-step lag whereby the instance would clip the collision for a brief moment, long enough for most players to notice.
 
Last edited:
P

ParodyKnaveBob

Guest
Howdy, mrredleg0, and welcome to the GMC! $:^ J

Depending on how you've set things up, it's feasible you can skip all the manual pixel-by-pixel GML checking and instead use move_outside_*() or move_contact_*(), either as you already seem to with a Step Event, or moving things to a Collision Event. The manual is your friend. $:^ ]

I hope this helps,
 

mrredleg0

Member
It works! I never joined the GMC in till now because I didn't really think it would be useful. Boy you guys proved me wrong!
 

mrredleg0

Member
Maybe I spoke too soon about it working. It works a ton better but it is still clipping slightly and when it comes to a stop it jitters around a little bit.
 

TsukaYuriko

☄️
Forum Staff
Moderator
Make sure that no more movement occurs once the collision has taken place. Set all movement speed to 0 and make sure it stays there, or straight out disable the movement code from running at that point.

If you're still having issues, please post the code you're using as a lot of different suggestions have been made and we can't know what your current implementation looks like.
 

mrredleg0

Member
In the end step I put:
Code:
if (place_meeting(x,y,obj_solid))
{
   while (place_meeting(x,y,obj_solid))
   {
     x -= sign(hspeed);
     y -= sign(vspeed);
  }
   vspeed = 0;
   hspeed = 0;
}
Here is a picture. https://pasteboard.co/IAqKN4I.png
The edges of the bomb look rough because its jittering around.
 

TsukaYuriko

☄️
Forum Staff
Moderator
It shouldn't be. Solidity puts automatic collision checks and positioning adjustments in place that you can't override and which will, with almost absolute certainty, mess up any custom implementations of collisions.
 

mrredleg0

Member
Turned off solid. Still jittering.
This information might be helpful. The bomb is being launched out of a gun and is being assigned hspeed and vspeed values to give the effect of being thrown.
 
Last edited:

TheouAegis

Member
Edit: You're going to need to handle horizontal collisions and vertical collisions separately.I was trying to cut out that unnecessary step, but my code was still essentially setting "speed" (as a whole) to 0.

Code:
if place_meeting(x+hspeed,y,obj_solid) {
    var i = sign(hspeed);
    while !place_meeting(x+i,y,obj_solid)
        x += i;
    hspeed = 0;
}
if place_meeting(x,y+vspeed,obj_solid) {
    var i = sign(vspeed);
    while !place_meeting(x,y+i,obj_solid)
        y += i;
    vspeed = 0;
}
 
Last edited:

mrredleg0

Member
Edit: You're going to need to handle horizontal collisions and vertical collisions separately.I was trying to cut out that unnecessary step, but my code was still essentially setting "speed" (as a whole) to 0.

Code:
if place_meeting(x+hspeed,y,obj_solid) {
    var i = sign(hspeed);
    while !place_meeting(x+i,y,obj_solid)
        x += i;
    hspeed = 0;
}
if place_meeting(x,y+vspeed,obj_solid) {
    var i = sign(vspeed);
    while !place_meeting(x,y+i,obj_solid)
        y += i;
    vspeed = 0;
}
Thanks. I will try it out.
 

FrostyCat

Redemption Seeker
It's only frustrating because you've been given poor advice. The code from TheouAegis is misbehaving because it is mixing both custom movement and built-in movement, so it's moving twice and you're only controlling one of the two systems directly. You should completely remove hspeed and vspeed from your code, and substitute it with your own variables xspeed and yspeed.

Script: handle_movement
Code:
if place_meeting(x+xspeed,y,obj_solid) {
   var i = sign(xspeed);
   while !place_meeting(x+i,y,obj_solid)
       x += i;
   xspeed = 0;
}
if place_meeting(x,y+yspeed,obj_solid) {
   var i = sign(yspeed);
   while !place_meeting(x,y+i,obj_solid)
       y += i;
   yspeed = 0;
}
Create:
Code:
xspeed = 0;
yspeed = 0;
Step:
Code:
handle_movement();
From here on you will manipulate the speed using xspeed and yspeed exclusively. No more hspeed or vspeed.

The cardinal rules for custom pixel-precision movement:

Rule #1: If you decide to implement your own movement, there should NOT be a single hspeed or vspeed in your code (the built-in variables).
Rule #2: You should completely understand the pixel-precision movement algorithm before you use it.
Rule #3: Once you understand the pixel-precision movement algorithm, you should not type out the code again. Pack it into a script and take it with you, lest you make the same kind of typo TheouAegis did.
 

mrredleg0

Member
It's only frustrating because you've been given poor advice. The code from TheouAegis is misbehaving because it is mixing both custom movement and built-in movement, so it's moving twice and you're only controlling one of the two systems directly. You should completely remove hspeed and vspeed from your code, and substitute it with your own variables xspeed and yspeed.

Script: handle_movement
Code:
if place_meeting(x+xspeed,y,obj_solid) {
   var i = sign(xspeed);
   while !place_meeting(x+i,y,obj_solid)
       x += i;
   xspeed = 0;
}
if place_meeting(x,y+yspeed,obj_solid) {
   var i = sign(yspeed);
   while !place_meeting(x,y+i,obj_solid)
       y += i;
   yspeed = 0;
}
Create:
Code:
xspeed = 0;
yspeed = 0;
Step:
Code:
handle_movement();
From here on you will manipulate the speed using xspeed and yspeed exclusively. No more hspeed or vspeed.

The cardinal rules for custom pixel-precision movement:

Rule #1: If you decide to implement your own movement, there should NOT be a single hspeed or vspeed in your code (the built-in variables).
Rule #2: You should completely understand the pixel-precision movement algorithm before you use it.
Rule #3: Once you understand the pixel-precision movement algorithm, you should not type out the code again. Pack it into a script and take it with you, lest you make the same kind of typo TheouAegis did.
Thanks man!
 
Top