Search code examples
c++sdlreset

How to reset values after dying


I am making a google chrome dinosaur game using an SDL Template for graphics and I am almost finished but I have run into the issue of needing to be able to reset to the starting values of the game just like how you reset when you hit spacebar after dying in the google chrome dinosaur game. I have made an isGameOver function but I don't know how to reset the values to start a new game which is my main problem.

this is my GameScene class where the game over logic is located

GameScene.h

#pragma once
#include "Scene.h"
#include "GameObject.h"
#include "Player.h"
#include "Floor.h"
#include "Obstacle.h"
#include "FlyingObstacle.h"
#include <vector>
#include "util.h"
#include "text.h"

class GameScene : public Scene
{
public:
    GameScene();
    ~GameScene();
    void start();
    void draw();
    void update();
    std::vector<Obstacle*> spawnedObstacle;
    std::vector<FlyingObstacle*> spawnedBird;

private:
    Player* player;
    Floor* floor;

    float spawnTime;
    float currentSpawnTimer;
    void floorCollision();
    void obstacleCollision();
    void birdCollision();
    void obstacleSpawn();
    void birdSpawn();
    void despawnObstacle(Obstacle* obstacle);
    void despawnBird(FlyingObstacle* bird);
    int points;
    int highscore;
    bool isGameOver;
};

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);

    points = 0;
    highscore = 0;

}

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

void GameScene::start()
{
    Scene::start();
    // Initialize any scene logic here

    initFonts();
    isGameOver = true;
    currentSpawnTimer = 300;
    spawnTime = rand() % 300; //spawn time of 5 seconds

    for (int i = 0; i < 1; i++)
    {

        obstacleSpawn();

    }

    for (int i = 0; i < 3; i++)
    {
        birdSpawn();
    }


}

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

        drawText(110, 20, 255, 255, 255, TEXT_CENTER, "POINTS: %03d", points);


        if (player->getIsAlive() == true)
        {
            drawText(900, 20, 255, 255, 255, TEXT_CENTER, "PRESS SPACE TO START MOVING");
        }

    if (player->getIsAlive() == false)
    {
        if (isGameOver == false)

        drawText(SCREEN_WIDTH / 2, 200, 255, 255, 255, TEXT_CENTER, "YOU LOSE! PRESS SPACE TO SHOW POINTS");

        if (isGameOver == true)
        {
            drawText(SCREEN_WIDTH / 2, 200, 255, 255, 255, TEXT_CENTER, "HIGHSCORE: %03d", highscore); 

                if (points > highscore)
                {
                    drawText(SCREEN_WIDTH / 2, 200, 255, 255, 255, TEXT_CENTER, "NEW HIGHSCORE: %03d", points, highscore);
                }
        }
    }
}

void GameScene::update()
{

    if (isGameOver == true)
    {
        if (app.keyboard[SDL_SCANCODE_SPACE])
        {
            isGameOver = false;
            
        }

    }
    if (isGameOver == false)
    {
        Scene::update();

        floorCollision();
        obstacleCollision();
        birdCollision();


        if (currentSpawnTimer > 0)
            currentSpawnTimer--;

        if (currentSpawnTimer <= 0)
        {
            for (int i = 0; i < 1; i++)
            {
                obstacleSpawn();
            }

            for (int i = 0; i < 3; i++)
            {
                birdSpawn();
            }

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

        else {
            player->getY() + 0;
        }
    }
}



void GameScene::floorCollision()
{
        //Checks for collisions
        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)
                {

                    player->setOnFloor(true);
                    
                    if (player->getIsAlive() == true)
                    {
                        points++;
                        highscore++;
                    }

                    break;
                }

            }
        }
}


void GameScene::obstacleCollision()
{
    for (int i = 0; i < objects.size(); i++)
    {

        Obstacle* obstacle = dynamic_cast<Obstacle*>(objects[i]);

        if (obstacle != NULL)
        {
            if (obstacle != NULL)
            {
                int collision = checkCollision(
                    player->getX(), player->getY(), player->getWidth(), player->getHeight(),
                    obstacle->getX(), obstacle->getY(), obstacle->getWidth(), obstacle->getHeight()
                );

                if (collision == 1)
                {
                    player->doDeath();
                    isGameOver = true;
                    break;
                }
            }
        }

    }

}

void GameScene::birdCollision()
{
    for (int i = 0; i < objects.size(); i++)
    {

        FlyingObstacle* bird = dynamic_cast<FlyingObstacle*>(objects[i]);


        if (bird != NULL)
        {
            if (bird != NULL)
            {
                int collision = checkCollision(
                    player->getX(), player->getY(), player->getWidth(), player->getHeight(),
                    bird->getX(), bird->getY(), bird->getWidth(), bird->getHeight()
                );

                if (collision == 1)
                {
                    player->doDeath();
                    isGameOver = true;
                    break;
                }
            }
        }

    }
}


void GameScene::obstacleSpawn()
{
    Obstacle* obstacle = new Obstacle();
    this->addGameObject(obstacle);

    obstacle->setPosition(1200, 300 + (rand() % 300));
    spawnedObstacle.push_back(obstacle);
}

void GameScene::birdSpawn()
{
    FlyingObstacle* bird = new FlyingObstacle();
    this->addGameObject(bird);

    bird->setPos(1200, 300 + (rand() % 300));
    spawnedBird.push_back(bird);
}

void GameScene::despawnObstacle(Obstacle* obstacle)
{
    int index = -1;
    for (int i = 0; i < spawnedObstacle.size(); i++)
    {
        //If pointer matches
        if (obstacle == spawnedObstacle[i])
        {
            index = i;
            break;
        }
    }

    //If any match is found
    if (index != -1)
    {
        spawnedObstacle.erase(spawnedObstacle.begin() + index);
        delete obstacle;
    }
}

void GameScene::despawnBird(FlyingObstacle* bird)
{
    int index = -1;
    for (int i = 0; i < spawnedBird.size(); i++)
    {
        //If pointer matches
        if (bird == spawnedBird[i])
        {
            index = i;
            break;
        }
    }

    //If any match is found
    if (index != -1)
    {
        spawnedBird.erase(spawnedBird.begin() + index);
        delete bird;
    }
}

I tried making an isGameOver bool inside my GameScene.h and I made it so that pressing spacebar would reset the game but in reality when the player dies the screen pauses every movement instead of resetting and if I press space again the game continues to move even though the player is dead.


Solution

  • Your entry point for the game(probably main)function will probably have some form like this

    #include ...
    #include ...
    ...
    
    int main()
    {
       bool game_running = true;
       while(game_running)
       {
           GameInstance* game = new Game(); //Allocation and initialization of all resources needed to play the game.
           game.play(); // This function will finish when you lose the game.
           delete game; // Deallocation.
           if(!run_again())
           {
               game_running = false;
           }
       }
    
       return 0;
    }
    

    After deallocation, you check if user wants to play again, you enter the next iteration of while loop, and new instance of Game is allocated, where all the resource handling takes place. The only problem is that allocating Game instance for every iteration might be a little costly, but you can ignore that if you don't worry about performance much.