0
\$\begingroup\$

I'm recently learning to make a 2d game in SFML using a tutorial series on youtube by Suraj Sharma(Video 57):

https://www.youtube.com/watch?v=kwd_AVCkvXE&list=PL6xSOsbVA1ebkU66okpi-KViAO8_9DJKg&index=57

His Source Code:

https://github.com/Headturna/SFML_RPG

Right now he's teaching me to symplify the game's menu system by making a mini class 'StateData' in the parent class 'State' so any inherited class can access 'State' parameters via 'StateData'(Ex:MainMenu(StData* Stdata){}).

After debugging the game seems to runs fine.But everytime i click on something on the menu(start,settings,etc...) a 'Read access violation:Stdata was nullptr' occurs in the 'State' class constructor.

Here's the code:

State.h:

    #pragma once

#ifndef STATE_H
#define STATE_H

#include "Player.h"
#include "GrphSettings.h"

class Player;
class GrphSettings;
class State;

class StData {
public:
    StData(){}

    //Vars
    float GridSize;
    sf::RenderWindow* Window;
    GrphSettings* GSettings;
    std::map<std::string, int>* SupportedKeys;
    std::stack<State*>* states;
};

class State
{
private:

protected:
    StData* Stdata;
    std::stack<State*>* states;
    sf::RenderWindow* window;
    std::map<std::string, int>* SupportedKeys ;
    std::map<std::string, int> Keybinds;
    bool quit;
    bool pause;
    float keyTime; 
    float keyTimeMax;
    float GridSize;

    sf::Vector2i MousePosScr;
    sf::Vector2i MousePosWind;
    sf::Vector2f MousePosView;
    //Resources
    std::map<std::string,sf::Texture> texture;
    //Funcs
    virtual void InitKeybinds() = 0;
public:
    State(StData* Stdata);
    virtual~State();
    //Access
    const bool getKeytime();
    const bool& getquit()const;
    //Funcs
    void Endstate();
    void PauseSt();
    void UnPauseSt();

    virtual void UpdateInput(const float& dt) = 0;
    virtual void UpdateMousePos();
    virtual void UpdateKeyTime(const float& dt);
    virtual void Update(const float& dt) = 0;
    virtual void Render(sf::RenderTarget* target = nullptr) = 0;
};
#endif // !1

State.cpp:

    #include "pch.h"
#include "State.h"

State::State(StData* Stdata)
{ 
    this->Stdata = Stdata;
    this->window = Stdata->Window;
    this->SupportedKeys = Stdata->SupportedKeys;
    this->states = Stdata->states;
    this->quit = false;
    this->pause = false;
    this->keyTime = 0.f;
    this->keyTimeMax = 10.f;
    this->GridSize = Stdata->GridSize;
}

State::~State()
{
}
//Access
const bool State::getKeytime()
{
    if (this->keyTime >= this->keyTimeMax) {
        this->keyTime = 0.f; 
        return true;
    }
    return false;
}

const bool& State::getquit() const
{
    // TODO: insert return statement here
    return this->quit;
}
//Funcs
void State::Endstate()
{
    this->quit = true;
}

void State::PauseSt()
{
    this->pause = true;
}

void State::UnPauseSt()
{
    this->pause = false;
}

void State::UpdateMousePos()
{
    this->MousePosScr = sf::Mouse::getPosition();
    this->MousePosWind = sf::Mouse::getPosition(*this->window);
    this->MousePosView = this->window->mapPixelToCoords(sf::Mouse::getPosition(*this->window));
}

void State::UpdateKeyTime(const float& dt)
{
    if (this->keyTime < this->keyTimeMax)
        this->keyTime += 100.f * dt;
}

Every button one the menu(start,exit...)is an inherited state from 'State' class.This is,for example,the 'Edit' state.

Edit.h:

    #pragma once
#ifndef EDIT_H
#define EDIT_H

#include "State.h"
#include "Gui.h"
#include "PauseMenu.h"
#include "TileMap.h"

class State;
class Gui;
class PauseMenu;
class TileMap;

class Edit:public State
{
private:
    //Vars
    sf::Font Fnt;
    PauseMenu* PMenu;
    std::map<std::string, gui::Button*> buttons;
    TileMap Map;

    //Functions
    void InitVars();
    void InitBackGrnd();
    void InitFonts();
    void InitKeybinds();
    void InitPauseMenu();
    void InitBtn();
public:
    Edit(StData* Stdata);
    virtual~Edit();
    //Functions
    void UpdateInput(const float& dt);
    void Update(const float& dt);
    void UpdatePButtons();
    void UpdateBtn();

    void Endstate();

