I've gone about this a quite differently, but I'll show you how I do it and maybe it'll shed some light on this problem for you.
Pretty much I have two variables for x movement: xcount and xspeed.
The "xcount" variable might not be needed for you, because it's only used for "part-pixel" movement. Simply put, it allows the character to move at speeds under 1 pixel per step. If your graphics are high res, then you might not need such precision, but I'll put it in because it's pretty simple to understand anyway.
Now the "xspeed" variable is how fast the character is going. All of the code for adding or subtracting to the character's speed is put before the actual x movement (of course). For example, you can have all of your friction and whatnot taken into the equation beforehand.
Some terms you may need to know:
- "frac" gets the part of a number after the decimal point (e.g. "3.452" would return ".452").
- "abs" gets the absolute value, so a "-5" would return as just "5"
- "sign" can only return -1, 0, or 1 (i.e if the value of xspeed is greater than 0, sign returns a 1, if it's 0, sign returns a 0, and if it's lower than 0, sign returns -1)
Now that you know all that, here is an example of the code I'm using in my game:
//GET "PART-PIXEL" MOVEMENT
//xcount number = last fraction of xspeed plus current xspeed
xcount = frac(xcount) + abs(xspeed);
//X MOVEMENT AND SLOPE MOVEMENT
//do movement only if xcount = 1 or over
if xcount >= 1{
repeat (abs(floor(xcount))){
//if there's nothing solid at next x position, move 1 pixel over
if place_free(x+sign(xspeed),y){
x += sign(xspeed);
//if there is a solid 2 pixels below and no solid at 1 pixel below, move character down 1 pixel (for descending slopes)
if !place_free(x,y+2) && place_free(x,y+1){
y += 1;
}
}
//"else" just means there is something solid at next x position
else{
//(by already asking "else" we know there is a solid 1 over, so we ask..) if there is NO solid at position 1 over and 1 up, climb slope
if place_free(x+sign(xspeed),y-1){
y -= 1;
x += sign(xspeed);
}
else{
xspeed = 0;
break;
}
}
}
}
I hope I commented properly so it's easy enough to understand as opposed to sounding more complicated than it really is. I also took out a lot of code that takes special platforms into consideration (like platforms that you may jump up through and land on top of, etc).
I know your coding is very different, but I hope you can take something away from my code to figure out what is wrong with yours. Also, y movement is pretty much the same idea; if you understand the concept in this code, you'll have no problem with that.
One more thing: Game Maker kinda sucks with collision checking. The code I've shown is using the whole character's mask for checking, and it seems that yours is as well, which means that points of origin are kinda meaningless in this case. If your collision is as simple as a tall rectangle, this should work great, but you may need to have a mask the checks only the "feet" for this to work really well. In my game I was forced to frequently switch between multiple masks because the character's head is bigger than his body (which presents multiple problems, believe it or not).
Anyway, I hope I helped somehow, even though my approach is a little different.