首页 > 解决方案 > SFML/C++ 项目中的“读取访问冲突”异常:

问题描述

我最近正在学习使用 Suraj Sharma 在 youtube 上的教程系列(视频 57)在 SFML 中制作 2d 游戏:

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

他的源代码:

https://github.com/Headturna/SFML_RPG

现在他正在教我通过在父类“State”中创建一个迷你类“StateData”来简化游戏的菜单系统,这样任何继承的类都可以通过“StateData”访问“State”参数(例如:MainMenu(StData* Stdata){ })。

调试后游戏似乎运行良好。但每次我单击菜单上的某些内容(开始、设置等...)时,“状态”类构造函数中都会出现“读取访问冲突:Stdata 为 nullptr”。

这是代码:

状态.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

状态.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;
}

菜单中的每个按钮(开始、退出...)都是从“状态”类继承的状态。例如,“编辑”状态。

编辑.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

编辑.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);
}

谁能帮我 ?

标签: c++visual-studiosfml

解决方案


推荐阅读