将代码移动到另一个函数时的范围问题- c++ SFML

omhiaaxx  于 2023-07-01  发布在  其他
关注(0)|答案(1)|浏览(108)

我正在尝试创建一个简单的网格与一些图像。当初始化在一个函数中时,一切都很好:

void gameLoop()
{
    sf::RenderWindow window(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), "Minesweeper", sf::Style::Titlebar | sf::Style::Close);
    std::vector<std::vector<sf::Sprite>> grid(DEFAULT_ROWS_NUM, std::vector<sf::Sprite>(DEFAULT_COLS_NUM));

    sf::Texture unrevealedEmptyTexture;
    if (!unrevealedEmptyTexture.loadFromFile("Images/unrevealed_empty.png"))
        return;

    // Set the position and scale of each sprite
    for (int i = 0; i < DEFAULT_ROWS_NUM; i++)
    {
        for (int j = 0; j < DEFAULT_COLS_NUM; j++)
        {
            grid[i][j].setTexture(unrevealedEmptyTexture);
            grid[i][j].setPosition(i * CELL_SIZE, j * CELL_SIZE);

            // Rescale to CELL_SIZE (multiply by CELL_SIZE / IMAGE_DIMENSION, for both x and y) 
            grid[i][j].setScale((float)CELL_SIZE / unrevealedEmptyTexture.getSize().x, (float)CELL_SIZE / unrevealedEmptyTexture.getSize().y);
        }
    }

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        //window.clear(sf::Color::White);
        drawBoard(window, grid);
        window.display();
    }
}

但是如果我将创建sprite向量的代码移动到另一个函数(在同一个文件中):

std::vector<std::vector<sf::Sprite>> initGuiBoard()
{
    std::vector<std::vector<sf::Sprite>> grid(DEFAULT_ROWS_NUM, std::vector<sf::Sprite>(DEFAULT_COLS_NUM));

    sf::Texture unrevealedEmptyTexture;
    if (!unrevealedEmptyTexture.loadFromFile("Images/unrevealed_empty.png"))
        return {};

    // Set the position and scale of each sprite
    for (int i = 0; i < DEFAULT_ROWS_NUM; i++)
    {
        for (int j = 0; j < DEFAULT_COLS_NUM; j++)
        {
            grid[i][j].setTexture(unrevealedEmptyTexture);
            grid[i][j].setPosition(i * CELL_SIZE, j * CELL_SIZE);

            // Rescale to CELL_SIZE (multiply by CELL_SIZE / IMAGE_DIMENSION, for both x and y) 
            grid[i][j].setScale((float)CELL_SIZE / unrevealedEmptyTexture.getSize().x, (float)CELL_SIZE / unrevealedEmptyTexture.getSize().y);
        }
    }

    return grid;
}

然后称之为:

void gameLoop()
{
    sf::RenderWindow window(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), "Minesweeper", sf::Style::Titlebar | sf::Style::Close);
    std::vector<std::vector<sf::Sprite>> guiGrid = initGuiBoard();

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        //window.clear(sf::Color::White);
        drawBoard(window, guiGrid);
        window.display();
    }
}

Windows是纯白色的。我假设这与范围有关,但我真的不确定。我知道我可以只去与第一个选项,但我想我的代码分离成函数。
有什么办法可以解决这个问题吗?谢谢!

gfttwv5a

gfttwv5a1#

正如注解中所指出的,Texture在使用Sprite之前被销毁。这是因为Texture是作为initGuiBoard中的局部变量创建的,并在函数结束时被销毁。
要解决这个问题,可以从initGuiBoard返回Texture

pair<vector<vector<sf::Sprite>>, sf::Texture> initGuiBoard() {
    // ...
    return { grid, unrevealedEmptyTexture };
}
void gameLoop() {
    auto [ guiGrid, unrevealedEmptyTexture ] = initGuiBoard();
    // ...
}

另一个选项是在gameLoop中创建纹理,并通过引用将其传递给initGuiBoard

void gameLoop() {
    sf::Texture unrevealedEmptyTexture;
    if (!unrevealedEmptyTexture.loadFromFile("Images/unrevealed_empty.png"))
        return;
    std::vector<std::vector<sf::Sprite>> guiGrid = initGuiBoard(unrevealedEmptyTexture);
    // ...
}

这样,纹理将是本地gameLoop变量,并将一直存在到该函数结束。

相关问题