You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

开发SFML回合制游戏时窗口自动关闭(错误码0)求助

回合制游戏网格系统窗口自动关闭问题排查与修复

运行回合制游戏的网格系统实现后,窗口会在短时间内自动关闭,错误码为0。以下是问题排查和修复方案,附完整代码:

核心问题分析

  1. 字体文件加载失败触发未定义行为
    MapManager中加载字体时未做错误检查,若路径错误或文件缺失,textFont.loadFromFile返回false,后续将无效字体绑定到sf::Text会导致程序崩溃。

  2. 事件处理遗漏窗口关闭事件
    Input函数仅处理了Escape键关闭窗口,未响应用户点击窗口关闭按钮的事件,可能导致异常退出。

  3. 构造函数中字符串换行符格式错误
    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 11:04:51