I am currently making a game in c++ using sfml, I encountered a problem where if I jump in my game, the jump mechanic allows the player to jump repeatedly in mid-air which is something I do not want. Here is a video showing my issue. I believe there is either an issue with my bool or collision but I am not sure what it is. Here is my player.h player.cpp and game.cpp.
player.h
#pragma once
#include "Precomp.h"
enum PLAYER_ANIMATION_STATES { Idle = 0, Left_Move, Right_Move, Jumping };
class Player
{
private:
sf::Sprite sprite;
sf::Texture textureSheet;
sf::Clock animationTimer;
//Animation
short animationStates;
sf::IntRect currentFrame;
bool animationSwitch;
//Physics
sf::Vector2f velocity;
sf::Vector2f position = sprite.getPosition();
float x;
float y;
float maxVelocity;
float minVelocity;
float acceleration;
float drag;
float gravity;
float MaxYVelocity;
float time;
float jumpVelocity;
float maxJumpHeight;
bool isJumping = false;
bool canJump = true;
//Health Points
//Private functions
void initVariables();
void initTexture();
void initSprite();
void initAnimations();
void initPhysics();
public:
Player();
virtual ~Player();
//Accessors
const bool& getAnimationSwitch();
const sf::Vector2f getPosition();
const sf::FloatRect getGlobalBounds() const;
const sf::Sprite& getSprite() const;
//Modifiers
void setPosition(const float x, const float y);
void resetVeloictyY();
void resetVelocityX();
//Functions
void resetAnimationTimer();
void move(const float dir_x, const float dir_y);
void setPlayerHitbox();
void updatePhysics();
void update();
void updateAnimations();
void updateMovement();
void render(sf::RenderTarget& target);
};
player.cpp
include "Player.h"
void Player::initVariables()
{
this->animationStates = PLAYER_ANIMATION_STATES::Idle;
}
void Player::initTexture()
{
//lLoad a texture
if (!this->textureSheet.loadFromFile("Sprites and Textures/Kim Pine Full Sprite Sheet 3.png"))
{
std::cout << "Failed";
}
}
void Player::initSprite()
{
//Set the texture to the sprite
this->sprite.setTexture(this->textureSheet);
//Resize the sprite
this->sprite.scale(3.f, 3.f);
this->currentFrame = sf::IntRect(0, 0 , 48, 95);
this->sprite.setTextureRect(this->currentFrame);
}
void Player::initAnimations()
{
this->animationTimer.restart();
this->animationSwitch = true;
}
void Player::initPhysics()
{
this->maxVelocity = 10.f;
this->minVelocity = 1.f;
this->acceleration = 1.05f;
this->drag = 0.96f;
this->gravity = 4.f;
this->MaxYVelocity = -15.f;
this->time = 1.f;
this->jumpVelocity = -12.0f;
}
Player::Player()
{
this->initVariables();
this->initTexture();
this->initSprite();
this->initAnimations();
this->initPhysics();
}
Player ::~Player()
{
}
const bool& Player::getAnimationSwitch()
{
bool anim_switch = this->animationSwitch;
if (this->animationSwitch)
this->animationSwitch = false;
return anim_switch; //Have not documented this yet as I have not fixed the animation yet
}
const sf::Vector2f Player::getPosition()
{
return this->sprite.getPosition();
}
const sf::FloatRect Player::getGlobalBounds() const
{
return this->sprite.getGlobalBounds();
}
const sf::Sprite& Player::getSprite() const
{
return this->sprite;
}
void Player::setPosition(const float x, const float y)
{
this->sprite.setPosition(x, y);
}
void Player::resetVeloictyY()
{
this->velocity.y = 0.f;
}
void Player::resetVelocityX()
{
this->velocity.x = 0.f;
}
void Player::updateAnimations()
{
if (this->animationStates == PLAYER_ANIMATION_STATES::Idle)
{
if (this->animationTimer.getElapsedTime().asSeconds() >= 0.25f || this->getAnimationSwitch())
{
this->currentFrame.top = 0.f;
this->currentFrame.left += 49.25f;
if (this->currentFrame.left >= 147.75f)
this->currentFrame.left = 0;
this->animationTimer.restart();
this->sprite.setTextureRect(this->currentFrame);
}
}
else if (this->animationStates == PLAYER_ANIMATION_STATES::Right_Move)
{
if (this->animationTimer.getElapsedTime().asSeconds() >= 0.1f || this->getAnimationSwitch())
{
this->currentFrame.top = 92.0f;
this->currentFrame.left += 49.1f;
if (this->currentFrame.left >= 245.9f)
this->currentFrame.left = 0;
this->animationTimer.restart();
this->sprite.setTextureRect(this->currentFrame);
}
this->sprite.setScale(3.f, 3.f);
this->sprite.setOrigin(0.f, 0.f);
}
else if (this->animationStates == PLAYER_ANIMATION_STATES::Left_Move)
{
if (this->animationTimer.getElapsedTime().asSeconds() >= 0.1f || this->getAnimationSwitch())
{
this->currentFrame.top = 92.0f;
this->currentFrame.left += 49.1f;
if (this->currentFrame.left >= 245.9f)
this->currentFrame.left = 0;
this->animationTimer.restart();
this->sprite.setTextureRect(this->currentFrame);
}
this->sprite.setScale(-3.f, 3.f);
this->sprite.setOrigin(this->sprite.getGlobalBounds().width / 3.f, 0.f);
}
/*
else if (this->animationStates == PLAYER_ANIMATION_STATES::Jumping)
{
if (this->animationTimer.getElapsedTime().asSeconds() >= 0.1f || this->getAnimationSwitch())
{
this->currentFrame.top = 196.0f;
this->currentFrame.left += 59.8f;
if (this->currentFrame.left >= 778.f)
this->currentFrame.left = 0;
this->animationTimer.restart();
this->sprite.setTextureRect(this->currentFrame);
}
this->sprite.setScale(3.f, 3.f);
this->sprite.setOrigin(0.f, 0.f);
}
*/
else
{
this->animationTimer.restart();
}
}
void Player::updateMovement()
{
//Move Player
this->animationStates = PLAYER_ANIMATION_STATES::Idle;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::A) || sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Left))
{
this->move(-1.f, 0.f);
this->animationStates = PLAYER_ANIMATION_STATES::Left_Move;
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::D) || sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Right))
{
this->move(1.f, 0.f);
this->animationStates = PLAYER_ANIMATION_STATES::Right_Move;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W) || sf::Keyboard::isKeyPressed(sf::Keyboard::Space) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && canJump)
{
this->velocity.y = jumpVelocity;
this->canJump = false;
this->animationStates = PLAYER_ANIMATION_STATES::Jumping;
if (sf::Event::KeyReleased)
{
if (this->velocity.y < -12.f)
this->velocity.y = -12.f;
}
}
/*
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
{
this->sprite.move(0.f, 1.f);
}
*/
}
void Player::resetAnimationTimer()
{
this->animationTimer.restart();
this->animationSwitch = true;
}
void Player::move(const float dir_x, const float dir_y)
{
//Accceleration
this->velocity.x += dir_x * this->acceleration;
//Limit Velocity
if (std::abs(this->velocity.x) > this->maxVelocity)
{
this->velocity.x = this->maxVelocity * ((this->velocity.x < 0.f) ? -1.f : 1.f);
}
}
void Player::updatePhysics()
{
/*
//Gravity
this->velocity.y += 1.0 * this->gravity;
if (std::abs(this->velocity.y) > this->MaxYVelocity)
{
this->velocity.y = this->MaxYVelocity * ((this->velocity.y < 0.f) ? -1.f : 1.f);
}
*/
//Deceleration
this->velocity *= this->drag;
//Limit Deceleration
if (std::abs(this->velocity.x) < this->minVelocity)
this->velocity.x = 0.f;
if (std::abs(this->velocity.y) < this->minVelocity)
this->velocity.y = 0.f;
this->sprite.move(this->velocity);
this->velocity.y += gravity * time;
//Jump Gravity
/*
if (canJump)
{
this->velocity.y = 0.f;
this->canJump = true;
}
*/
if (this->sprite.getPosition().y + this->sprite.getGlobalBounds().height >= 600)
{
this->canJump = false;
this->velocity.y = 0.f;
this->sprite.setPosition(this->sprite.getPosition().x, 600 - this->sprite.getGlobalBounds().height);
}
}
void Player::update()
{
this->updateMovement();
this->updatePhysics();
this->updateAnimations();
}
void Player::setPlayerHitbox()
{
}
void Player::render(sf::RenderTarget& target)
{
target.draw(this->sprite);
sf::CircleShape circ;
circ.setFillColor(sf::Color::Red);
circ.setRadius(2.f);
circ.setPosition(this->sprite.getPosition());
target.draw(circ);
};
game.cpp
#include "Game.h"
//Private Functions
void Game::initPlayer()
{
this->player = new Player();
}
void Game::initPlatform()
{
sf::RectangleShape platform(sf::Vector2f(200.f, 20.f));
platform.setPosition(300.f, 500.f);
platform.setFillColor(sf::Color::White);
}
void Game::initVariables()
{
}
void Game::initWindow()
{
this->window.create(sf::VideoMode(800,600), "CFFA Window", sf::Style::Titlebar | sf::Style::Close);
this->window.setFramerateLimit(144);
}
//Constructors
Game :: Game()
{
this->initVariables();
this->initWindow();
this->initPlayer();
}
Game ::~Game()
{
delete this->player;
}
const bool Game::running() const
{
return this->window.isOpen();
}
//Accessors
//Functions
void Game::render()
{
/*
return void
- clears the old frame
- renders the new objects
- displays the frame in the new window
Renders the game objects
*/
this->window.clear();
//Draw game objects
this->renderPlayer();
this->window.display();
}
void Game::update()
{
//Event Polling
while (this->window.pollEvent(this->ev))
{
if (this->ev.type == sf::Event::Closed)
{
this->window.close();
}
else if (this->ev.type == sf::Event::KeyPressed && this->ev.key.code == sf::Keyboard::Escape)
{
this->window.close();
}
if (this->ev.type == sf::Event::KeyReleased &&
(this->ev.key.code == sf::Keyboard::D ||
this->ev.key.code == sf::Keyboard::A ||
this->ev.key.code == sf::Keyboard::W ||
this->ev.key.code == sf::Keyboard::S
)
) // Need to Document when animation fixed
this->player->resetAnimationTimer();
}
this->updatePlayer();
}
void Game::renderPlayer()
{
this->player->render(this->window);
}
const sf::RenderWindow & Game::getWindow() const
{
// TODO: insert return statement here
return this->window;
}
void Game::updatePlayer()
{
this->player->update();
this->updateCollision();
}
void Game::updateCollision()
{
//Collision with Window
if (this->player->getPosition().y + this->player->getGlobalBounds().height > this->window.getSize().y)
{
this->player->resetVeloictyY();
this->player->setPosition(this->player->getPosition().x, this->window.getSize().y - this->player->getGlobalBounds().height);
}
if (this->player->getPosition().x + this->player->getGlobalBounds().width > this->window.getSize().x)
{
this->player->resetVelocityX();
this->player->setPosition(this->window.getSize().x - this->player->getGlobalBounds().width, this->player->getPosition().y);
}
if (this->player->getPosition().x < 0)
{
this->player->resetVelocityX();
this->player->setPosition(0, this->player->getPosition().y);
}
//Check collision between objects
}
Any help would be appreciated, thank you!