Legacy GM Edge Sliding problem (from Bomberman games)

Hi guys,
I was problem to development one feature used in the Bomberman game:Edge Sliding.

If player is on the edge of a block and tries to go down, but the tile down is blocked and if tile next to this block is walkable, the player will gently slide onto it.

I tried too many and still could figuring out. The objects are 16x16 and with orgin point point at. I'll post the important code of this problem.

obj_player's create event:
vx=0;//horizontal speed
vy=0;//vertical speed
vxmax=2;//absolute max horizontal speed
vymax=vxmax;//absolute max vertical speed
acc=vxmax;//accelaration to the motion. set to vxmax or vymax value if you want skip the smooth transition
fric=vxmax;//friction to the motion. set to vxmax or vymax value if you want skip the smooth transition

//For sub-pixel motion
cx=0;
cy=0;

state=pstate.idle;//Player state
prevstate=state;//previous Player state
facing=270;//Facing direction : 0 Right 90 UP 180 Left 270 Down
pfacing=270;


obj_player's step event:

// Input //////////////////////////////////////////////////////////////////////
var kLeft, kRight, kUp, kDown, kBomb;

kLeft = left_held_input();
kRight = right_held_input();
kDown = down_held_input();
kUp = up_held_input();
kBomb = bomb_pressed_input();

////////////////////////////////////////////

////////////////////////////////////////// Left movement
if (kLeft and not kRight) {
vx=Approach(vx,-vxmax,acc);
if(state==pstate.idle)state=pstate.walk;
facing =180;
}
////////////////////////////////////////// Right movement
else if (kRight and not kLeft) {
vx=Approach(vx, vxmax,acc);
if(state==pstate.idle)state=pstate.walk;
facing =0;
}
////////////////////////////////////////// Stops Action
else if (not kRight and not kLeft){
vx=Approach(vx,0,fric);
if(state==pstate.walk) state=pstate.idle;
}

////////////////////////////////////////// Left movement
if (kUp and not kDown) {
vy=Approach(vy,-vymax,acc);
if(state==pstate.idle)state=pstate.walk;
facing =90;
}
////////////////////////////////////////// Right movement
else if (kDown and not kUp) {
vy=Approach(vy, vymax,acc);
if(state==pstate.idle)state=pstate.walk;
facing =270;
}
////////////////////////////////////////// Stops Action
else if (not kUp and not kDown){
vy=Approach(vy,0,fric);
if(state==pstate.walk) state=pstate.idle;
}

scr_player_hmotion();
scr_player_vmotion();


scr_player_hmotion()
var vxNew,yy;

cx += vx;
vxNew = round(cx);
cx -= vxNew;

// Horizontal
repeat(abs(vxNew)) {
yy=y+7;
yy=round(yy/grid_size)*grid_size;
if(not place_meeting(x+sign(vxNew),yy,obj_block))
y+=sign(yy-y);

if(not place_meeting(x+sign(vxNew),y,obj_block))
x+=sign(vxNew);
else {
vx= 0;
break;
}
}

scr_player_vmotion()
var vyNew,xx;


cy += vy;
vyNew = round(cy);
cy -= vyNew;

// Vertical
repeat(abs(vyNew)) {
xx=x+7;
xx=round(xx/grid_size)*grid_size;
if(not place_meeting(xx,y+sign(vyNew),obj_block))
x+=sign(xx-x);

if (not place_meeting(x, y + sign(vyNew),obj_block))
y+=sign(vyNew);
else {
vy= 0;
break;
}
}


The motion is based of using repeat loop method that I saw in the ZackBellBlog. If some one can give a idea of how implementing the edge sliding, I'll appreciate.






 
I'm not going to give you code directly, because there's a ton of different ways to go about it, but the rough idea is this:

1) If there is a collision in the direction you're moving in, determine which direction left or right relative to the movement is closer. In the event of a tie, choose one, but not randomly, as it could cause jittering
2) Check the tile in that relative direction, and if it's free, move laterally in the same direction instead of moving forward
3) If the above tile is not free, you can check the farther direction, if this is what you want, and repeat as above
4) If neither direction is free, then movement stops

Again, this is a rough outline, but it's basically how I've achieved it in the past and it's worked flawlessly.
 
Hi staineddofmind,
Firstly, thanks for the hint. In theory , I already think in these steps, and still didn't solved. But now I discovered the problem is when you press 2 directional keys of the same time (UP+Right for example), turning the player imovable. Because the horizontal motion is independent of vertical motion, so one cancel the effect of the other. Anyway, adding some if cases solve my problem for good.
 
Top