1. Hey! Guest! The 32nd GMC Jam will take place between Feb 22nd, 12:00 UTC (Friday noon) and Feb 25th, 12:00 UTC (Monday noon). Why not join in! Click here to find out more!
    Dismiss Notice

GML HELP - ds_grid collision slopes problem

Discussion in 'Programming' started by NeZvers, Feb 14, 2019 at 8:02 AM.

  1. NeZvers

    NeZvers Member

    Joined:
    Mar 24, 2018
    Posts:
    217
    As a material for tutorials I wanted to give a challenge for myself and make platformer with bitwise calculation (no floats) and ds_grid. I want to avoid from any loop and achieve it only with if. Regular block collision work like charm, but I wanted to push it further with slopes and moving with the sprite middle on slopes. There's bool for block/ slope collision systems.
    Blocks collision work and is decoupled with if(!useSlopes).
    1) its ds_grid collision and slopes have height map calculation script that return value of pixel above the slope.
    2) if grounded, player should slide on slopes (kinda works but glitchy)
    3) suspects - slope_slide(), ground_check(), collide_verticaly() (originates in set_position())
    I revorked slope section from the ground several times and can't find what's the problem.
    PROJECT Its (1.4) organized bare bone project and written clean with some comments. I think it's best to see it in project.
    Code:
    TILE_SIZE = 16;
    TILE_ROUND = TILE_SIZE -1;
    TILE_SHIFT = 4;
    
    Code:
    h_move(); //Basic hspd setting
    
    collide_horizontaly();
    
    ///Room clamp
    if(x+hitbox_l < 0){
        x = -hitbox_l;
    }
    if(x+hitbox_r > room_width){
        x = room_width -hitbox_r;
    }
    
    ground_check(); //set grounded
    
    v_move();
    
    collide_vertically();
     
    
    Code:
    var hsp = argument0;
    
    if(grounded) //Slide up and down the slopes and block tiles
    {
        var tileFeet  = gridCollision[# x+hitbox_hc+hsp >> TILE_SHIFT, y+hitbox_d   >> TILE_SHIFT];
        var tileBelow = gridCollision[# x+hitbox_hc+hsp >> TILE_SHIFT, y+hitbox_d+hsp >> TILE_SHIFT];
        if(tileFeet != 0){ y = tile_height(x+hitbox_hc+hsp, y+hitbox_d, tileFeet);}
        else if (tileBelow != 0){y = tile_height(x+hitbox_hc+hsp, y+hitbox_d+hsp, tileBelow);}
        else if (tileFeet == 0){
            tileFeet = gridCollision[# x+hitbox_hc+hsp >> TILE_SHIFT, (y+hitbox_d >> TILE_SHIFT)+1];
            if(tileFeet!=0){y = tile_height(x+hitbox_hc+hsp, y+hitbox_d+TILE_SIZE, tileFeet);}
        }
    }
    Code:
    grounded = false;
    
    if(!useSlopes) // Block collision
    {
        var L = gridCollision[# (x+hitbox_l)>>TILE_SHIFT,  (y+hitbox_d+1)>>TILE_SHIFT] == 1;
        var M = gridCollision[# (x+hitbox_hc)>>TILE_SHIFT, (y+hitbox_d+1)>>TILE_SHIFT] == 1;
        var R = gridCollision[# (x+hitbox_r)>>TILE_SHIFT,  (y+hitbox_d+1)>>TILE_SHIFT] == 1;
        if(L || M || R)
        {
            grounded = true;
        }
    }
    else //Slope collision
    {
        //Center
        var C = gridCollision[# x+hitbox_hc >> TILE_SHIFT, y+hitbox_d >> TILE_SHIFT];
        if(C!=0){
            var h = tile_height(x+hitbox_hc, y+hitbox_d, C);
            if(y == h){grounded = true;}
        }
        else
        {
            C = gridCollision[# x+hitbox_hc >> TILE_SHIFT, y+hitbox_d+1 >> TILE_SHIFT];
            if(C!=0)
            {
                var h = tile_height(x+hitbox_hc, y+hitbox_d+1, C);
                if(y == h){grounded = true;}
            }
        }
     
        //Right
        if(!grounded)
        {
            var R = gridCollision[# x+hitbox_r >> TILE_SHIFT, y+hitbox_d >> TILE_SHIFT];
            if(R!=0)
            {
                h = tile_height(x+hitbox_r, y+hitbox_d, R);
                if(y == h){grounded = true;}
            }
            else
            {
                R = gridCollision[# x+hitbox_r >> TILE_SHIFT, y+hitbox_d+1 >> TILE_SHIFT];
                if(R!=0)
                {
                    h = tile_height(x+hitbox_r, y+hitbox_d+1, R);
                    if(y == h){grounded = true;}
                }
            }
        }
        //Left
        if(!grounded)
        {
            var L = gridCollision[# x+hitbox_l >> TILE_SHIFT, y+hitbox_d >> TILE_SHIFT];
            if(L!=0)
            {
                h = tile_height(x+hitbox_l, y+hitbox_d, L);
                if(y == h){grounded = true;}
            }
            else
            {
                L = gridCollision[# x+hitbox_l >> TILE_SHIFT, y+hitbox_d+1 >> TILE_SHIFT];
                if(L!=0)
                {
                    h = tile_height(x+hitbox_l, y+hitbox_d+1, L);
                    if(y == h){grounded = true;}
                }
            }
        }
    }
    
    
    Code:
    var vsp = (vspd[0] >> 8); //speeds are 256 times higher since can't use floats with bitwise
    
    if(!useSlopes) //NO SLOPES
    {
        vertical_wall(vsp); // for easier reading decoupled in script (see in project)
    }
    else // SLOPES
    {
        if (vsp>0)
        {
            //Center
            //Feet: in case inside slope tile potentialy could fall through
            var C = gridCollision[# x+hitbox_hc >> TILE_SHIFT, y+hitbox_d >> TILE_SHIFT];
            if(C!=0)
            {
                var h = tile_height(x+hitbox_hc, y+hitbox_d, C);
                if(y+hitbox_d+vsp >= h)
                {
                    y = h;
                    grounded = true;
                }
            }
        
            if(!grounded)
            {
                var Cs = gridCollision[# x+hitbox_hc >> TILE_SHIFT, y+hitbox_d+vsp >> TILE_SHIFT];
                if(Cs!=0)
                {
                    var h = tile_height(x+hitbox_hc, y+hitbox_d+vsp, Cs);
                    if(y+hitbox_d+vsp >= h)
                    {
                        y = h;
                        grounded = true;
                    }
                }
            }
            //!!!!!!!!!!!!! MAYBE THERE'S A PROBBLEM BELOW
            if(!grounded)
            {
                C = gridCollision[# x+hitbox_hc >> TILE_SHIFT, y+hitbox_d+hitbox_half+vsp >> TILE_SHIFT];
            }
            if(C!=0)
            {
                //Left corner
                if(!grounded){
                    var L = gridCollision[# x+hitbox_l >> TILE_SHIFT, y+hitbox_d >> TILE_SHIFT];
                    if(L!=0){
                        var h = tile_height(x+hitbox_l, y+hitbox_d, L);
                        if(y+hitbox_d+vsp >= h)
                        {
                            y = h;
                            grounded = true;
                        }
                    }
                }
                if(!grounded){
                    var L = gridCollision[# x+hitbox_l >> TILE_SHIFT, y+hitbox_d+vsp >> TILE_SHIFT];
                    if(L!=0){
                        var h = tile_height(x+hitbox_l, y+hitbox_d+vsp, L);
                        if(y+hitbox_d+vsp >= h)
                        {
                            y = h;
                            grounded = true;
                        }
                    }
                }
            
                //Right corner
                if(!grounded){
                    var R = gridCollision[# x+hitbox_r >> TILE_SHIFT, y+hitbox_d >> TILE_SHIFT];
                    if(R!=0){
                        var h = tile_height(x+hitbox_r, y+hitbox_d, R);
                        if(y+hitbox_d+vsp >= h)
                        {
                            y = h;
                            grounded = true;
                        }
                    }
                }
                if(!grounded){
                    var R = gridCollision[# x+hitbox_r >> TILE_SHIFT, y+hitbox_d+vsp >> TILE_SHIFT];
                    if(R!=0){
                        var h = tile_height(x+hitbox_r, y+hitbox_d+vsp, R);
                        if(y+hitbox_d+vsp >= h)
                        {
                            y = h;
                            grounded = true;
                        }
                    }
                }
            }
        }
        if (vsp<0)
        {
            var L = gridCollision[# (x+hitbox_l)>>TILE_SHIFT,  (y+hitbox_u+vsp)>>TILE_SHIFT] == 1;
            var M = gridCollision[# (x+hitbox_hc)>>TILE_SHIFT, (y+hitbox_u+vsp)>>TILE_SHIFT] == 1;
            var R = gridCollision[# (x+hitbox_r)>>TILE_SHIFT,  (y+hitbox_u+vsp)>>TILE_SHIFT] == 1;
            if(L || M || R)
            {
                y = ((y+hitbox_u+vsp) & ~TILE_ROUND) +TILE_SIZE -hitbox_u;
                grounded = true;
            }
        }
    }
    
    if(grounded)
    {
        vspd[0] = 0;
        vspd[1] = 0;
        vspd[2] = 0;
    }
    else
    {
        y+=vsp;
    }
    
    Code:
    ///tile_height(x, y, tile_index)
    
    var xx = argument[0];
    var yy = argument[1];
    var tile = argument[2];
    
    switch (tile){
        case 1: // Block
            yy = (yy & ~TILE_ROUND) -1;
            break;
        case 2: // Right 45 degree slope
            yy = (yy & ~TILE_ROUND) -1 + TILE_SIZE - (xx & TILE_ROUND);
            //yy = ((yy div TILE_SIZE) * TILR_SIZE) + TILE_SIZE - (xx mod TILE_SIZE);
            break;
        case 3: // Left 45 degree slope
            yy = (yy & ~TILE_ROUND) -1 + (xx & TILE_ROUND);
            break;
        case 4: // Right 22.5 degree 1st half
            yy = (yy & ~TILE_ROUND) -1 + TILE_SIZE - ((xx & TILE_ROUND)>>1);
            break;
        case 5: // Right 22.5 degree 2nd half
            yy = (yy & ~TILE_ROUND) -1 + TILE_SIZE - ((xx & TILE_ROUND)>>1) - (TILE_SIZE >> 1);
            break;
        case 6: // Left 22.5 degree 1st half
            yy = (yy & ~TILE_ROUND) -1 + ((x & TILE_ROUND)>>1);
            break;
        case 7: // Left 22.5 degree 2nd half
            yy = (yy & ~TILE_ROUND) -1 + ((x & TILE_ROUND)>>1) - (TILE_SIZE >> 1);
            break;
        default:
            show_debug_message(string("wrong tile argument"));
            break;
    }
    return yy;
    
     
    Last edited: Feb 15, 2019 at 4:44 PM
  2. NeZvers

    NeZvers Member

    Joined:
    Mar 24, 2018
    Posts:
    217
    Why no one is replying?
     
  3. TheSly

    TheSly Member

    Joined:
    Jan 16, 2017
    Posts:
    671
    Most likely because what you are asking takes up peoples time, and quite a lot considering the detailed content in your post they need to go through. This community is based on the good nature of people giving their time freely to help others. What you are asking is quite advanced and requires a large investment of someone's time. You may never get a response, or if someone feels generous they will give up a part of their day and try to assist.

    It's presumptuous to assume every question will always get a response.
     
    Last edited: Feb 16, 2019 at 12:44 AM
    Bayesian likes this.
  4. NeZvers

    NeZvers Member

    Joined:
    Mar 24, 2018
    Posts:
    217
    @TheSly That is exactly the reason it’s bare bone project and I made it as easy readable as possible. Irrelevant stuff to question is decoupled with script and there’s comments on relevant code to understand my idea. It’s a material for tutorial and I hanged up on slopes.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice