Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Jumping over sprite collision issue[SOLVED]  (Read 1725 times)

0 Members and 1 Guest are viewing this topic.

anrdyshmrdy

  • Newbie
  • *
  • Posts: 5
    • View Profile
Jumping over sprite collision issue[SOLVED]
« on: March 24, 2016, 03:45:26 pm »
I have been using SFML for about 4 months now. I recently began making a 2D platformer, after finally learning how to make a sprite jump by using AlexanderX's jumping tutorial. I pretty much use the same code AlexanderX used to make the sprite jump. I have no problem with the jumping overall, but there was one nagging issue I encountered that involved the sprite jumping over a block. When I hold down either the left or right key, collide into a block, and jump while still holding down either the left or right key, the moment the sprite goes over the corner of the block, the sprite acts as though it already landed and jumped again. Because this happens, the player looks like it is moving diagonally over a staircase of blocks. To better explain it, the sprite looks as though it never collides with the ground, and looks like it is floating diagonally over a staircase of blocks. I realize this could be a very common problem, but I couldn't find anything online to help solve it.
The code I have here is the code from the tutorial. I'm using this because it is much shorter than my code, and I didn't want to just show a small part, since you can't really see how it is applied. This code still has the same issue that I had in my code, so it will still help identify the problem.
#include <SFML/Graphics.hpp>
 
#include <vector>
 
const int gravity = 500;
bool onGround = false;
float inAir;
float maxInAir = 0.3f;
 
void move(sf::Vector2f &playerVelocity, float dt)
{
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
    {
        playerVelocity.x = -gravity;
    }
    else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
    {
        playerVelocity.x = gravity;
    }
    else if (playerVelocity.x != 0)
    {
        playerVelocity.x = 0;
    }
 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && (onGround || inAir < maxInAir))
    {
        playerVelocity.y = -gravity;
        inAir += dt;
    }
    else
    {
        playerVelocity.y = gravity;
        inAir = maxInAir;
    }
}
 
int main()
{
    sf::RenderWindow window(sf::VideoMode(800,600), "How to apply collision?");
 
    // Loading player texture
    sf::Texture playerTexture;
    if (!playerTexture.loadFromFile("player.png")) return 0;
 
    // Creating player sprite
    sf::Sprite player;
    player.setTexture(playerTexture);
 
    // Loading grass texture
    sf::Texture grassTexture;
    if (!grassTexture.loadFromFile("grass.png")) return 0;
 
    // Creating a vector because we have more blocks and we will need them into a container
    std::vector<sf::Sprite> grass;
 
    // Add 4 grass blocks to the container
    grass.resize(4);
    for (std::size_t i=0; i<3; ++i)
    {
        grass[i].setTexture(grassTexture);
        grass[i].setPosition(128 * i, 384);
    }
 
    // Last grass block will bo above the first one
    grass[3].setTexture(grassTexture);
    grass[3].setPosition(0,256);
 
    // Create a sf::Vector2f for player velocity and add to the y variable value gravity
    sf::Vector2f playerVelocity(0, gravity);
 
    sf::Clock clock;
    while (window.isOpen())
    {
        // Get the frame elapsed time and restart the clock
        float dt = clock.restart().asSeconds();
 
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }
 
        // Apply physics to player
        player.setPosition(player.getPosition().x + playerVelocity.x * dt, player.getPosition().y + playerVelocity.y * dt);
        onGround = false;
        for (std::size_t i=0; i<grass.size(); ++i)
        {
            // Affected area
            sf::FloatRect area;
            if (player.getGlobalBounds().intersects(grass[i].getGlobalBounds(), area))
            {
                // Verifying if we need to apply collision to the vertical axis, else we apply to horizontal axis
                if (area.width > area.height)
                {
                    if (area.contains({ area.left, player.getPosition().y }))
                    {
                        // Up side crash
                        player.setPosition({ player.getPosition().x, player.getPosition().y + area.height });
                    }
                    else
                    {
                        // Down side crash
                        onGround = true;
                        inAir = 0.f;
                        player.setPosition({ player.getPosition().x, player.getPosition().y - area.height });
                    }
                }
                else if (area.width < area.height)
                {
                    if (area.contains({ player.getPosition().x + player.getGlobalBounds().width - 1.f, area.top + 1.f }))
                    {
                        //Right side crash
                        player.setPosition({ player.getPosition().x - area.width, player.getPosition().y });
                    }
                    else
                    {
                        //Left side crash
                        player.setPosition({ player.getPosition().x + area.width, player.getPosition().y });
                    }
                }
            }
        }
 
        move(playerVelocity, dt);
 
        window.clear();
         
        // Draw the grass
        for (std::size_t i=0; i<grass.size(); ++i)
        {
            window.draw(grass[i]);
        }
 
        // Draw the player
        window.draw(player);
 
        window.display();
    }  
 
    return 0;
}
« Last Edit: March 26, 2016, 11:44:44 pm by anrdyshmrdy »

anrdyshmrdy

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Jumping over sprite collision issue[SOLVED]
« Reply #1 on: March 26, 2016, 11:43:39 pm »
Well, I managed to figure out the solution on my own. Turns out that it was a very easy fix.For future reference, here's the solution:
  else if (inAir == maxInAir)
                    {
                        // Down side crash
                        onGround = true;
                        inAir = 0.f;
                        player.setPosition( player.getPosition().x, player.getPosition().y - area.height );
                    }
                }

When I tested the variables using cout, I saw that the down side crash was being recognized when inAir was not equal to maxInAir. So I added an else if statement to make the section check when inAir was equal to maxInAir, and it immediately fixed it.