GameMaker [SOLVED]: One Way Platforms

Dividious

Member
So after changing to a FSM to solve some other issues and getting rid of the Shaun Spalding Platform Code and replacing it. My horizontal and vertical moving platforms work, however i can't figure out how to do a One Way "passthru/jumpthru/fallthru" type platform. Currently my player object has the main collision code in a script while platform code resides in the player step event.

I do have an "par_platforms" parent object for obj_h_platform, obj_v_platform, obj_passthru


Player Object-Step Event
Code:
if (object_id != noone)

    {
        if (x <= object_id.bbox_left) || (x >= object_id.bbox_right) object_id = noone;
    }
//Verticle Moving Platforms Collision

//New Value
var nvspd = round(vspd=min(vspd+gravity_inc*false,gravity_max));

//Recalculates with the New Value
if (place_meeting(x,y+nvspd,_solid_parent))
    {
        while(!place_meeting(x,y+sign(nvspd),_solid_parent))
            {
                y = y + sign(nvspd);
            }
        vspd = 0;

        var object_inst = instance_place(x,y+1,_solid_parent);
        if (object_inst != noone) object_id = object_inst;
    }
y = y + vspd;

Move_Player Script
Code:
against_wall = [0,0];
/// @description ap_move_player
/// @param {real} Control_Effectivness >=0
/// @param {real} Friction_Effectivness >=0
/// @param {real} Gravity_Effectivness >=0
/// returns array representing the vector of detected collisions

//Horizontal

hspd += (right[held]-left[held])*(move_accel*argument0);

hspd=clamp(hspd,-move_max_speed,move_max_speed);
if(place_meeting(round(x)+ceil_signed(hspd),round(y),_solid_parent))
{
    round_position();
    while(!place_meeting(x+sign(hspd),y,_solid_parent))
        x+=sign(hspd);
    against_wall[0]=sign(hspd);
    hspd=0;
}

x+=hspd;
hspd=approach(hspd,0,move_friction*argument1);

//vertical
vspd=min(vspd+gravity_inc*argument2,gravity_max);
if(place_meeting(round(x),round(y)+ceil_signed(vspd),_solid_parent))
{
    round_position();
    while(!place_meeting(x,y+sign(vspd),_solid_parent))
        y+=sign(vspd);
    against_wall[1]=sign(vspd);
    vspd=0;
    grace_frames=max_grace_frames;
}
else
    grace_frames -= grace_frames > 0;
y+=vspd;

wall_escape(_solid_parent);

obj_v_platform Create Event
Code:
dir=-1; //direction vertical]spd=1;
vspd=0;
hspd=0;

obj_v_platform Begin Step Event
Code:
vspd=dir*spd;
//Vertical Collision

if(place_meeting(round(x),round(y)+ceil_signed(vspd),_solid_parent))
{
    round_position();
    while(!place_meeting(x,y+sign(vspd),_solid_parent))
        y+=sign(vspd);
    vspd=0;
    dir*=-1;
}
y+=vspd;
if (obj_ap_player.object_id = id)
    {
        obj_ap_player.x += hspd;
        obj_ap_player.y += vspd;
        if (obj_ap_player.bbox_bottom >= bbox_top) obj_ap_player.y--;
    }
I know its not the most beautiful slapped together code but it works.. except the One Way "passthru/jumpthru/fallthru" part... I've tried many different methods and I just cant get it to work.. or maybe they all have and just the inputs are jacked.

just in case here is the input


GetInput Script
Code:
var _key = vk_shift;
engarde[pressed] = (keyboard_check_pressed(_key)||gamepad_button_check_pressed(0,gp_shoulderlb));
engarde[released] = (keyboard_check_released(_key)||gamepad_button_check_released(0,gp_shoulderlb));
if(keyboard_check(_key))
    engarde[held]++;
else
    engarde[held]=0;
 
var _key = ord("D");
slide[pressed] = (keyboard_check_pressed(_key)||gamepad_button_check_pressed(0,gp_face2));
slide[released] = (keyboard_check_released(_key)||gamepad_button_check_released(0,gp_face2));
if(keyboard_check(_key))
    slide[held]++;
else
    slide[held]=0;

var _key = ord("A");
attack[pressed] = (keyboard_check_pressed(_key)||gamepad_button_check_pressed(0,gp_face3));
attack[released] = (keyboard_check_released(_key)||gamepad_button_check_released(0,gp_face3));
if(keyboard_check(_key))
    attack[held]++;
