Based on the last tutorial, How to apply collision?, in this post I will you show how to make an entity jump in a platform game.

First thing we need to do in order to enable an entity to jump is to verify if the entity is on a ground:

bool onGround = false;

int main()
{
	// ...

	while (window.isOpen())
	{
		// ...

		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 it 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;
						player.setPosition({ player.getPosition().x, player.getPosition().y - area.height });
					}

				}
				else if (area.width < area.height)
				{
					// ...
				}
			}
		}
	}
}

We set the variable onGround initially to false because we set the player in air.

We set the variable to false to every frame because we don’t know if the player is still colliding with a block of grass. If the player collides with a block of grass we set the value to true.

We need two variables: for the maximum time the player is jumping and for the actual time the player is in the air:

float inAir;

float maxInAir = 0.3f;

And now in the function move() we add the code for jumping:

void move(sf::Vector2f &playerVelocity, float dt)
{
	// ...

	if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && (onGround || inAir < maxInAir))
	{
		playerVelocity.y = -gravity;
		inAir += dt;
	}
	else
	{
		playerVelocity.y = gravity;
		inAir = maxInAir;
	}
}

We modified the arguments of the function move() by adding the float dt in order to increase the variable inAir, which is the actual time the player is in the air.

We enable the player to jump only by pressing the UP key if the player is on ground or already in the air and the maximum time has not yet been reached.

If the above conditions have been met we set the velocity of vertical axis, y member, to -gravity and increase the inAir with the time of the frame, dt.

Otherwise we set the y value of velocity to gravity, so the player will fall down until it hits a block of grass, then we set inAir to maxInAir so the player can’t jump from air.

Last thing to do is to reset the inAir when the player is hitting the ground.

Here is the complete code:

#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;
}

You can find the source code and the resources on GitHub.