GameMaker Terraria Style Platforms

B

brogolem35

Guest
Hello, I am trying to make an object works like platforms in Terraria. If you didn't play Terraria it works like this. You can jump (or fly) below them to go top and if you top of them you can press down to go below them. But my collision system does not fit to this.
My collision system does not overshoot and pixel-perfect.
My collision script:

Code:
hrepeat = hsp / 30;
vrepeat = vsp / 46;
hrepeat = abs(hrepeat);
vrepeat = abs(vrepeat);
hmod = hsp % 30;
vmod = vsp % 46;
hmod = abs(hmod);
vmod = abs(vmod);
hrep = 1;
vrep = 1;
hbool = true;
vbool = true;

//Horizantal
if(place_meeting(x,y,oBlock1))
{
    x = round(x);
    while(!place_meeting(x+sign(hsp),y,oBlock1))
    {
        x += sign(hsp);
    }
    hsp = 0;
}
else if(place_meeting(x+hmod*sign(hsp),y,oBlock1))
{
    x = round(x);
    while(!place_meeting(x+sign(hsp),y,oBlock1))
    {
        x += sign(hsp);
    }
    hsp = 0;
}
else
{
while(hrep <= hrepeat)
{
    if(place_meeting(x+((hrep * 30)+hmod)*sign(hsp),y,oBlock1))
    {
        x = round(x);
        while(!place_meeting(x+sign(hsp),y,oBlock1))
        {
            x += sign(hsp);
        }
        hsp = 0;
        hrep = hrepeat + 1;
    }
    else
    {
        hrep += 1;
    }
}
}

//Vertical
if(place_meeting(x,y,oBlock1))
{
    y = round(y);
    while(!place_meeting(x,y+sign(vsp),oBlock1))
    {
        y += sign(vsp);
    }
    vsp = 0;
}
else if(place_meeting(x,y+vmod*sign(vsp),oBlock1))
{
    y = round(y);
    while(!place_meeting(x,y+sign(vsp),oBlock1))
    {
        y += sign(vsp);
    }
    vsp = 0;
}
else
{
while(vrep <= vrepeat)
{
    if(place_meeting(x,y+((vrep * 46)+vmod)*sign(vsp),oBlock1))
    {
        y = round(y);
        while(!place_meeting(x,y+sign(vsp),oBlock1))
        {
            y += sign(vsp);
        }
        vsp = 0;
        vrep = vrepeat + 1;
    }
    else
    {
        vrep += 1;
    }
}
}
I modified the code to fit platforms but it has some issues. When collision checking finds a platform my character teleports itself to the closest block below it.
Modified version:

Code:
var falling;
hrepeat = hsp / 30;
vrepeat = vsp / 46;
hrepeat = abs(hrepeat);
vrepeat = abs(vrepeat);
hmod = hsp % 30;
vmod = vsp % 46;
hmod = abs(hmod);
vmod = abs(vmod);
hrep = 1;
vrep = 1;
hbool = true;
vbool = true;

//Horizantal
if(place_meeting(x,y,oBlock1))
{
    x = round(x);
    while(!place_meeting(x+sign(hsp),y,oBlock1))
    {
        x += sign(hsp);
    }
    hsp = 0;
}
else if(place_meeting(x+hmod*sign(hsp),y,oBlock1))
{
    x = round(x);
    while(!place_meeting(x+sign(hsp),y,oBlock1))
    {
        x += sign(hsp);
    }
    hsp = 0;
}
else
{
while(hrep <= hrepeat)
{
    if(place_meeting(x+((hrep * 30)+hmod)*sign(hsp),y,oBlock1))
    {
        x = round(x);
        while(!place_meeting(x+sign(hsp),y,oBlock1))
        {
            x += sign(hsp);
        }
        hsp = 0;
        hrep = hrepeat + 1;
    }
    else
    {
        hrep += 1;
    }
}
}

//Vertical
if(vsp > 0)
{
    falling = true;
}
else falling = false;
if(place_meeting(x,y,oBlock1) || (falling && !key_down && collision_rectangle(x-15, y+23, x+15, y+23+vsp, oPlatform0, false, true)))
{
    y = round(y);
    while(!place_meeting(x,y+sign(vsp),oBlock1) || (!key_down && collision_rectangle(x-15, y+23, x+15, y+23+1, oPlatform0, false, true)))
    {
        y += sign(vsp);
    }
    vsp = 0;
}
else if(place_meeting(x,y+vmod*sign(vsp),oBlock1))
{
    y = round(y);
    while(!place_meeting(x,y+sign(vsp),oBlock1))
    {
        y += sign(vsp);
    }
    vsp = 0;
}
else
{
while(vrep <= vrepeat)
{
    if(place_meeting(x,y+((vrep * 46)+vmod)*sign(vsp),oBlock1))
    {
        y = round(y);
        while(!place_meeting(x,y+sign(vsp),oBlock1))
        {
            y += sign(vsp);
        }
        vsp = 0;
        vrep = vrepeat + 1;
    }
    else
    {
        vrep += 1;
    }
}
}
 
Top