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

The best box pushing mechanic for a platformer

M

Misu

Guest
I was told to start this thread. Anyway I have been struggling on how to do pushable boxes in a complicated level design. I lave slopes and gaps that can (will) also affect the boxes in the game. Of course Im not doing real physics. Im trying to pull off a basic gravity with simple character pushing it to move along.

Can anyone here help out establish the best way to perform this?
 

John Andrews

Living Enigma
Hello Misu! I read about your problem just now and wanted to help you, I'm no expert, and have only made pushable boxes twice in my life, but I hope this helps.

I would reccomend that you use the collision_line() methods for this, and I will try to cover slopes as well, with what I would do.

I'd make the boxes be moved by detecting collision with another entity, it can be a box, the player, a pushing thing like a piston, etc, like this:

Code:
//step event of the BOX

pusher_right = collision_line(right collision line of the box)
if pusher_right
{
    hspeed=pusher_right.hspeed
}

pusher_left = collision_line(left collision line of the box)
if pusher_left
{
    hspeed=pusher_left.hspeed
}
In case your box is in a slope:

Code:
//step event of the BOX

slope=collision_line(bottom collision line of the box)
if slope
{
    image_angle=slope.inclination
    //I assume your slope has a variable that designates it's inclination
 
}
And of course, your collision_line() parameters would need to follow the inclination of the slope by using lenthdir_x|y() to make it collide better,

The info I gave here might be vague, If you need more explanation or I missed something I'll try to reply with better info but I hope it helps.

Edit: I noticed I missed on how the box would move on a slope. well for that, I'd use the inclination the box has, and move along the angle by adding hspeed and vspeed with the lengthdir functions, like:
Code:
pusher = collision_line(where it collided)
{
    hspeed=lengthdir_x(pusher.hspeed,image_angle)
    vspeed=lengthdir_y(pusher.hspeed,image_angle)
}
 
N

nlolotte

Guest
I am using this to handle the pushing in the step event (normal state):
Code:
//Push Left
if (place_meeting(x-1,y,obj_solid_push) && (leftkeyheld) && grnd = 1)
{
    pushing = 1;
    i = instance_place(x-1,y,obj_solid_push);
    with i
    {
        if !place_meeting(x-1,y,obj_solid)
        {
            x -= 1;
         
            //Set Sprite
            with obj_player
            {
                sprite_index = spr_player_push;
                anim = "push";
            }
        }
        else
        {
            //Set Sprite
            with obj_player
            {
                sprite_index = spr_player_push;
                anim = "move";
            }
        }
    }
}

//Push Right
if (place_meeting(x+hspd,y,obj_solid_push) && (rightkeyheld) && grnd = 1)
{
    pushing = 1;
    i = instance_place(x+1,y,obj_solid_push);
    with i
    {
        if !place_meeting(x+1,y,obj_solid)
        {
            x += 1;
         
            //Set Sprite
            with obj_player
            {
                sprite_index = spr_player_push;
                anim = "push";
            }
        }
        else
        {
            //Set Sprite
            with obj_player
            {
                sprite_index = spr_player_push;
                anim = "move";
            }
        }
    }
}
I basically check to see if the player is colliding with the box whilst holding a key and grounded. The pushing variableis used to handle sprite change between running and pushing.



I move the x of the box which limits the speed of the player to be the same. As for slopes you could try and apply the same collision code you are using for your player to the box. I have done somthing similar to apply gravity to the boxes.
 
Last edited:
M

Misu

Guest
Sorry for the late reply @nlolotte and @John Andrews
Been getting out extremely late from my job over the past week and never had the chance to get on my computer once until today.

So I've been analyzing your information but it seems these techniques may not work properly. My biggest problem at the moment is that my collision may cause lag if the character is pushing the object towards another solid object.

This is what I have:
Code:
///hsp is the hspeed triggered base on left or right key input...
    if (place_meeting(x+hsp,y,obj_rock)){
            var ii = instance_place(x+hsp,y,obj_rock);
            if (y > ii.y-64)
            {
                hsp = clamp(hsp,-spd,spd);
                ii.move = 1;
                ii.hsp = hsp;
                ii.face = spd * sign(hsp);//for friction code (not important)
                if (!place_meeting(ii.x+sign(hsp),ii.y,obj_solid))
                {with(ii){event_perform(ev_step,0)}}///do rock's collision check
                hsp = 0;
                move = 0;
                //////////////////////
            }
            else if (y > ii.y-100)
            {
                while(!place_meeting(x+sign(hsp),y,obj_rock)){ x += sign(hsp); }
                x-=sign(hsp);
                hsp = 0;
            }
    }
x += hsp;
Rock's collision
Code:
    if (place_meeting(x+hsp,y,obj_solid)){
        var ystep = 0;
        while(place_meeting(x+hsp,y-ystep,obj_solid)&&(ystep <= abs(1*hsp))){++ystep;}
        if (place_meeting(x+hsp,y-ystep,obj_solid))
        {
            while(!place_meeting(x+sign(hsp),y,obj_solid)){ x += sign(hsp); }
            hsp = 0;
        }
        else{y -= ystep}
    }
x += hsp;
////slope collision
if (!place_meeting(x,y,obj_solid) && (vsp >= 0) {
    if (place_meeting(x,y+2+abs(hsp),obj_solid)){
        while(!place_meeting(x,y+1,obj_solid)) {++y;}
        }
}
////y collision
if (place_meeting(x,y+vsp,obj_solid)){
        while(!place_meeting(x,y+sign(vsp),obj_solid)){ y += sign(vsp); }
        vsp = 0;
}
y += vsp;
I know there has to be a better way of doing this. My code seems too inefficient to do the task.
 
Top