• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Legacy GM [SOLVED] Endless Runner with Slopes help

B

Becon

Guest
So I requested help on this old project back in the original GM forum and no help but I have come back to it trying new things.

Off and on for a few years I have been trying to make a random generated endless runner using slopes. I can get the slopes to work fine on their own in many different ways. I got the level to randomly generate and sync the slopes and then move them to the left like a runner often does....On it's own.

When you put the two together though, ground moving to the left with a slope coming at the player, upon collision, the ground/solid objects/slopes whatever, they move. If I jump and land on them they shift a little. When they come for the player, instead of the player rising and falling with the slopes, he pushes those objects like a bulldozer across the screen stacking them on top of each other.

I'm not going to post the original code here because I forgot how most of that giant bunch of code works atm but recently editing
Strawbry_jam's Part 2 code from https://forum.yoyogames.com/index.php?threads/generic-platformer.1090/
Found here: https://drive.google.com/file/d/0B-XGa2C_e2NSNTd5cjZ6aFp3RTQ/view?usp=sharing

I was able to do get it to do what mine does, granted I just made the controls move the ground instead of the player.

obj_player
Step:
Code:
///standard platform movement


//area list to get accurate on ground readings and stuff
var colList = area_get_collision_list(obj_wall);

//update jumpThru state
update_solid(colList,270,keyboard_check(vk_down));

//check if on ground
if( place_free( x, y+1 )){
    gravity = 0.8; //set gravity - we are in the air!
} else {
    gravity = 0; //no need for gravity on ground

    //we are on ground so we can check if we need to jump
    if( keyboard_check_pressed( vk_up )){
        vspeed = -12;
    }
}


//reset jumpThru states
reset_solid(colList);

//clean up
ds_list_destroy(colList);
End Step:
Code:
///Collision Correction


//Moving into a solid puts us back as if we never moved.
//This part allows us to move on slopes and fill the gaps.

//First check if we need to correct for collision
if( speed != 0 and x == xprevious and y == yprevious ){
    
    //get a list of all possible wall objects to collide with
    var colList = move_get_collision_list(obj_wall);

    //move up first if vspeed is up
    if( vspeed < 0 ){
        //update jumpThru state
        update_solid(colList,90,keyboard_check(vk_down));
        move_contact_solid( 90, -vspeed );
    }
    
    //move over if hspeed is not 0
    if( hspeed != 0 ){
        //setting some temporary vars
        var temp_y = y;
        //update jumpThru state
        update_solid(colList,90,keyboard_check(vk_down));
        //move up
        move_contact_solid( 90, abs( hspeed ));

        update_solid(colList,90 - sign( hspeed ) * 90,keyboard_check(vk_down));
        //move over
        move_contact_solid( 90 - sign( hspeed ) * 90, abs( hspeed ));

        update_solid(colList,270,keyboard_check(vk_down));
        //move down what we moved up
        if(temp_y-y != 0){
            move_contact_solid( 270, temp_y-y);
        }
        //move down again if it puts us on ground
        if( !place_free( x, y + abs( hspeed ) + 1 )){
            move_contact_solid( 270, abs( hspeed ));
        }
    }
    //move down if vspeed is down
    if( vspeed > 0 ){
        update_solid(colList,270,keyboard_check(vk_down));
        move_contact_solid( 270, vspeed );
    }
    //if we are blocked then set vspeed to 0
    update_solid(colList,180+90*sign(vspeed),keyboard_check(vk_down));
    if( !place_free( x, y + sign( vspeed ))){
        vspeed = 0;
    }
    //set hspeed to 0 if we can't move horizontally (we're blocked)
    if( hspeed != 0 and x == xprevious ){
        hspeed = 0;
    }
    
    //reset jumpThru states
    reset_solid(colList);
    
    //clean up
    ds_list_destroy(colList);
}
Then I added a step even in the slopes and ground so I could force the ground to move with the L and R arrow keys instead of the player. FYI Up arrow makes player jump still so you can see that crash as well.
Step:
Code:
hkey = keyboard_check( vk_right ) - keyboard_check( vk_left );