else
    attack[held]=0;

_key = ord("S");
jump[pressed] = (keyboard_check_pressed(_key)||gamepad_button_check_pressed(0,gp_face1));
jump[released] = (keyboard_check_released(_key)||gamepad_button_check_released(0,gp_face1));
if(keyboard_check(_key))
    jump[held]++;
else
    jump[held]=0;
 
_key = vk_left;
left[pressed] = (keyboard_check_pressed(_key)||gamepad_button_check_pressed(0,gp_padl));
left[released] = (keyboard_check_released(_key)||gamepad_button_check_released(0,gp_padl));
left[held] = (keyboard_check(_key)||gamepad_button_check(0,gp_padl));

_key = vk_right;
right[pressed] = (keyboard_check_pressed(_key)||gamepad_button_check_pressed(0,gp_padr));
right[released] = (keyboard_check_released(_key)||gamepad_button_check_released(0,gp_padr));
right[held] = (keyboard_check(_key)||gamepad_button_check(0,gp_padr));

_key = vk_up;
up[pressed] = (keyboard_check_pressed(_key)||gamepad_button_check_pressed(0,gp_padu));
up[released] = (keyboard_check_released(_key)||gamepad_button_check_released(0,gp_padu));
up[held] = (keyboard_check(_key)||gamepad_button_check(0,gp_padu));

_key = vk_down;
down[pressed] = (keyboard_check_pressed(_key)||gamepad_button_check_pressed(0,gp_padd));
down[released] = (keyboard_check_released(_key)||gamepad_button_check_released(0,gp_padd));
down[held] = (keyboard_check(_key)||gamepad_button_check(0,gp_padd));

var _h = right[held]-left[held];
if(point_distance(0,0,_h,0) > 0)
    dpad_dir=point_direction(0,0,_h,0);
else
    dpad_dir=no_direction;
any help would be great
 
Last edited:

TheouAegis

Member
Is vspd greater than 0? If so, get the id of the pass-thru platform it will collide with. Is the player currently colliding with that platform? If so, you can't land on it.
 

Dividious

Member
The player whilst on or riding on "colliding" with platforms has no issues. The player rides the platforms perfectly... horizontally and vertically, the issue lies when trying to fall through via holding a key or to just jump up through the platform.. but it failed, no matter which way i coded the passthrough. I've tried many ways... it took me awhile to even get the vertical platform to work with out player microfalling or player constantly sliding off the platform. Once i got the moving platforms and collisions to work i went on to try the better types of passthrough instead of the previously used spalding mask method.
 

TheouAegis

Member
I'm not talking about Spalding's code at all. I'm talking about the actual mechanics for a pass-thru platform. You first check if your vertical speed is positive (or in a reverse gravity game, negative...). Then you find if you are going to collide with a pass-thru platform; then you check if you're not already colliding with that platform. Or if you prefer post-motion collision detection, you check if you're already colliding with a platform and then check if you weren't previously colliding with it.

It's essentially the same principle as killing a Goomba.
 

Dividious

Member
Ah my mistake i misinterpreted what you were saying. I applied my previous attempts at a passthru as all versions made logical sense... but i decided to change my input method as i attempted to hold the passthru button i noticed a slight subpixel jitter that would occur with the player once every time the button was pushed...

My old input was down[held]
My new input is down_held

However they both equal the same
But had different outcomes... odd...
Not sure if it was a bandaid or actual fix
 

TheouAegis

Member
down[held] is an array, which is fine if you had something like this:

Create Event:
press = 0;
held = 1;

Step Event:
down[press] = keyboard_check_pressed(vk_down);
down[held] = keyboard_check(vk_down);

in either case, press and held should have been enumerators, but it's not a huge deal. What's important is that doing it this way, press and held should never get modified ever again. They are meant to be enumerators and that's it, meaning you set them at the beginning of the game and don't touch them ever again. if you change the value of either one of them, you would be changing which index in the array you are actually looking at.

in your Band-Aid, I'm just going to call that even though it may or may not actually have been a Band-Aid, you are ensuring that the variable you set is correct because there's no way to modify the pointer. So if that works for you, then that suggest your previous method is mishandling the array format.
 

Dividious

Member
see, i was thinking that being the input is an array that the coding i was using as the platform passthru activation was at fault. I've probably tried 5 different methods or so just each time i was using the array improperly.. thanks for the insight TheouAegis sometimes a second pair of eyes and a fresh look and confirmation is all we need!
 
Top