LibGDX box2D Moving Platfromer and Player

Hi.

I want player to stay on the moving platform without sliding and if i want to move i want player to move freely on platform even when platform moves.
So what i did is i add moving platform’s velocity to player’s body but player still sliding. I look up the problem on google and here but can’t find a solution. Some people add platform’s speed to player body’s setTransform method but it is just not working or i am doing something wrong.

I am adding executable jar file:
https://drive.google.com/file/d/1hvn6S7phjv051h8OA1UBNrfolJwEteTf

and source code:
https://github.com/ingriddev/Libgdx-Box2d-Platformer

playerUpdate method in Player class is where i add platform’s velocity to player.

To control player use arrow keys and press ‘x’ to show box2d debug renderer.
I hope i explain it good.
Thanks in advance. :slight_smile:

Hi, have you tried to add some more friction to the moving platform? What happens then, is it makes movement on the platform difficult? To think about it as a simulation, there have to be more downforce for the player, I guess. Also there is kinda wacky solution - to add an invisible helper object that will attach player to the platform until player jump :stuck_out_tongue:

I found the bug that causes your issue, you dampen the linear velocity after you apply the velocity of the moving platform:
https://github.com/ingriddev/Libgdx-Box2d-Platformer/blob/master/core/src/com/ingriddev/game/entities/Player.java#L90

        // This also runs while on a moving platform duh
        if(!isPressingAnyButton()) {
            float lx = body.getLinearVelocity().x *= 0.78f;  //TODO dampling value
            //float ly = body.getLinearVelocity().y *= 0.9f;
            body.setLinearVelocity(lx, body.getLinearVelocity().y);

        }

You’re disabling this when no button is pressed but it’s still enabled when the player is on a platform, that’s what is slowing down the player while on a platform.

You can’t simply fix this by disabling the dampening while on a platform though, as this causes another bug! The player won’t slow down again if you move while standing on a platform. Instead you need to separate the platform velocity and player velocity by keeping track of the player velocity separately and then adding the platform velocity to that if on a platform.

As another option, have tried working with the friction variable yet as SugarBlood suggested? Maybe you could go by without applying platform velocity altogether if you use friction, read this topic: https://www.badlogicgames.com/forum/viewtopic.php?f=11&t=15894

I tried and yes it makes movement on platform really difficult if i add more friction to platform player doesn’t move at all. Sliding problem solved my removing the dampening value.
For movement on platforms i am thinking something like this: When platform moves to left faster and player wants to move left, instead of adding just platform’s velocity to player i will add extra values to make it move normally just like on the ground and if platform moves to the right i will extract some values to stop the player moving so fast to left and vice versa.

Thank you for the answer. :wink:

Thank you. Now player stay on the platform without sliding. :smiley: I remove that dampening value completely and i will work with friction values now. Movement on the ground feels weird now. Player stuck at walls because of the friction but i can add sensors to left and right side of the player and disable the movement when sensors touched walls. Or i can add wheels under the player. I update the code on github.

[quote]I remove that dampening value completely and i will work with friction values now. Movement on the ground feels weird now.
[/quote]
Well… What did you expect? Read this again:

[quote]Instead you need to separate the platform velocity and player velocity by keeping track of the player velocity separately and then adding the platform velocity to that if on a platform.
[/quote]
You can and should keep your dampening code, just make sure you only apply the dampening on the player initiated portion of the velocity by tracking the player speed separately in some class level variable and you’re golden.

