Legacy GM [SOLVED]Strange bug in simple collision system

C

Conlee

Guest
I have been using an extremely simple collision/control system I found from this video. I am unsure if it is outdated.

For some strange reason, when my character is descending and touches the ground again, sometimes the character will levitate a minuscule amount off the ground. During this time, jumping and horizontal movement still works. My sprites are centered.

Here is the code for the vertical collisions. It is within a step event; vsp is vertical speed and obj_floor is the floor. The rest of the code can be found in the video, but I can post it here if needed.
Code:
if (place_meeting(x, y+vsp, obj_floor))
{
    while(!place_meeting(x,y+sign(vsp),obj_floor))
    {
        y += sign(vsp); 
    }
    vsp = 0;
}
The player sprite is 44*92 and the floor objects are 64*64.

It is very apparent here.

Again, it is ever so slightly above the floor.

Here is a picture of the collisions working properly.

If can can provide more information if needed.
 
Last edited by a moderator:
D

Diogo

Guest
It may be the vsp? try vsp=1;
You may be moving the character too much in the opposite direction (up).

Edited: Nevermind, you're using sign, my bad.
 
C

Conlee

Guest
It may be the vsp? try vsp=1;
You may be moving the character too much in the opposite direction (up).

Edited: Nevermind, you're using sign, my bad.
Thank you for trying to help me. I have already tried using y += 1 instead of y += sign(vsp) with the same result, so I don't believe it is an issue with math.

Could this bug have something to do with the room size?
 
D

Diogo

Guest
Could this bug have something to do with the room size?
I don't think it should. You can try to align the sprite directly, though.

Instead of a while, you set its position directly with x=sign(x-other.x)*(other.x+other.sprite_get_width(other.sprite_index)/2 + sprite_get_width(sprite_index)/2);

sign(x-other.x) gives you the direction.
"other" is the wall's id. You can get it with instance_place (returns the id instead of a boolean).
This code isn't very general, though, and it assumes centered sprites with box collision masks.
Wouldn't hurt to try, anyway!
 
C

Conlee

Guest
I don't think it should. You can try to align the sprite directly, though.

Instead of a while, you set its position directly with x=sign(x-other.x)*(other.x+other.sprite_get_width(other.sprite_index)/2 + sprite_get_width(sprite_index)/2);