//set horizontal movement based on controls
if( hkey == 0 ){
    hspeed *= 0.75; //friction
    if( abs( hspeed ) < 0.5 ){ hspeed = 0; }
} else {
    hspeed *= 0.75;
    hspeed += 2 * sign( hkey );
}
Any help would be greatly appreciated. Not being able to figure this one out is why I keep stepping away from GameMaker.
 

jo-thijs

Member
So I requested help on this old project back in the original GM forum and no help but I have come back to it trying new things.

Off and on for a few years I have been trying to make a random generated endless runner using slopes. I can get the slopes to work fine on their own in many different ways. I got the level to randomly generate and sync the slopes and then move them to the left like a runner often does....On it's own.

When you put the two together though, ground moving to the left with a slope coming at the player, upon collision, the ground/solid objects/slopes whatever, they move. If I jump and land on them they shift a little. When they come for the player, instead of the player rising and falling with the slopes, he pushes those objects like a bulldozer across the screen stacking them on top of each other.

I'm not going to post the original code here because I forgot how most of that giant bunch of code works atm but recently editing
Strawbry_jam's Part 2 code from https://forum.yoyogames.com/index.php?threads/generic-platformer.1090/
Found here: https://drive.google.com/file/d/0B-XGa2C_e2NSNTd5cjZ6aFp3RTQ/view?usp=sharing

I was able to do get it to do what mine does, granted I just made the controls move the ground instead of the player.


obj_player
Step:
Code:
///standard platform movement


//area list to get accurate on ground readings and stuff
var colList = area_get_collision_list(obj_wall);

//update jumpThru state
update_solid(colList,270,keyboard_check(vk_down));

//check if on ground
if( place_free( x, y+1 )){
    gravity = 0.8; //set gravity - we are in the air!
} else {
    gravity = 0; //no need for gravity on ground

    //we are on ground so we can check if we need to jump
    if( keyboard_check_pressed( vk_up )){
        vspeed = -12;
    }
}


//reset jumpThru states
reset_solid(colList);

//clean up
ds_list_destroy(colList);
End Step:
Code:
///Collision Correction


//Moving into a solid puts us back as if we never moved.
//This part allows us to move on slopes and fill the gaps.

//First check if we need to correct for collision
if( speed != 0 and x == xprevious and y == yprevious ){
   
    //get a list of all possible wall objects to collide with
    var colList = move_get_collision_list(obj_wall);

    //move up first if vspeed is up
    if( vspeed < 0 ){
        //update jumpThru state
        update_solid(colList,90,keyboard_check(vk_down));
        move_contact_solid( 90, -vspeed );
    }
   
    //move over if hspeed is not 0
    if( hspeed != 0 ){
        //setting some temporary vars
        var temp_y = y;
        //update jumpThru state
        update_solid(colList,90,keyboard_check(vk_down));
        //move up
        move_contact_solid( 90, abs( hspeed ));

        update_solid(colList,90 - sign( hspeed ) * 90,keyboard_check(vk_down));
        //move over
        move_contact_solid( 90 - sign( hspeed ) * 90, abs( hspeed ));

        update_solid(colList,270,keyboard_check(vk_down));
        //move down what we moved up
        if(temp_y-y != 0){
            move_contact_solid( 270, temp_y-y);
        }
        //move down again if it puts us on ground
        if( !place_free( x, y + abs( hspeed ) + 1 )){
            move_contact_solid( 270, abs( hspeed ));
        }
    }
    //move down if vspeed is down
    if( vspeed > 0 ){
        update_solid(colList,270,keyboard_check(vk_down));
        move_contact_solid( 270, vspeed );
    }
    //if we are blocked then set vspeed to 0
    update_solid(colList,180+90*sign(vspeed),keyboard_check(vk_down));
    if( !place_free( x, y + sign( vspeed ))){
        vspeed = 0;
    }
    //set hspeed to 0 if we can't move horizontally (we're blocked)
    if( hspeed != 0 and x == xprevious ){
        hspeed = 0;
    }
   
    //reset jumpThru states
    reset_solid(colList);
   
    //clean up
    ds_list_destroy(colList);
}
Then I added a step even in the slopes and ground so I could force the ground to move with the L and R arrow keys instead of the player. FYI Up arrow makes player jump still so you can see that crash as well.
Step:
Code:
hkey = keyboard_check( vk_right ) - keyboard_check( vk_left );


