• 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!

Releasing the crouch button clips through wall

Liam Earles

Member
So I'm making a game where a crouch mechanic takes place. When I release the down arrow key, it would go back to the idle sprite. So because of that, when I crouch or slide under a wall, it would clip through a wall because when I release the down arrow key, it would always go back to the idle sprite where it's not crouching.
Here's a code for when down is pressed:
Code:
if sprite_exists(sprite_CowboyWalkingRight)
if sprite_exists(sprite_CowboyIdleRight)
{
sprite_index = (sprite_CowboyDuckingRight)
}
else
if sprite_exists(sprite_CowboyWalkingLeft)
if sprite_exists(sprite_CowboyIdleLeft)
{
sprite_index = (sprite_CowboyDuckingLeft)
}
Here's a piece of code where I release the down arrow key:
Code:
if sprite_exists(sprite_CowboyDuckingRight)
{
sprite_index = (sprite_CowboyIdleRight)
}
else
if sprite_exists(sprite_CowboyDuckingLeft)
{
sprite_index = (sprite_CowboyIdleLeft)
}
Here's a picture of what it looks like when I test my game out.clipping issue.png
 

CMAllen

Member
What exactly do you want to have happen, and what is the problem? Is the player object becoming permanently stuck and unable to move/duck/proceed if the player stands up into a wall? Do you want to force the player object to remain crouched if standing up would otherwise cause a collision? Do you want a colliding sprite to get 'pushed' out of the space it currently occupies until a collision no longer happens? I've seen both methods used. Super Mario Bros (the old 2d ones) actually has the crouched sprite shorter than the vertical size of each cell, which allows the player to jump and move a bit, allowing them to wiggle through one-cell passages like the one in your image (and even expected players to utilize that skill in some cases).
 

Liam Earles

Member
What exactly do you want to have happen, and what is the problem? Is the player object becoming permanently stuck and unable to move/duck/proceed if the player stands up into a wall? Do you want to force the player object to remain crouched if standing up would otherwise cause a collision? Do you want a colliding sprite to get 'pushed' out of the space it currently occupies until a collision no longer happens? I've seen both methods used. Super Mario Bros (the old 2d ones) actually has the crouched sprite shorter than the vertical size of each cell, which allows the player to jump and move a bit, allowing them to wiggle through one-cell passages like the one in your image (and even expected players to utilize that skill in some cases).
I would like to have the player stay ducking while it's under that one block, like with the ducking and sliding mechanics in Super Mario Bros. The player does not get permanently stuck, I can use the down arrow keys and slide with left or right, so I can move while holding the down arrow key when stuck. When I have the player under a block/wall and I release the down arrow key, I want the player to stay crouching, and maybe press the jump button and use left and/or right arrow keys to get out of the tight space. So my problem is that when I release the down arrow key while sliding, it goes back to the idle, not crouching sprite, and will just stay stuck until I hold the down arrow key, and use left or right to get out of the tight space.
 

CMAllen

Member
Okay...that's easily done, actually. Inside your check for the release of the duck key, before transitioning into your standing state, change your sprite to the standing one and check for a collision at the player's position. If you have a collision, change back to the ducking sprite and continue on as though the duck key was still pressed. Otherwise, there's no collision and there's no problem.
 

Liam Earles

Member
Okay so I got it to work halfway, but two issues. When I press down, it will stay crouching until I press left or right, which would change to the walking sprite unless I am holding the down arrow key. Because the left press and right press switches the sprites, it would still be stuck unless I hold down then move left or right. So issue 1, it stays crouching unless I press left or right, and issue 2, is where the sprite for ducking would change to the walking animation, and would still get stuck when I press left or right. I might change the press down to hold down, otherwise it's a bit buggy.
 

CMAllen

Member
Then you've got two separate issues at play. One, your movement code is still assuming that it doesn't need to be ducking if the ducking button isn't being pressed. The second issue is that when the ducking button is not being pressed but the player object is still ducking, you need to continue doing the check for a collision above the player object until there no longer is one. When the player object is ducking, the ducking button is not being pressed, and there is no collision above the player object, then you need to stand the player back up correctly.

Ex (step-event pseudo code):
Code:
if (duck_button == true) // the player object should be ducking
{
    if(player_facing == direction_left)   
    {
        sprite_index=sprite_CowboyDuckingLeft;   // the player object is facing left
    else                   
    {
        sprite_index=sprite_CowboyDuckingRight;  // the player object is facing right
    }
else
{
    // the player object should not be ducking.
    var current_sprite = sprite_index // we're storing the current sprite here for a moment.
    if (current_sprite == sprite_CowboyDuckingRight OR current_sprite == sprite_CowboyDuckingLeft)
    {
        // The player object is ducking and shouldn't be
        sprite=sprite_CowboyWalkingRight;
        if(!place_meeting(x, y, obj_WallsAndSuch)
        {
            // No collision. Stand up.
            if(player_facing == direction_left)     
            {
                sprite_index=sprite_CowboyWalkingLeft;  // the player object is facing left
            else                   
            {
                sprite_index=sprite_CowboyWalkingRight; // the player object is facing right
            }
        else
        {
            // There's a collision above. Remain ducking.
            sprite_index=current_sprite;
        }
    }
}
Now, this is not how I'd handle all of this in my own work. For that, I'd use state machines. And I'd suggest you look into that. Finite State Machines is an incredibly useful programming theory to understand and utilize.
 

Let's Clone

Member
Not a quick solution, but one that might do well to teach you a better way to conceptualize this sort of thing: State machine tutorial.

I don't think I've watched this one, but Shaun Spalding is solid at what he does.
 

TheouAegis

Member
Because it's the only code I know that would recognize the sprite. I there are alternatives, let me know. I still can't figure out the issue.
If you looked up the function in the Help File, you'd see that it doesn't work. You don't need to recognize the sprite, you need to see what sprite the instance is currently using. The function's name itself even tells you it won't work the way you want -- "sprite_exists", of course the sprite exists, otherwise you would be getting errors left and right since you're trying to draw it. Furthermore, if you had read the Help File entry on sprite_exists() before throwing it haphazardly into your code, you would have also found the correct code to use:

Example:
if sprite_exists(spr_array[0])
{
sprite_index = spr_array[0];
}
else
{
sprite_index = spr_BaseSprite;
}

The above code checks an array to see if it contains a valid sprite index and if so it assigns that sprite to the instance, but if not, it assigns a sprite from the included resources.
 

CMAllen

Member
If you looked up the function in the Help File, you'd see that it doesn't work. You don't need to recognize the sprite, you need to see what sprite the instance is currently using. The function's name itself even tells you it won't work the way you want -- "sprite_exists", of course the sprite exists, otherwise you would be getting errors left and right since you're trying to draw it. Furthermore, if you had read the Help File entry on sprite_exists() before throwing it haphazardly into your code, you would have also found the correct code to use:
To expand on what TheouAegis is saying, the name you give to each sprite, which are unique, *IS* that's sprite's identifier. So a simple if(sprite_index=sprite_walking) test will check to see if the object running that code is using the sprite_walking sprite. Furthermore, the actual values of each sprite is numeric, starting from 0 for the first sprite at the top of the resource list, and incrementing by one for each additional sprite. This is true of all resources added to a project, in fact (each different type of asset is its own list, each one starting from 0).

Note: this is still *not* the best way to do this sort of thing, regardless. You shouldn't be checking the sprite_index value to determine what kind of action to take. Rather, when your object draws itself, it should be checking what kind of state it is in and use that information to determine what sprite it should be drawing.
 
Top