sign(x-other.x) gives you the direction.
"other" is the wall's id. You can get it with instance_place (returns the id instead of a boolean).
This code isn't very general, though, and it assumes centered sprites with box collision masks.
Wouldn't hurt to try, anyway!
Code:
if (place_meeting(x, y+vsp, obj_floor))
{
    //other = instance_place(x, y+vsp, obj_floor)
 x=sign(x-other.x)*(other.x + other.sprite_get_width(other.sprite_index)/2 + sprite_get_width(sprite_index)/2);
It is saying it expects a variable name at "other.sprite_get_width. I am unsure if I am even using this line you gave me correctly- could you help me out a bit? Is "Other" a variable I have to define?
I turned the line I had into a comment, but I tried using it as well. Sorry, I'm a bit inept with GML (and obviously most programming)
 
D

Diogo

Guest
That was my bad! It's just sprite_get_width(other.sprite_index).
Also, I gave you the code for horizontal collision. For vertical ones, you'll have to use y and sprite_get_height().

Sorry, I'm a bit inept with GML (and obviously most programming)
No worries, we all have to start somewhere!

"other" is a useful constant when using the "with" statement, but it was a bit misplaced, here.
In this case, it is a variable you need to define.
Instead of "other", do, for example, var wall=instance_place(x, y+vsp, obj_floor);
And then wall.sprite_index.
 
C

Conlee

Guest
That was my bad! It's just sprite_get_width(other.sprite_index).
Also, I gave you the code for horizontal collision. For vertical ones, you'll have to use y and sprite_get_height().


No worries, we all have to start somewhere!

"other" is a useful constant when using the "with" statement, but it was a bit misplaced, here.
In this case, it is a variable you need to define.
Instead of "other", do, for example, var wall=instance_place(x, y+vsp, obj_floor);
And then wall.sprite_index.
Code:
if (place_meeting(x, y+vsp, obj_floor))
{
    var wall=instance_place(x, y+vsp, obj_floor);
 y=sign(y-wall.y)*(wall.y + sprite_get_height(wall.sprite_index)/2 + sprite_get_height(sprite_index)/2);
Alright; it's starting to work, but whenever the character lands he sometimes is moved to the top of the room, then descends back down 1-2 time before landing (And sometimes when he lands he is slightly above the ground :( )

Also, thank you for putting up with me :p
 
D

Diogo

Guest
Sorry, it's late. And not your fault at all, I'm the one providing wrong code. xD

What I'm doing is placing the character right next to the wall. So, we start with the wall's position, and place the character sprite_get_height(wall.sprite_index)+sprite_get_height(self.sprite_index) to the correct side. Here, side means whether you sum or subtract (right vs. left; down vs. up) the value to the wall's position.

dir = sign(y-wall.y)
y = wall.y + dir * ( sprite_get_height(wall.sprite_index)/2 + sprite_get_height(sprite_index)/2 ).

This "dir" wouldn't work is y==wall.y. So you may want to change it to something more reliable.

If this doesn't work, sorry, but I'll check again tomorrow! Should go better with a fresh head.
 
Last edited by a moderator:
C

Conlee

Guest
Update: After going to the code I was using originally, I figured out that I can recreate the problem by jumping onto the lower block- however, if I jump to the higher block (Which lands fine most of the time), then walk off onto the lower block, it lands pixel perfect. If I walk off the highest block onto the lowest block, it lands fine. If I land with with pixel gap onto the lower block, then walk off, most of the time it fixes itself.

I plan on adding another check, where if vsp = 0, then check beneath the player character for a floor.

Edit: Good news and bad news!

Code:
if (place_meeting(x, y+vsp, obj_floor))
{
   // var wall=instance_place(x, y+vsp, obj_floor);
   // dir = (y-wall.y)
//y = wall.y + dir * ( sprite_get_height(wall.sprite_index)/2 + sprite_get_height(sprite_index)/2 )
 //y=sign(y-wall.y)*(wall.y + sprite_get_height(wall.sprite_index)/2 + sprite_get_height(sprite_index)/2);
    while(!place_meeting(x,y+sign(vsp),obj_floor))
    {
        y += sign(vsp);   // basically, fall until the pixel below is our floor
    }
    vsp = 0;
}
if vsp = 0
{
    if !place_meeting(x, y + 1, obj_floor)
    {
     while(!place_meeting(x,y+1,obj_floor))
     {
      y += 1;
     }
    }
}
y += vsp;
Obviously, this creates issues at the peak of the jump and the instant the character walks off of something, but there's no more gaps between the floor! I am now going to work on fixing the jump peak/walk off issues.

Edit 2:
I think I have proof that this isn't a math error-

Code:
if vsp = 0
{
if (!place_meeting(x, y+1, obj_floor))
{
    if place_meeting(x, y + 15, obj_floor)
    {
     while(!place_meeting(x,y+1,obj_floor))
     {
      y += 1;
     }
    }
    }
}
This was something I made as a tester- basically, when the player is not falling, check every frame to make sure that the floor is only 1 pixel below the sprite, and if it isn't (aka floating) check to see if the floor is at least 15 pixels below the sprite. The bug is still happening, but a little less frequently and I am unable to tell what causes it.
 
Last edited by a moderator:
C

Conlee

Guest
Ok, last post until I get help! I swear this time!

I took these 2 pictures of the same room without moving the character, the only difference is that I resized the window. The objects changed sized and scaled as expected, but the gap remained 1 pixel, independent of the window size.



Final edit:

Wow, I spent WAY too long on this then I'd like to admit. Apparently in the object I had this near the beginning:
Code:
if (place_meeting(x,y+2,obj_floor)) //
{
vsp = jumpkey * -jumpsp
}
I feel really, really dumb right now.
 
Last edited by a moderator:
Top