//set horizontal movement based on controls
if( hkey == 0 ){
    hspeed *= 0.75; //friction
    if( abs( hspeed ) < 0.5 ){ hspeed = 0; }
} else {
    hspeed *= 0.75;
    hspeed += 2 * sign( hkey );
}
Any help would be greatly appreciated. Not being able to figure this one out is why I keep stepping away from GameMaker.
Reading the first part of your issue, my first thought was "he's probably using solid objects".
The code you then provided seems to confirm this suspicion.
Basically, you should never use solid objects in GameMaker, as they always end up causing these kind of bugs.
Using functions such as move_contact is also a bad idea.
In your case, using GameMaker's built-in speed system (hspeed and vspeed) also seems like a bad idea.
Using your own speed variables provides you with much more control over what happens.

Basically, what you should do, is to just create your own collision system.
The with-structures and place_meeting/instance_place functions can help with this.
 
B

Becon

Guest
Thanks for the reply @jo-thijs . I'll try something without solids and move_contact and see where it gets me although I have a feeling I'll be back. =o)~
 
B

Becon

Guest
OK. Again I got some strangeness going on. Let me toss some code here first:
obj_char
CREATE
Code:
contactGround = instance_place(x,y, obj_block)
jumping = false
STEP
Code:
///Movement

if contactGround = noone
    {
    vspeed = 0
    }
//Gravity
if place_meeting (x,y+1,obj_block) or place_meeting (x,y-1,obj_slope)
    {
    gravity = 0
    }
else
    {
    gravity = 3.3 gravity_direction = 270
    }
//Jumping
if keyboard_check (vk_up)
    {
    jumping = true
    y -= 15
    }
else
    {
    jumping = false
    }
//Movement
if keyboard_check (vk_left)
    {
    x -= 6
    }      
if keyboard_check (vk_right)
    {
    x += 6
    }
if keyboard_check (vk_right) && place_meeting (x+1,y+1, obj_slope)
    {
    y -= 6
    }      
if keyboard_check (vk_left) && place_meeting (x-1,y-1, obj_slope)
    {
    y -= 6
    }
So I can move left and right on the surfaces now. I don't fall through. I can even go up and down the slopes both ways.
If I jump....sometimes my character lands about 3 pixels in the obj_block. Sometimes it lands right on top. This is WAY worse if I increase gravity, which sucks because this gravity is so low that I float down and over the slopes instead of actually "walk" down, but if I turn the gravity up and jump, when I land I can end up half way in the obj_block or more.

To add to that, when I get to the top of the slope the obj_char bounces a bit like he hit a stone at the top. Both obj's are 32x32 and line up just fine, but the transfer from one to the other appears to have some disorder.

And why the hell does line 3 have to be a variable? I tried just:
Code:
if instance_place(x,y, obj_block) = noone
and the player fell through the floor, but if I use the variable saying the exact same thing it works?

I figure I should get this part fixed before I start making it so the ground is actually moving instead of the player.

How am I doing so far???
Any additional help would totally be welcome. What am I doing right? What am I doing wrong?

Thanks in advance.
 

jo-thijs

Member
OK. Again I got some strangeness going on. Let me toss some code here first:
obj_char
CREATE
Code:
contactGround = instance_place(x,y, obj_block)
jumping = false
STEP
Code:
///Movement

if contactGround = noone
    {
    vspeed = 0
    }
//Gravity
if place_meeting (x,y+1,obj_block) or place_meeting (x,y-1,obj_slope)
    {
    gravity = 0
    }
