Momentum from moving platform. Need help

Galla

Member
Hi,

how could I read the movement speed (x,y) from a platform that I'm standing on?
I'm new to Gamemaker programming any help is appreciated.

Gamemaker 2 ( 2.2.5.481 )

objPLayer Step event:

GML:
///Does this mean I'm standing on the platform?
if place_meeting(x,y+1,objMovingPLatform)
{
    if gamepad_button_check_pressed(0,gp_face1) //Jump button
    
    {
        jump_height = jump_height * other.vsp /// does this makes sense?
                                             ///vsp is the vertical speed of the platform
    }
    jump_height = jump_height
    //How to get my normal jump_height back?
}
 
There are a couple of things wrong here and other things to consider. First off your code seems to only be concerned with momentum from jumping off the platform, not getting "carried" by it yet, so I'll just focus on that.

  • The place_meeting is indeed checking for a moving platform object below you, i.e. that you are "standing" on it... more or less.
  • I don't think "other" will refer to the right object here. "other" is correct in collision events with "other" objects, which isn't where this code is being called! Instead you should use instance_place. See the code below for an example.
  • Multiplying your jump height with the other object's vspeed doesn't really make sense. To help you think what the code should be doing, try to think of things case-by-case. Let's say you try to jump on a platform that isn't moving. You'd expect your jump_height to be normal, right? But here you get a height of 0 instead, since jump_height * 0 = 0! A much more sensible formula might be jump_height + other.vsp.
  • Setting jump_height directly and then wanting to get your normal height back is an interesting question to ask. The next question to ask is, "what is jump_height"? Is it an indicator of your player's default jump velocity, or the one used for each individual jump? Why not have one variable for the default which is never changed, and then another for your movement? I'd recommend jump_height for the default value, which you never SET and only READ, and then vsp directly for your movement speed afterwards. I assume you use vsp elsewhere. What's the point in not setting it directly when you see the player pressed jump on the platform? I assume you do something like vsp = -jump_height elsewhere, in the code below I just did that directly plus the momentum from the platform.

Here is the modified code with those considerations above taken into account.

GML:
//Get the platform below you.
// If there is one, its id will be saved to myPlat.
// If there is not, myPlat will be set to the special id "noone".
var myPlat = instance_place(x, y+1, objMovingPLatform);
if ( myPlat != noone )
{
    if gamepad_button_check_pressed(0,gp_face1) //Jump button
    {
        vsp = -jump_height + myPlat.vsp;
                                            
    }
}
 

Galla

Member
There are a couple of things wrong here and other things to consider. First off your code seems to only be concerned with momentum from jumping off the platform, not getting "carried" by it yet, so I'll just focus on that.

  • The place_meeting is indeed checking for a moving platform object below you, i.e. that you are "standing" on it... more or less.
  • I don't think "other" will refer to the right object here. "other" is correct in collision events with "other" objects, which isn't where this code is being called! Instead you should use instance_place. See the code below for an example.
  • Multiplying your jump height with the other object's vspeed doesn't really make sense. To help you think what the code should be doing, try to think of things case-by-case. Let's say you try to jump on a platform that isn't moving. You'd expect your jump_height to be normal, right? But here you get a height of 0 instead, since jump_height * 0 = 0! A much more sensible formula might be jump_height + other.vsp.
  • Setting jump_height directly and then wanting to get your normal height back is an interesting question to ask. The next question to ask is, "what is jump_height"? Is it an indicator of your player's default jump velocity, or the one used for each individual jump? Why not have one variable for the default which is never changed, and then another for your movement? I'd recommend jump_height for the default value, which you never SET and only READ, and then vsp directly for your movement speed afterwards. I assume you use vsp elsewhere. What's the point in not setting it directly when you see the player pressed jump on the platform? I assume you do something like vsp = -jump_height elsewhere, in the code below I just did that directly plus the momentum from the platform.

Here is the modified code with those considerations above taken into account.

GML:
//Get the platform below you.
// If there is one, its id will be saved to myPlat.
// If there is not, myPlat will be set to the special id "noone".
var myPlat = instance_place(x, y+1, objMovingPLatform);
if ( myPlat != noone )
{
    if gamepad_button_check_pressed(0,gp_face1) //Jump button
    {
        vsp = -jump_height + myPlat.vsp;
                                           
    }
}

Yep, it's working I got the same answer on Reddit. I got some more question if you have time to answer :) What's the difference between place_meeting and instance_place? Is one better or more accurate? And thank you for the detailed explanation I really appreciate the help.
 
The docs on place_meeting explain when/why you'd want to use instance_place. Basically you want to not only check for a collision with an object, but then do something with that specific object later. One is not "better" or "more accurate", it all depends on what you're trying to accomplish!
 

Galla

Member
Thanks for the info. If you excuse i have one more question this is the last one I promise. If I want to store the hsp of my moving platform just before it stops? I'm trying to give the player a window to react before its too late, basically saying a Coyote jump.

I think the script will explain it better.
GML:
action_inherited();

if (place_meeting(x, y-1, objBlock))
        vsp = 0;
if (place_meeting(x, y+1, objBlock))
        vsp = 0;


// To chnage the direction and start moving the platform 
var playerAbovePrev = playerAbove;
playerAbove         = place_meeting(x, y - 1, objPlayer);

if (playerAbove && !playerAbovePrev) {
        

     if (image_index == 0){
         vsp =spd
        image_index = 1;
     }
    else
    {
        vsp=-spd
        image_index = 0;
    }

}
My player reads the hsp of the platform and adds it to the jump. See @blockdude11 answer to my first question.


What i was think was to keep the platform moving even its colliding the wall for 4 frames so the player can react. But im not sure how to make it. Any help is appreciated.
MomentumPlatformVertical.gif
 

Nidoking

Member
Just store some kind of active momentum variable that lags a few steps behind and use that instead of the momentum that's used for movement. You can push the values into a list, queue, or array to make them easier to track that way.
 

Galla

Member
Just store some kind of active momentum variable that lags a few steps behind and use that instead of the momentum that's used for movement. You can push the values into a list, queue, or array to make them easier to track that way.
Never tried arrays. How can i queue something?
 

Galla

Member
Found another way. I'm not calculating the vsp or hsp of the platform for my jump. I made a variable of the hsp and vsp and waiting for 3 frames to reset it to the vsp or hsp. If that makes sense. I'm sure there is a better way but this is what my programing skills gave me :p

Script from a horizontal moving platform.
GML:
action_inherited();
///////Start countdown spd_keep like coyote jump
        if (place_meeting(x-1, y, objBlock))
            hsp = 0;
        if hsp == 0
            spd_keep --
        if (place_meeting(x+1, y, objBlock))
            hsp = 0;
        if hsp == 0
            spd_keep --


// To chnage the direction and start moving the platform
var playerAbovePrev = playerAbove;
playerAbove         = place_meeting(x, y - 1, objPlayer);

if (playerAbove && !playerAbovePrev) {
////////Change spd_max to positive or negative on jumping
        if (spd_max =+spd_max)
            spd_max =-spd_max
        else
            spd_hsp=spd_max
/////Sprite change and direction start on platform jump
     if (image_index == 0){
         spd_hsp = spd_max
        spd_keep = spd_keep_max
         hsp =spd_max
        image_index = 1;
     }
    else
    {
        spd_hsp = spd_max
        spd_keep = spd_keep_max
        hsp=spd_max
        image_index = 0;
    }

}
////Reset countdown
if spd_keep <= 0
    spd_hsp = hsp
 
else
    spd_hsp = spd_max;
 
Top