1. Hey! Guest! The 36th GMC Jam will take place between February 27th, 12:00 UTC - March 2nd, 12:00 UTC. Why not join in! Click here to find out more!
    Dismiss Notice
  2. NOTICE: We will be applying a Xenforo update on Tuesday 25th of February. This means that from approximately 10:00 to 14:00 BST the forums will be offline (or possibly longer). Sorry for the inconvenience! Official Announcement here.

GM:S 1.4 Physics platformer collision

Discussion in 'Programming' started by OctoMoosePrime, Jan 17, 2020.

  1. OctoMoosePrime

    OctoMoosePrime Member

    Joined:
    Jan 13, 2020
    Posts:
    4
    Hello everyone.
    I'm trying to make a local multiplayer platformer but can't get the basic collisions to work properly.

    I started by using the classic hsp/vsp movement/collision code from Shaun Spaldings platformer tutorials but I had problems implementing collisions with other players.
    (standing on, side-pushing, jumping with other player on top etc.)

    So I decided to instead try using Game Makers built in physics functions because that seemed like a logical approach.
    I found "Rm2kdev's physics platformer" youtube tutorial, and it solved the player to player functions without any additional code. So it feels like a better choice for the game.
    But here comes the problem he kept a bug where the wall is detected as ground, reseting the jump, making you able to climb walls, as a "feature".
    (And since obj_Player uses obj_Wall as parent, you're also able to chestbump other players all the way to space)

    Noone in the youtube comment section had an answer and the very few other "physics platformer" examples I found had the same issue.

    It's just using the built in physics collisions by putting an empty comment in a collision with obj_wall event, so i added a "if place_meeting(x,y+1,obj_wall)" to enable a jump, but it's detected when you collide on the x-axis aswell, even if you're not colliding on the y-axis.
    I thought i could cheat it by creating an object following obj_players feet and enable jumping when that object collide with obj_wall, but the tracking didn't follow the movements correctly, so not even that worked.

    How do i get "if place_meeting(x,y+1,obj_wall)" to only react on the x-axis, as it's supposed to?
    Does the built in collision somehow override the code, and if so how do i work around that?


    Obj_players code
    -Creation
    Code:
    phy_fixed_rotation = true;
    move_speed = 200;
    max_xspeed = 4;
    jump_force = -100;
    jumptimer = 0;
    dir = 1;
    
    -Step
    Code:
    ///Movement and collision
    key_right = keyboard_check(vk_right);
    key_left = keyboard_check(vk_left);
    key_jump = keyboard_check_pressed(vk_up);
    key_jump_held = keyboard_check(vk_up);
    
    if key_left{
        physics_apply_force(x,y,-move_speed,0);
        dir = -1;
    }else if key_right{
        physics_apply_force(x,y,move_speed,0);
        dir = 1;
    }else{
        phy_speed_x = (phy_speed_x/8 * 7); //decelleration
    }
    if key_jump{    //jump
        if  jumptimer >0{
            physics_apply_impulse(x,y,0,jump_force);
        }
    }
    
        //speed < maxspeed
    phy_speed_x = max(min(phy_speed_x,max_xspeed),-max_xspeed);
        //varialbe Jump height
    if (phy_speed_y <0) && (!key_jump_held) && !place_meeting(x,y,obj_player){
        phy_speed_y = max(phy_speed_y, (phy_speed_y /6 *5));
    }
    if jumptimer > 0 {       //"coyote" jump-timer
        jumptimer -= 1;
    }
    
    //Attempt at fixing Collision (kind of works, but you cant jump if you're standing next to a wall/player)
    if (place_meeting(x,y+1,obj_wall) && !place_meeting(x+1,y,obj_wall)){
        jumptimer = 5;
    }
    -Collision with obj_wall
    Code:
     //comment needed to initiate physics collision
    
    obj_wall is parent to obj_player. Both objects uses physics
    Physics properties for obj_wall: 0s on everything. Solid
    Physics properties for obj_player: Density: 1, Linear Damping: 1, 0s on everything else.
    Physics properties for room0: Gravity y: 70.0
     
  2. OctoMoosePrime

    OctoMoosePrime Member

    Joined:
    Jan 13, 2020
    Posts:
    4
    I think I might have solved my problems.
    (Feels like a ghetto-rig but it works atleast)

    Instead of using the sprite-mask or the physics2dBox to check for collisions I create three collision rectangles below the player.
    I tried with just one first but the collisions were either 1 pixel too small, making jumps inacessable on the very edge of the floor, or 1 pixel too big, enabling jumping while touching walls. (very weird)
    So I decided to make the rectange smaller and add additional rectangles on each side.
    (which let me add more functions aswell)

    So my system is as follows:
    3 collision rectangles 1 pixel below the players physics box.
    If any of the rectangles touch ground and vertical speed = 0 it allows jumping.
    If only one side collides and vertical speed = 0, force is added to push the player away from the ground. (making you slide off if you're too close to the edge.
    If the middle one collides with another player it allows jumping.
    (had to make this separate from ground collision since I want to be able to jump when ontop of a jumping/falling player, so can't check if vspeed = 0 here)
    [​IMG]
    (Blue is only colliding with the side rectangle, so he gets pushed to the left. Both players touch ground, so both are able to jump)
    Code:
    //mid collision-box or side collision-box on ground = jumpreset
    if phy_speed_y = 0 && (collision_rectangle(x-3,y+17,x+3,y+18,obj_wall,true,true) or collision_rectangle(x-8,y+17,x-4,y+18,obj_wall,true,true) or collision_rectangle(x+4,y+17,x+8,y+18,obj_wall,true,true)){
        jumptimer = 5;
    }
    //side collision-boxes on ground = push off
    if phy_speed_y = 0 && !collision_rectangle(x-3,y+17,x+3,y+18,obj_wall,true,true) && collision_rectangle(x-8,y+17,x-4,y+18,obj_wall,true,true){
        phy_speed_x += 0.05;
    }
    if phy_speed_y = 0 && !collision_rectangle(x-3,y+17,x+3,y+18,obj_wall,true,true) && collision_rectangle(x+4,y+17,x+8,y+18,obj_wall,true,true){
        phy_speed_x -= 0.05;
    }
    if collision_rectangle(x,y+14,x,y+16,obj_player,true,true){
        jumptimer = 5;
    }
    
    Is this a good way to do it or could I improve it somehow?

    And if I have other functions I need help with for the same project, do I post them in this thread or a new one?
     
  3. OctoMoosePrime

    OctoMoosePrime Member

    Joined:
    Jan 13, 2020
    Posts:
    4
    Nope, I did not manage to solve it yet.
    This is for an "infinate runner" type of game, so I have made an object that spawns new chunks/rooms as the level progresses.
    I design these chunks using a 32x32 pixel collision object, so I can make gaps and falls easily, as if using a tileset.
    But the 32x32 blocks make my characters stop while transitioning from one block to another sometimes. (as if there is a wall there)
    I thought I could maybe fix it by making the collidable blocks as long as the chunks, but the bug will still happen when transitioning from one chunk to the next, so that wouldn't make a difference.
    Why does this happen?
    (As stated above, I'm using the built in box2d physics on my character and collidables)
     
  4. Jezla

    Jezla Member

    Joined:
    Jun 20, 2016
    Posts:
    434
    This explains why it is happening. Your solution in GM:S is to use a chain shape for your ground. It will probably be more efficient, since you won't have a bunch of physics instances being generated, just one instance for each chain shape.

    As an additional note, your code above suggests that you really need to spend some time doing the basic physics tutorials (they are included with GM:S 1.4) and reading through the physics section of the manual. Two things that you are doing that work against the physics system stick out to me:

    1) To decelerate your player, you need to just set the friction for the player's fixture, rather than decrement the phy_speed_x directly.
    2) To limit your top speed, you need to calculate and clamp the force being applied, rather than clamping phy_speed_x.

    Whenever you manipulate the phy_speed_x and _y directly, you are breaking the simulation, which can have unpredictable and unintended consequences.
     

Share This Page