I tried something. What do you think? I removed the dampening code because this one works better i think.
Jar file:
https://drive.google.com/open?id=1LOxWiRm2z9_dmfZTzYjDqUaBX-Ojkixy


    private float velocity = 0;
    private float run_velocity = 12;
    private float jump_velocity = 12;
    private float increase_value = 2f;
    private float decrease_value = 1f;

    private void playerUpdate(){

        if(rightButton && !leftButton){
            velocity += increase_value;
            playerState = State.RUN;
            if(velocity >= run_velocity){
                velocity = run_velocity;
            }
        }

        if(!rightButton && leftButton){
            velocity -= increase_value;
            playerState = State.RUN;
            if(velocity <= -run_velocity){
                velocity = -run_velocity;
            }
        }

        if(!rightButton && !leftButton){ //&& !isTouchedPlatform){
            if(velocity > 0){
                velocity -= decrease_value;
                if(velocity <= 0){
                    velocity = 0;
                }
            }

            if(velocity < 0){
                velocity += decrease_value;
                if(velocity >= 0){
                    velocity = 0;
                }
            }

            if(velocity == 0){
                velocity = 0;
            }
        }

        body.setLinearVelocity(velocity, body.getLinearVelocity().y);

        if (upButton && ground > 0) {
            body.applyLinearImpulse(new Vector2(0, jump_velocity), body.getWorldCenter(), true);
        }

        if(isTouchedPlatform){

            float mpx = movingPlatform.getLinearVelocity().x;
            float mpy = movingPlatform.getLinearVelocity().y;

            if(!rightButton && !leftButton && !upButton) { // if we stand on platform.
                velocity = 0;
                body.setLinearVelocity(mpx, mpy);

            }else{  // if we try to move on platform.

                if (!upButton) {

                    if(mpx > 0 && velocity > 0){
                        body.setLinearVelocity((velocity /2) + mpx, mpy);
                    }

                    if(mpx < 0 && velocity <  0){
                        body.setLinearVelocity((velocity /2) + mpx, mpy);
                    }

                    if((mpx > 0 && velocity < 0) || (mpx < 0 && velocity > 0)){
                        body.setLinearVelocity(velocity + mpx, mpy);
                    }

                }
            }
        }
    }


This works well with slow platforms and is absolute garbage with fast ones (player does not retain platform speed after jumping) because you do not actually layer the velocities.

    private float velocityX = 0;
    private float run_velocity = 12;
    private float jump_velocity = 12;
    private float increase_value = 2f;
    private float decrease_value = 1f;

    private void playerUpdate(){

        if(rightButton && !leftButton){
            velocityX += increase_value;
            playerState = State.RUN;
            if(velocityX >= run_velocity){
                velocityX = run_velocity;
            }
        }

        if(!rightButton && leftButton){
            velocityX -= increase_value;
            playerState = State.RUN;
            if(velocityX <= -run_velocity){
                velocityX = -run_velocity;
            }
        }

        if(!rightButton && !leftButton){ //&& !isTouchedPlatform){
            if(velocityX > 0){
                velocityX -= decrease_value;
                if(velocityX <= 0){
                    velocityX = 0;
                }
            }

            if(velocityX < 0){
                velocityX += decrease_value;
                if(velocityX >= 0){
                    velocityX = 0;
                }
            }

            if(velocityX == 0){
                velocityX = 0;
            }
        }

        // Layer the platform velocity on top of the bodies velocity if on a platform
        if(isTouchedPlatform){

            float mpx = movingPlatform.getLinearVelocity().x;
            float mpy = movingPlatform.getLinearVelocity().y;
            
            // Vertical movement can't be added up since you do not have a constant reference like with velocityX
            // adding body.getLinearVelocity().y and mpy would make the player spazz around on up/down movement.
            // Idk if this makes the player stick to the platform when trying to jump though
            body.setLinearVelocity(velocityX + mpx, mpy);

        } else {
            body.setLinearVelocity(velocityX, body.getLinearVelocity().y);
        }

        if (upButton && ground > 0) {
            body.applyLinearImpulse(new Vector2(0, jump_velocity), body.getWorldCenter(), true);
        }
    }

I fixed the jumping problem like this.(probably not a good solution to be honest) It looks okay i guess. Also changed float velocityX value to Vector2 class. Like you said i need to vertical reference like horizontal one. I am working on it.


if(isTouchedPlatform) {

    float mpx = movingPlatform.getLinearVelocity().x;
    float mpy = movingPlatform.getLinearVelocity().y;

    if (!upButton) {
        body.setLinearVelocity(velocity.x + mpx, mpy);
    }else{
        body.setLinearVelocity(velocity.x + mpx, body.getLinearVelocity().y);
    }
}else{ //.....

If I may, I would recommend use State Pattern for your player states, otherwise you gonna have a bunch of flags around your inputs and that’s really error prone.

something like:

JumpingState
onGroundState
onPlatformState

The State class can be a nested class, for example.

Then you just use inputs for each state and don’t need to worry about flags all around the house.

Good lecture: http://gameprogrammingpatterns.com/state.html

Regards!