Нужна помощь с исключением "нарушение доступа на чтение" в проекте SFML/C++ :
Недавно я учусь делать 2d-игру на SFML, используя учебную серию на youtube от Suraj Sharma(видео 57):
https://www.youtube.com/watch?v=kwd_AVCkvXE&list=PL6xSOsbVA1ebkU66okpi-KViAO8_9DJKg&index=57
Его Исходный Код:
https://github.com/Headturna/SFML_RPG
Прямо сейчас он учит меня упрощать систему меню игры, создавая мини-класс "StateData" в родительском классе "State", чтобы любой унаследованный класс мог получить доступ к параметрам "State" через "StateData" (например:MainMenu(StData* Stdata){}).
После отладки игра, кажется, работает нормально.Но каждый раз,когда я нажимаю на что-то в меню(Пуск,Настройки и т. д.), В конструкторе класса "состояние" возникает "нарушение доступа на чтение:Stdata was nullptr".
Вот этот код:
Государства.ч:
<pre>#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:
<pre>#include "pch.h" #include "State.h" State::State(StData* Stdata) { this->Stdata = Stdata; this->window = Stdata->Window;//Read access violation 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; }
Каждая кнопка меню(Пуск,выход...)является наследуемым состоянием от класса "состояние".Это,например,состояние "редактировать".
Редактировать.ч:
<pre>#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:
<pre>#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); }
Кто-нибудь может мне помочь ?
Что я уже пробовал:
Я пробовал отлаживать проект,кажется, что с другими состояниями все в порядке.После того, как все параметры класса "State" были помещены в мини-класс "StData", это происходит.
TankRockett
Еще одна информация,оказывается, что в 'государстве.файл h конструктор 'StData()' имеет предупреждение 'C26495' , жалующееся на то, что следующие переменные 'Windows', 'GSettings', 'SupportedKeys' , 'states' , 'GridSize' неинициализированы.Этого не было в учебнике.