else
    {
    gravity = 3.3 gravity_direction = 270
    }
//Jumping
if keyboard_check (vk_up)
    {
    jumping = true
    y -= 15
    }
else
    {
    jumping = false
    }
//Movement
if keyboard_check (vk_left)
    {
    x -= 6
    }     
if keyboard_check (vk_right)
    {
    x += 6
    }
if keyboard_check (vk_right) && place_meeting (x+1,y+1, obj_slope)
    {
    y -= 6
    }     
if keyboard_check (vk_left) && place_meeting (x-1,y-1, obj_slope)
    {
    y -= 6
    }
So I can move left and right on the surfaces now. I don't fall through. I can even go up and down the slopes both ways.
If I jump....sometimes my character lands about 3 pixels in the obj_block. Sometimes it lands right on top. This is WAY worse if I increase gravity, which sucks because this gravity is so low that I float down and over the slopes instead of actually "walk" down, but if I turn the gravity up and jump, when I land I can end up half way in the obj_block or more.

To add to that, when I get to the top of the slope the obj_char bounces a bit like he hit a stone at the top. Both obj's are 32x32 and line up just fine, but the transfer from one to the other appears to have some disorder.

And why the hell does line 3 have to be a variable? I tried just:
Code:
if instance_place(x,y, obj_block) = noone
and the player fell through the floor, but if I use the variable saying the exact same thing it works?

I figure I should get this part fixed before I start making it so the ground is actually moving instead of the player.

How am I doing so far???
Any additional help would totally be welcome. What am I doing right? What am I doing wrong?

Thanks in advance.
I still think you should not be using hspeed, vspeed, gravity and gravity_direction in this project.

It doesn't make sense that contactGrounds needs to be a variable.
However, it also doesn't make sense to reset vspeed to 0 when contactGround is noone,
as that means you stop falling as long as you're not inside a block, but keep falling as long as you're inside a block.

Is your game tile based?
How do you want slope collision to work?
Should the player be prevented to overlap slopes at all,
or should the bottom center of the player be kept on top of the slopes,
allowing a part of the player to overlap the slopes.
 
B

Becon

Guest
Forgot about that vspeed. I revamped it with the help of a ShaunJS tutorial. Then, I rewired it so that jumping affects only the obj_player and left and right movement only affect the obj_block/ground and obj_slope. I threw in an obj_solid and made it the parent to the block and slope. No code in there.
Also I know some of the code is redundant as I copied/pasted it into each of the object, I just haven't gotten a chance to clean it up yet fully.
OBJ_PLAYER
Create
Code:
grav = 1
hsp = 0
vsp = 0
jumpSpeed = 17
moveSpeed = 10
yplus = 0
Steps
Code:
//Player Inputs
key_jump = keyboard_check_pressed (vk_up)

//Movement

//Gravity
if (vsp < 10)
    {
    vsp += grav
    }
//Jump
if (place_meeting(x,y+1,obj_solid))
    {
    vsp = key_jump * -jumpSpeed
    }
 
//Vertical Collision
if (place_meeting(x,y+vsp,obj_solid))
    {
    while (!place_meeting(x,y+sign(vsp),obj_solid))
        {
        y += sign(vsp)
        }
        vsp = 0
    }
y += vsp
OBJ_BLOCK
Create
Code:
hsp = 0
vsp = 0
moveSpeed = 10
Steps
Code:
//Player Inputs
key_right = keyboard_check (vk_left)
key_left = -keyboard_check (vk_right)

//Movement

//Left - Right
move = key_left + key_right
hsp = move * moveSpeed

//Horizontal Collision
if (place_meeting(x+hsp,y,obj_player))
    {
    yplus = 0
    while (place_meeting(x+hsp,y-yplus,obj_player) && yplus <= abs(1*hsp))
        {
        yplus += 1
        }
    if place_meeting(x,y-yplus,obj_player)
        {    
    while (!place_meeting(x+sign(hsp),y,obj_player))
        {
        obj_player.x += sign(hsp)
        }
        obj_player.hsp = 0
        }
        else
        {
        obj_player.y -= yplus
        }
    }
