Search code examples
c++booleansdlcollision

How can I make my player stop when he hits the floor


I am working on a google chrome dinosaur chrome clone using an SDL template and I have an issue where the character is not stopping once he hits the floor. My code logic is supposed to work like this, I have a bool called "onFloor" that tells the program when the player and ground come into contact with each other. When onFloor = false the player keeps on falling and when onFloor = true the player stops falling and stays in place. My issue is that when I try to do the reverse of my current falling or gravity code.

These are the parts of my code that I think are the problem

Player.h

#pragma once
#include "GameObject.h"
#include "common.h"
#include "draw.h"

class Player :
    public GameObject
{
public:
    void start();
    void update();
    void draw();


    //X Setter
    void setX(int x) {
        this->side = x;
    }
    //X Getter
    int getX() {
        return side;
    }
    //Y Setter
    void setY(int y) {
        this->fall = y;
    }
    //Y Getter
    int getY() {
        return fall;
    }
    //Height Setter
    void setHeight(int h) {
        height = h;
    }
    //Height Getter
    int getHeight() {
        return height;
    }
    //Width Setter
    void setWidth(int w) {
        width = w;
    }
    //Width Getter
    int getWidth() {
        return width;
    }
    //OnFloor Setter
    void setOnFloor(bool onFloor) {
        onFloor = true;
    }
    //OnFloor Getter
    bool getOnFloor() {
        return onFloor;
    }
private:
    SDL_Texture* texture;
    int side;
    int fall;
    int height;
    int width;
    int speed;
    bool onFloor;

};

GameScene.cpp

#include "GameScene.h"

GameScene::GameScene()
{
    // Register and add game objects on constructor
    player = new Player();
    this->addGameObject(player);

    floor = new Floor();
    this->addGameObject(floor);
}

GameScene::~GameScene()
{
    delete player;
}

void GameScene::start()
{
    Scene::start();


    // Initialize any scene logic here
}

void GameScene::draw()
{
    Scene::draw();
}

void GameScene::update()
{
    Scene::update();


    floorCollision();
    //This is where Gravity strength is located
    if (player->getOnFloor() == false) {
        player->setY(player->getY() + 2);
    }

    else {
        player->setY(0);
    }
    
}

void GameScene::floorCollision()
{
        //Checks for collisions between player and floor
        for (int i = 0; i < objects.size(); i++)
        {
            //Cast to floor
            Floor* floor = dynamic_cast<Floor*>(objects[i]);

            //Check if the floor was casted
            if (floor != NULL)
            {

                int collision = checkCollision(
                    player->getX(), player->getY(), player->getWidth(), player->getHeight(),
                    floor->getX(), floor->getY(), floor->getWidth(), floor->getHeight()
                );

                if (collision == 1)
                {
                    std::cout << "!" << std::endl;
                    player->getOnFloor() == true;
                    break;
                }

            }
        }
}

at first I thought that just changing the false to true would work so I just put this part of the code

player->getOnFloor() == false

into my collision logic but instead of false I make it true once he hits the ground to stop him from falling

void GameScene::floorCollision()
{
        //Checks for collisions between player and floor
        for (int i = 0; i < objects.size(); i++)
        {
            //Cast to floor
            Floor* floor = dynamic_cast<Floor*>(objects[i]);

            //Check if the floor was casted
            if (floor != NULL)
            {

                int collision = checkCollision(
                    player->getX(), player->getY(), player->getWidth(), player->getHeight(),
                    floor->getX(), floor->getY(), floor->getWidth(), floor->getHeight()
                );

                if (collision == 1)
                {   
                    std::cout << "!" << std::endl;
                    //This is what is supposed to make the player stop falling
                    player->setOnFloor(player->getOnFloor() == true);
                    break;
                }

            }
        }
}

but the player just falls through the floor

EDIT:

Okay I think I fixed it and the player stops falling when he hits the ground by changing my onFloor setter in my player.h to this


    //OnFloor Setter
    void setOnFloor(bool) {
        onFloor = true;
    }

and my GameScene collision logic to this

if (collision == 1)
                {
                    std::cout << "!" << std::endl;
                    player->setOnFloor(true);
                    break;
                }

New problem now though is that when onFloor = true the player just sticks to the top of the screen with no way to move down or up anymore.


Solution

  • I'm not sure whether this is the only issue but it's one which could be responsible for OPs reported problem:

        //OnFloor Setter
        void setOnFloor(bool onFloor) {
            onFloor = true;
        }
    

    The argument onFloor shadows the member variable Player::onFloor. (This is legal in C++ as the function starts a local scope.)

    Thus, true is assigned to the argument onFloor (which is pointless as it's a value parameter and lost after return from function) while the member variable Player::onFloor is not modified at all.

    Nevertheless, though the member variable is shadowed by an argument , it's still accessible — either by this->onFloor or by Player::onFloor.

    So, a possible fix is:

        //OnFloor Setter
        void setOnFloor(bool onFloor) {
            this->onFloor = onFloor;
        }
    

    or

        //OnFloor Setter
        void setOnFloor() {
            onFloor = true;
        }