开发SFML回合制游戏时窗口自动关闭(错误码0)求助
回合制游戏网格系统窗口自动关闭问题排查与修复
运行回合制游戏的网格系统实现后,窗口会在短时间内自动关闭,错误码为0。以下是问题排查和修复方案,附完整代码:
核心问题分析
字体文件加载失败触发未定义行为
MapManager中加载字体时未做错误检查,若路径错误或文件缺失,textFont.loadFromFile返回false,后续将无效字体绑定到sf::Text会导致程序崩溃。事件处理遗漏窗口关闭事件
Input函数仅处理了Escape键关闭窗口,未响应用户点击窗口关闭按钮的事件,可能导致异常退出。构造函数中字符串换行符格式错误
MapManager构造函数中的输出语句存在语法错误,可能引发编译或运行时问题。
修复方案
1. 修复字体加载逻辑
在MapManager::InitializeInformationText中添加加载失败检查,提前暴露问题:
void MapManager::InitializeInformationText() { if (!textFont.loadFromFile("font/CaviarDreams.ttf")) { std::cerr << "Error: Failed to load font file at font/CaviarDreams.ttf" << std::endl; throw std::runtime_error("Font loading failed"); } gridInformationText.setCharacterSize(40); gridInformationText.setFillColor(sf::Color::Red); gridInformationText.setFont(textFont); gridInformationText.setPosition(20.f, 20.f); }
同时确认字体文件路径正确:工程根目录下需存在font文件夹,且包含CaviarDreams.ttf文件。
2. 完善事件处理逻辑
在Engine::input中添加窗口关闭事件的处理:
void Engine::input() { sf::Event event_play; while (window->pollEvent(event_play)) { if (event_play.type == sf::Event::Closed) { window->close(); } if (event_play.type == sf::Event::KeyPressed && event_play.key.code == sf::Keyboard::Escape) { window->close(); } } }
3. 修正构造函数中的字符串格式
MapManager::MapManager中的输出语句修正为:
MapManager::MapManager() { std::cout << "Map manager initialized\n"; gridSizeF = tile.getTileSize(); gridSizeU = static_cast<unsigned>(gridSizeF); grid.resize(Rows, std::vector<Tile>(Columns)); InitializeInformationText(); }
完整代码
tile.h
#pragma once #include "SFML/Graphics.hpp" #include "AssetManager.h" class Tile { public: Tile(); Tile(float size, sf::Texture texture); void setPosition(sf::Vector2f position); sf::Vector2f getPosition() const; void setTexture(std::string& filename); float getTileSize(); void setShape(); // set the rectangle shape parametrs sf::RectangleShape& getShape(); private: float tileSize = 0; sf::Vector2f tilePosition; sf::Texture tileTexture; sf::RectangleShape tileShape; };
tile.cpp
#include "Tile.h" Tile::Tile() { setShape(); } Tile::Tile(float size, sf::Texture texture) : tileSize(size), tileTexture(texture) { tileShape.setTexture(&tileTexture); tileShape.setOutlineThickness(1.f); tileShape.setOutlineColor(sf::Color::Black); } void Tile::setShape() { if(tileSize == 0) tileSize = 64.f; tileShape.setSize(sf::Vector2f(tileSize,tileSize)); tileShape.setFillColor(sf::Color::White); tileShape.setOutlineThickness(1.f); tileShape.setOutlineColor(sf::Color::Black); } void Tile::setPosition(sf::Vector2f position) { tilePosition = position; tileShape.setPosition(tilePosition.x, tilePosition.y); } sf::Vector2f Tile::getPosition() const { return tilePosition; } void Tile::setTexture(std::string& filename) { tileShape.setTexture(&AssetManager::GetTexture(filename)); } float Tile::getTileSize() { return tileSize; } sf::RectangleShape& Tile::getShape() { return tileShape; }
MapManager.h
#pragma once #include "SFML/Graphics.hpp" #include "Tile.h" #include <string> #include <vector> #include <sstream> class AssetManager; class MapManager { public: MapManager(); Tile getTile(); void generateGrid(); void InitializeInformationText();//Initialize sf::Text gridInformationText std::string gridInformation(sf::RenderWindow& window); // Make information about screen sf::Text& getInformationText(); void drawGrid(sf::RenderWindow& window); std::vector<std::vector<Tile>>& getGrid(); private: size_t Rows = 10; size_t Columns = 10; float gridSizeF = 0; // size of one cell of grid unsigned gridSizeU = 0; Tile tile; sf::Text gridInformationText; sf::Font textFont; sf::Vector2i mousePosScreen; // position of mouse on the screen sf::Vector2i mousePosWindow; // mouse position on window sf::Vector2f mousePosView; // mouse position on view sf::Vector2u mousePosGrid; // mouse position on grid std::vector<std::vector<Tile>> grid; };
MapManager.cpp
#include "MapManager.h" #include <iostream> MapManager::MapManager() { std::cout << "Map manager initialized\n"; gridSizeF = tile.getTileSize(); gridSizeU = static_cast<unsigned>(gridSizeF); grid.resize(Rows, std::vector<Tile>(Columns)); InitializeInformationText(); } Tile MapManager::getTile() { return tile; } void MapManager::generateGrid() { for (size_t x = 0; x < Rows; x++) { for (size_t y = 0; y < Columns; y++) { grid[x][y].setPosition(sf::Vector2f(x * gridSizeF, y * gridSizeF)); } } } void MapManager::InitializeInformationText() { if (!textFont.loadFromFile("font/CaviarDreams.ttf")) { std::cerr << "Error: Failed to load font file at font/CaviarDreams.ttf" << std::endl; throw std::runtime_error("Font loading failed"); } gridInformationText.setCharacterSize(40); gridInformationText.setFillColor(sf::Color::Red); gridInformationText.setFont(textFont); gridInformationText.setPosition(20.f, 20.f); } std::string MapManager::gridInformation(sf::RenderWindow& window) { mousePosScreen = sf::Mouse::getPosition(); mousePosWindow = sf::Mouse::getPosition(window); mousePosView = window.mapPixelToCoords(mousePosWindow); if (mousePosView.x >= 0.f) mousePosGrid.x = mousePosView.x / gridSizeU; if (mousePosView.y >= 0.f) mousePosGrid.y = mousePosView.y / gridSizeU; window.setView(window.getDefaultView()); std::stringstream ss; ss << "Screen: " << mousePosScreen.x << " " << mousePosScreen.y << std::endl << "Window: " << mousePosWindow.x << " " << mousePosWindow.y << std::endl << "View: " << mousePosView.x << " " << mousePosView.y << std::endl << "Grid: " << mousePosGrid.x << " " << mousePosGrid.y << std::endl; return ss.str(); } sf::Text& MapManager::getInformationText() { return gridInformationText; } void MapManager::drawGrid(sf::RenderWindow& window) { for (size_t x = 0; x < Rows; x++) { for (size_t y = 0; y < Columns; y++) { window.draw(getGrid()[x][y].getShape()); } } } std::vector<std::vector<Tile>>& MapManager::getGrid() { return grid; }
Engine.h
#pragma once #include<SFML/Graphics.hpp> #include "AssetManager.h" #include "MapManager.h" #include<memory> class Engine { public: Engine(); void run(); private: AssetManager manager; std::unique_ptr<sf::RenderWindow> window = std::make_unique<sf::RenderWindow>(sf::VideoMode(1280, 720), L"Dark Heresy Tactics", sf::Style::Default); MapManager mapManager; sf::RectangleShape background = sf::RectangleShape(sf::Vector2f(1280, 720)); sf::Texture background_texture; void input(); void update(sf::Time const& deltaTime); void draw(); };
Engine.cpp
#include "Engine.h" #include <iostream> void Engine::input() { sf::Event event_play; while (window->pollEvent(event_play)) { if (event_play.type == sf::Event::Closed) { window->close(); } if (event_play.type == sf::Event::KeyPressed && event_play.key.code == sf::Keyboard::Escape) { window->close(); } } } void Engine::update(sf::Time const& deltaTime) { mapManager.getInformationText().setString(mapManager.gridInformation(*window)); } void Engine::draw() { // Очистка графического окна window->clear(); mapManager.drawGrid(*window); window->draw(mapManager.getInformationText()); window->display(); } Engine::Engine() { mapManager.generateGrid(); } void Engine::run() { // Объявление переменной часы sf::Clock clock; // Цикл работает пока окно открыто while (window->isOpen()) { // Текущее время присваиваем переменной времени dt sf::Time dt = clock.restart(); input(); update(dt); draw(); } }
main.cpp
#include "Engine.h" #include "SFML/Graphics.hpp" #include <iostream> int main() { Engine engine; try { engine.run(); } catch (std::exception e) { std::cout << e.what() << std::endl; // 暂停控制台窗口,方便查看错误信息(Windows下) system("pause"); } return 0; }
内容的提问来源于stack exchange,提问作者Noname frai
相关产品推荐
相关产品推荐

