GML Player stuck in jump sprite (Platformer)

A

Agletsio

Guest
Trying to add jump animation to Player. My approach at the moment is to say that whenever the Player is not touching the floor(obj_wall), play the jump sprite (basically whenever the character is in mid-air) and vice versa.

Below is my current code setup (only the //Sprite Control section in Player step event, let me know if you want to see full code). With this code, the player just stays in jump sprite (when the game starts, he falls he a bit before touching ground). So controls and everything working normally except for playing the right sprite.

Am i approaching this in the wrong way? Any help or guidance will be appreciated!


//Sprite Control

if !place_meeting(x,y,obj_wall) {
sprite_index = Player_jump
}



else



if !place_meeting(x,y,obj_wall) {

if keyboard_check (vk_left)
{
sprite_index = walk_left;
}

if keyboard_check (vk_right)
{
sprite_index = walk_right;
}

if !keyboard_check (vk_left) && !keyboard_check (vk_right)
{
if sprite_index == walk_right sprite_index = idle_right;
else if sprite_index == walk_left sprite_index = idle_left;
}
}
 

matharoo

Tutorial Guy
YYG Staff
In your second condition (after the else), you are checking the same condition that would've returned false in the first place. You're checking for the jump state.
Code:
!place_meeting(x, y, obj_wall)
You would need to remove the !

EDIT: Follow the next post as well
 

Gillen82

Member
In the first part of the code, add a +1 after the y coordinate. That way, the character is checking one pixel below to see if the obj_wall is there. If it's not, he would be in the jump state, but if there is, the player will be on the ground. Hope this makes sense...and helps.

Code:
if !place_meeting(x,y+1,obj_wall) {
sprite_index = Player_jump
}
Just noticing what @matharoo has said. This is also true. Remove the ! from the line of code mentioned.
 
A

Agletsio

Guest
Hye @Gillen82 and @matharoo ,

Omg what an idiot haha, the "!" was originally removed. Don't know how it got back in there.
So code looks like this now (below). Omitted the first "!". And added the "+1" to y, I think this is good practice.

So now it's still staying in jump state, even when it touches obj_wall. It's only when Player is touching obj_wall and then press left or right, that it start playing walk sprites. So if I jump and land (without pressing movement keys), stays in jump state. This is confusing, I mean the second argument (for "place_meeting) should read true as soon as he lands, right?



//Sprite Control

if !place_meeting(x,y+1,obj_wall) {
sprite_index = Player_jump
}



else



if place_meeting(x,y+1,obj_wall) {

if keyboard_check (vk_left)
{
sprite_index = walk_left;

}

if keyboard_check (vk_right)
{
sprite_index = walk_right;

}

if !keyboard_check (vk_left) && !keyboard_check (vk_right)
{
if sprite_index == walk_right sprite_index = idle_right;
else if sprite_index == walk_left sprite_index = idle_left;

}

}
 

matharoo

Tutorial Guy
YYG Staff
Let's examine your code.
After else, you check for left and right keys. When you aren't pressing them, they aren't turning to true.
After that you're checking if the left and right keys are not pressed. Okay, that does turn to true, but inside that it checks if the sprite is either walk_left or walk_right and THEN change the sprite to idle. So when the sprite is player_jump, nothing will happen.

 

Gillen82

Member
Try this:

Code:
if !place_meeting(x,y+1,obj_wall) {
sprite_index = Player_jump
}else {
    if ( image_angle == 0 ) {
        sprite_index = idle_right;
    }

    if ( image_angle == 180 ) {
        sprite_index = idle_left;
    }
}

if keyboard_check (vk_left)
{
sprite_index = walk_left;

}

if keyboard_check (vk_right)
{
sprite_index = walk_right;

}

if !keyboard_check (vk_left) && !keyboard_check (vk_right)
{
if sprite_index == walk_right sprite_index = idle_right;
else if sprite_index == walk_left sprite_index = idle_left;
}
 

matharoo

Tutorial Guy
YYG Staff
Try this:

Code:
if !place_meeting(x,y+1,obj_wall) {
sprite_index = Player_jump
}else {
    if ( image_angle == 0 ) {
        sprite_index = idle_right;
    }

    if ( image_angle == 180 ) {
        sprite_index = idle_left;
    }
}

if keyboard_check (vk_left)
{
sprite_index = walk_left;

}

if keyboard_check (vk_right)
{
sprite_index = walk_right;

}

if !keyboard_check (vk_left) && !keyboard_check (vk_right)
{
if sprite_index == walk_right sprite_index = idle_right;
else if sprite_index == walk_left sprite_index = idle_left;
}
Why would the OP be using image_angle in a platformer? I think it would be direction, or image_xscale, depending on how they programmed the player.
 

Gillen82

Member
Why would the OP be using image_angle in a platformer? I think it would be direction, or image_xscale, depending on how they programmed the player.
Yeah. Sorry. You're right. Maybe I should have asked if image_xscale was being used to turn the player
 
A

Agletsio

Guest
@matharoo :

Ok so what you're saying is that there is no condition that states what should happen when the Player is in "Player_jump" state? As in it doesn't know what to do when going from "Player_jump" to touching obj_wall, unless "walk_right" or "walk_left" is involved?


@Gillen82:
I'm not sure how your approach works. I'm not familiar with "image_angle" or "image_xscale" and haven't used them in my code.. know the "direction" function but not using it in this code, think the "vsp" and "hsp" variables in my create event makes them absolute??

I have tried it though and it does manage to call the idle sprites when landing.. but now the walking sprites are played when pressing arrow keys in mid-air, which was what I was trying to avoid by only making them playable when in contact with obj_wall haha
 
A

Agletsio

Guest
Ok so what I've managed to do now is tell it where to go from "Player_jump" (in last argument) and it works...kind of. Where it gets tricky for me is that I can only define one sprite as the result, as in:

else if sprite_index == Player_jump sprite_index = idle_right; (am i able to say it should choose between left and right depending on the direction it last faced?).

Code:
//Sprite Control

if !place_meeting(x,y+1,obj_wall) {
sprite_index = Player_jump
}



else



if place_meeting(x,y+1,obj_wall) {

if keyboard_check (vk_left)
{
   sprite_index = walk_left;

    
}



if keyboard_check (vk_right)
{
   sprite_index = walk_right;
  
}


if !keyboard_check (vk_left) && !keyboard_check (vk_right)
{
   if sprite_index == walk_right sprite_index = idle_right;
   else if sprite_index == walk_left sprite_index = idle_left;
   else if sprite_index == Player_jump sprite_index = idle_right;
  
      
}



}
 

Gillen82

Member
Think I might have solved your problem...finally!!

Have a look at the quick system I have. Letters on sprite indicate the different sprites used e.g. il = idle_right, j = jump etc.

http://bit.ly/2kuQ6FG

If you want, I'll create a link to the project file and you can have a look at the code. It' slightly different to what you already have (but not too different). I just have the movement separate from the sprite control. More coding involved, but quite easy to understand.
 
A

Agletsio

Guest
Think I might have solved your problem...finally!!

Have a look at the quick system I have. Letters on sprite indicate the different sprites used e.g. il = idle_right, j = jump etc.

http://bit.ly/2kuQ6FG

If you want, I'll create a link to the project file and you can have a look at the code. It' slightly different to what you already have (but not too different). I just have the movement separate from the sprite control. More coding involved, but quite easy to understand.
Ahh yes, this looks exactly like what i want! If you could link me the project that would be great! Would love to have a look at the code!

Also, thanks for all the effort! You've seriously been a massive help!
 

Gillen82

Member
Here's the code I used. Hopefully it makes a bit of sense.

CREATE EVENT

Code:
///Init Player

hspd = 0;
vspd = 0;
mspd = 4;
jspd = 14;
grav = 0.6;

//Used to determine what way you were last facing after jumping ( 1 = right, -1 = left )
dir = 1;

//Face right by default
sprite_index = spr_idle_right;
STEP EVENT

Code:
///Player Controls

//Player input
left    = keyboard_check(vk_left);
right   = keyboard_check(vk_right);
jump    = keyboard_check_pressed (vk_space);

//If on the ground
if(place_meeting(x, y+1, obj_solid)){

    //Stop from falling
    vspd = 0;
  
    //Determines that we are currently on the ground
    grounded = true;
  
    //If the jump key is pressed
    if(jump){   
        //Jump
        vspd = -jspd;
    }

}else{
    //If not on ground
    if(grav < 15){       
        //Add gravity
        vspd += grav;
      
        //Determines that we are currently in the air
        grounded = false;
    }
}


//Control Movement
if(left){
    hspd = -mspd;
    dir = -1;
}

if(right){
    hspd = mspd;
    dir = 1;
}

//Stop moving
if(left && right) || (!left && ! right){
    hspd = 0;
}

//Control Sprites

//If on the ground...
if(grounded){

    //If dir is left...
    if(dir == -1){
        //Use walk left sprite
        sprite_index = spr_walk_left;
    }
  
    //If dir is right...
    if(dir == 1){
        //Use walk left sprite
        sprite_index = spr_walk_right;
  
    }
  
    //If not moving...
    if(!left && !right){   
        //If you were walking left...
        if(sprite_index == spr_walk_left){
            //Use idle left sprite
            sprite_index = spr_idle_left;
        }else
        //If you were walking right
        if(sprite_index == spr_walk_right){
            //Use the idle right sprite
            sprite_index = spr_idle_right;
        }
    }
  
}else{//If in the air

    //Use the jump sprite
    sprite_index = spr_jump;
}

//Check for collisions with walls
if(place_meeting(x+hspd, y, obj_solid)){
  
    while(!place_meeting(x+sign(hspd), y, obj_solid)){
        x+=sign(hspd);
    }

    hspd = 0;
}

if(place_meeting(x, y+vspd, obj_solid)){
  
    while(!place_meeting(x, y+sign(vspd), obj_solid)){
        y+=sign(vspd);
    }

    vspd = 0;
}


//Initialize movement
x += hspd;
y += vspd;
 
A

Agletsio

Guest
Here's the code I used. Hopefully it makes a bit of sense.

CREATE EVENT

Code:
///Init Player

hspd = 0;
vspd = 0;
mspd = 4;
jspd = 14;
grav = 0.6;

//Used to determine what way you were last facing after jumping ( 1 = right, -1 = left )
dir = 1;

//Face right by default
sprite_index = spr_idle_right;
STEP EVENT

Code:
///Player Controls

//Player input
left    = keyboard_check(vk_left);
right   = keyboard_check(vk_right);
jump    = keyboard_check_pressed (vk_space);

//If on the ground
if(place_meeting(x, y+1, obj_solid)){

    //Stop from falling
    vspd = 0;
 
    //Determines that we are currently on the ground
    grounded = true;
 
    //If the jump key is pressed
    if(jump){  
        //Jump
        vspd = -jspd;
    }

}else{
    //If not on ground
    if(grav < 15){      
        //Add gravity
        vspd += grav;
     
        //Determines that we are currently in the air
        grounded = false;
    }
}


//Control Movement
if(left){
    hspd = -mspd;
    dir = -1;
}

if(right){
    hspd = mspd;
    dir = 1;
}

//Stop moving
if(left && right) || (!left && ! right){
    hspd = 0;
}

//Control Sprites

//If on the ground...
if(grounded){

    //If dir is left...
    if(dir == -1){
        //Use walk left sprite
        sprite_index = spr_walk_left;
    }
 
    //If dir is right...
    if(dir == 1){
        //Use walk left sprite
        sprite_index = spr_walk_right;
 
    }
 
    //If not moving...
    if(!left && !right){  
        //If you were walking left...
        if(sprite_index == spr_walk_left){
            //Use idle left sprite
            sprite_index = spr_idle_left;
        }else
        //If you were walking right
        if(sprite_index == spr_walk_right){
            //Use the idle right sprite
            sprite_index = spr_idle_right;
        }
    }
 
}else{//If in the air

    //Use the jump sprite
    sprite_index = spr_jump;
}

//Check for collisions with walls
if(place_meeting(x+hspd, y, obj_solid)){
 
    while(!place_meeting(x+sign(hspd), y, obj_solid)){
        x+=sign(hspd);
    }

    hspd = 0;
}

if(place_meeting(x, y+vspd, obj_solid)){
 
    while(!place_meeting(x, y+sign(vspd), obj_solid)){
        y+=sign(vspd);
    }

    vspd = 0;
}


//Initialize movement
x += hspd;
y += vspd;

hi @Gillen82,

Sorry for late reply, been super busy!

So with this code my Player keeps rapidly shifting between idle and jump sprites when colliding with obj_solid? It does seem to call the correct sprite when landing in the different direction, so I think the answer is close!
 

Gillen82

Member
Also, are you using a parent object to control your solid objects? Just trying to compare to the system I set up to see if there are any differences
 
A

Agletsio

Guest
Yes @Gillen82 , it's happening when colliding with obj_solid (which is the only other object apart from player I have in the scene). When in mid-air everything is fine. As soon as Player touches ground, it rapidly starts shifting between sprites.

No, obj_solid has no parent.

I hope that's the info you were looking for?
 

Gillen82

Member
Yes @Gillen82 , it's happening when colliding with obj_solid (which is the only other object apart from player I have in the scene). When in mid-air everything is fine. As soon as Player touches ground, it rapidly starts shifting between sprites.

No, obj_solid has no parent.

I hope that's the info you were looking for?
What about your collision mask? Has this been modified in any way?
 
A

Agletsio

Guest
Yes, I modified the jumping sprite to be one pixel longer in height, otherwise when the Player landed and changed back to idle sprite it was few pixels inside ground and became totally stuck.

Do you think that would affect your code in some way?
 
Top