x += hsp
OBJ_SLOPE
Create
Code:
hsp = 0
vsp = 0
moveSpeed = 10
Steps
Code:
//Player Inputs
key_right = keyboard_check (vk_left)
key_left = -keyboard_check (vk_right)

//Movement

//Left - Right
move = key_left + key_right
hsp = move * moveSpeed

//Horizontal Collision
if (place_meeting(x+hsp,y,obj_player))
    {
    yplus = 0
    while (place_meeting(x+hsp,y-yplus,obj_player) && yplus <= abs(1*hsp))
        {
        yplus += 1
        }
    if place_meeting(x,y-yplus,obj_player)
        {
        while (!place_meeting(x+sign(hsp),y,obj_player))
            {
            obj_player.x += sign(hsp)
            }
        }
    }
x += hsp
So, the player does seam to go over the objects when I'm moving to the right. It is SO Glitchy though. I know there is something wrong with this thing. When going over the slopes I actually go inside the slope and go over everything. I can't figure this thing out. I DID stop the block stacking that occurred when the player crashed into the slope and bulldozed through it pushing all the ground in it's path. (That thing that happened when I used all the bad things like Solid objects, hspeed,vspeed etc.) It DID happen with this too...but I got that out of there at least. I can still walk through the blocks if they are made into walls instead having them stop the player though. I can walk and jump on them fine. I assume that's just something when if block contacts player hsp=0. I'm really tired. =o)~

How is your day??
 
Last edited by a moderator:
B

Becon

Guest
K. Think I got it.

obj_player

Create

Code:
//Initialize Variables
grav = 1
vsp = 0
jumpSpeed = 17
Steps

Code:
///Movement
key_jump = keyboard_check_pressed (vk_up)
//Gravity
if (vsp < 10) vsp += grav
//Jump
if (place_meeting(x,y+1,obj_solid))
    {
    vsp = key_jump * -jumpSpeed
    }
//Vertical Collision
if (place_meeting(x,y+vsp,obj_solid))
    {
    while (!place_meeting(x,y+sign(vsp),obj_solid))
        {
        y += sign(vsp)
        }
        vsp = 0
    } 
y += vsp

obj_block


Create

Code:
hsp = 0
vsp = 0
moveSpeed = 10

Step

Code:
//Player Inputs
key_right = keyboard_check (vk_left)
key_left = -keyboard_check (vk_right)
//Movement
//Left - Right
move = key_left + key_right
hsp = move * moveSpeed

//Horizontal Collision
if (place_meeting(x+hsp,y,obj_player))
    {
    yplus = 0
    while (place_meeting(x+hsp,y-yplus,obj_player) && yplus <= abs(1*hsp))
        {
        yplus += 1
        }
    if place_meeting(x,y-yplus,obj_player)
        {       
    while (!place_meeting(x+sign(hsp),y,obj_player))
        {
        obj_player.x += sign(hsp)
        }
        obj_player.hsp = 0
        }
        else
        {
        obj_player.y -= yplus
        }
    } 
x += hsp
obj_slope

Create
Code:
hsp = 0
vsp = 0
moveSpeed = 10
Step

Code:
//Player Inputs
key_right = keyboard_check (vk_left)
key_left = -keyboard_check (vk_right)

//Movement

//Left - Right
move = key_left + key_right
hsp = move * moveSpeed

//Horizontal Collision
if (place_meeting(x+hsp,y,obj_player))
    {
    yplus = 0
    while (place_meeting(x+hsp,y-yplus,obj_player) && yplus <= abs(1*hsp))
        {
        yplus += 1
        }
    if place_meeting(x,y+yplus,obj_player)
        {       
        while (!place_meeting(x+sign(hsp),y,obj_player))
            {
            x += sign(hsp)
            }
        hsp = 0
        }
        else
        {
        obj_player.y -= yplus
        }
    } 
x += hsp

obj_solid

Children are:

obj_bloc

obj_slope
 
Top