    void RenderBtn(sf::RenderTarget& target);
    void Render(sf::RenderTarget* target = nullptr);
};
#endif // ! EDIT_H

Edit.cpp:

    #include "pch.h"
#include "Edit.h"

void Edit::InitVars()
{
}

void Edit::InitBackGrnd()
{
}

void Edit::InitFonts()
{
    if (!this->Fnt.loadFromFile("Fonts/SPACEMAN.ttf")) {
        throw("Error::Edit::Couldn't load font");
    }
}

void Edit::InitKeybinds()
{
    std::ifstream ifs("Config/EditKeys.ini");

    if (ifs.is_open()) {
        std::string key = "";
        std::string key2 = "";
        int keyval = 0;
        while (ifs >> key >> key2)
        {
            this->Keybinds[key] = this->SupportedKeys->at(key2);
        }
    }
    ifs.close();

    this->Keybinds["Close"] = this->SupportedKeys->at("ESC");
    this->Keybinds["Left"] = this->SupportedKeys->at("A");
    this->Keybinds["Right"] = this->SupportedKeys->at("D");
    this->Keybinds["Up"] = this->SupportedKeys->at("W");
    this->Keybinds["Down"] = this->SupportedKeys->at("S");
}

void Edit::InitPauseMenu()
{
    this->PMenu = new PauseMenu(*this->window, this->Fnt);
    this->PMenu->addButtons("Quit", 800.f, "Quit");
}

void Edit::InitBtn()
{
}

Edit::Edit(StData* Stdata)
    :State(Stdata)
{
    this->InitVars();
    this->InitBackGrnd();
    this->InitFonts();
    this->InitKeybinds();
    this->InitPauseMenu();
    this->InitBtn();
}

Edit::~Edit()
{
    auto it = this->buttons.begin();
    for (it = this->buttons.begin(); it != this->buttons.end(); ++it) {
        delete it->second;
    }
    delete this->PMenu;
}

//Funcs
void Edit::UpdateInput(const float& dt)
{
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key(this->Keybinds.at("Close")))
        && this->getKeytime()) {
        if (!this->pause)
            this->PauseSt();
        else this->UnPauseSt();
    }

}

void Edit::Update(const float& dt)
{
    this->UpdateMousePos();
    this->UpdateKeyTime(dt);
    this->UpdateInput(dt);

    if (!this->pause) {//Unpaused
        this->UpdateBtn();
    }
    else {//Paused
        this->PMenu->Update(this->MousePosView);
        this->UpdatePButtons();
    }

    this->UpdateBtn();

    std::cout << this->MousePosView.x << " " << this->MousePosView.y << "\r";
}

void Edit::UpdatePButtons()
{
    if (this->PMenu->isPressed("Quit"))
            this->Endstate();
}

void Edit::UpdateBtn()
{   //Update buttons and handle their functions
    for (auto& it : this->buttons) {
        it.second->Update(MousePosView);
    }
}

void Edit::Endstate()
{
    std::cout << "Ending State" << "\n";
}

void Edit::RenderBtn(sf::RenderTarget& target)
{
    for (auto& it : this->buttons) {
        it.second->Render(target);
    }
}

void Edit::Render(sf::RenderTarget* target)
{
    if (!target)
        target = this->window;

    this->RenderBtn(*target);

    this->Map.Render(*target);

    if (this->pause) {//Pause Menu
        this->PMenu->Render(*target);
    }

    sf::Text MText;
    MText.setPosition(this->MousePosView);
    MText.setFont(this->Fnt);
    MText.setCharacterSize(12);
    std::stringstream ss;
    ss << this->MousePosView.x << ' ' << this->MousePosView.y;
    MText.setString(ss.str());

    target->draw(MText);
}

Can anyone help me ?

\$\endgroup\$
  • \$\begingroup\$ This type of error seems to be covered extensively on StackOverflow. How have you tried applying your research in these existing Q&A threads to solve this problem? \$\endgroup\$ – DMGregory Nov 18 '19 at 5:34
  • 1
    \$\begingroup\$ When this happens, check the call stack: check the calling frame(s), the parameter you pass should be null. Check why this parameter is null. Since you only provide the code for where it happens, and not the calling code, we can't help you further. \$\endgroup\$ – Vaillancourt Nov 18 '19 at 12:45
  • \$\begingroup\$ One more information,it appears that in the 'State.h' file the 'StData()' constructor are having warning 'C26495' complaining that the following variables 'Windows' , 'GSettings' , 'SupportedKeys' , 'states' , 'GridSize' are uninitialized.That didn't happen in the tutorial. \$\endgroup\$ – TankRocket Nov 18 '19 at 15:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.