我无法使用 CMake 将我的游戏资源加载到 SFML
I can't load my game resources into SFML with CMake
我正在用 Visual Studio 代码用 C++ 编写一个小游戏,以 CMake 作为构建系统。到目前为止,访问资源没有任何问题,但由于我决定通过在目录中组织它来整理我的项目,我的 GetTexture、GetSoundBuffer 和 GetFont 函数无法从 Resources 文件夹加载图像。
显然我知道在将文件保存在不同目录时,我必须更新路径。所以一开始是“Resources / image.png”变成了“../../../Resources/image.png”,(它对所有#include 指令都有效)但是当我 运行 游戏我只看到黑屏和控制台向我显示 无法加载图像“../../../Resources/image.png”之类的消息。原因:无法打开文件.
我一遍又一遍地尝试重新安排项目,但每次编译时都会发生这种情况。我对 CMake 了解不多,我不知道问题出在我的 CMakeLists.txt 文件还是我之前提到的函数,我怀疑它们之前工作得很好。
获取纹理:
sf::Texture& Game::GetTexture(std::string _fileName)
{
auto iter = textures.find(_fileName);
if (iter != textures.end())
{
return *iter->second;
}
TexturePtr texture = std::make_shared<sf::Texture>();
texture->loadFromFile(_fileName);
textures[_fileName] = texture;
return *texture;
}
GetSoundBuffer:
sf::SoundBuffer& Game::GetSoundBuffer(std::string _fileName)
{
auto iter = sounds.find(_fileName);
if (iter != sounds.end())
{
return *iter->second;
}
SoundBufferPtr sound = std::make_shared<sf::SoundBuffer>();
sound->loadFromFile(_fileName);
sounds[_fileName] = sound;
return *sound;
}
GetFont:
sf::Font& Game::GetFont(std::string _fileName)
{
auto iter = fonts.find(_fileName);
if (iter != fonts.end())
{
return *iter->second;
}
FontPtr font = std::make_shared<sf::Font>();
font->loadFromFile(_fileName);
fonts[_fileName] = font;
return *font;
}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.18)
set(PROJECT_NAME "MyGame")
project(MyGame)
set(SFML_DIR "${CMAKE_CURRENT_LIST_DIR}/libs/SFML-2.5.1/lib/cmake/SFML")
file(GLOB ALL_REQUIRED_DLL "libs/required_dlls/*.dll")
file(COPY ${ALL_REQUIRED_DLL} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
set(CMAKE_CXX_STANDARD 17)
set(SOURCE_FILES
...
${RES_FILES})
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
find_package(SFML 2.5.1 COMPONENTS system window graphics network audio REQUIRED)
target_link_libraries(${PROJECT_NAME} sfml-audio sfml-graphics sfml-window sfml-system)
项目组织结构如下:
Build:
(Cmake build stuff)
Engine:
(All engine codes, no problem here)
Scenes:
Scene1:
include:
(All .h files)
src:
(All .cpp files, here is where i call GetTexture, GetSoundBuffer
and GetFont)
Resources:
(All the images, sounds and fonts)
CMakeLists.txt
main.cpp
对于所有这些,值得一提的是我正在使用 Linux。
当您 运行 在另一个位置执行可执行文件时,相对路径将与编译时的路径不同。
一个解决方案是使所有内容都与可执行文件的位置相关,如:
namespace fs = std::filesystem;
int main( int argc, char* argv[] ) {
fs::path path( fs::canonical( argv[0] ) );
fs::path file = path.parent_path() / "sound.wav";
std::cout << file << std::endl;
}
结果:
Program stdout
"/app/sound.wav"
代码:https://godbolt.org/z/K7PPchdjT
另一个解决方案是将文件合并到实际的可执行文件中。我在这里回答过类似的问题:
我正在用 Visual Studio 代码用 C++ 编写一个小游戏,以 CMake 作为构建系统。到目前为止,访问资源没有任何问题,但由于我决定通过在目录中组织它来整理我的项目,我的 GetTexture、GetSoundBuffer 和 GetFont 函数无法从 Resources 文件夹加载图像。
显然我知道在将文件保存在不同目录时,我必须更新路径。所以一开始是“Resources / image.png”变成了“../../../Resources/image.png”,(它对所有#include 指令都有效)但是当我 运行 游戏我只看到黑屏和控制台向我显示 无法加载图像“../../../Resources/image.png”之类的消息。原因:无法打开文件.
我一遍又一遍地尝试重新安排项目,但每次编译时都会发生这种情况。我对 CMake 了解不多,我不知道问题出在我的 CMakeLists.txt 文件还是我之前提到的函数,我怀疑它们之前工作得很好。
获取纹理:
sf::Texture& Game::GetTexture(std::string _fileName)
{
auto iter = textures.find(_fileName);
if (iter != textures.end())
{
return *iter->second;
}
TexturePtr texture = std::make_shared<sf::Texture>();
texture->loadFromFile(_fileName);
textures[_fileName] = texture;
return *texture;
}
GetSoundBuffer:
sf::SoundBuffer& Game::GetSoundBuffer(std::string _fileName)
{
auto iter = sounds.find(_fileName);
if (iter != sounds.end())
{
return *iter->second;
}
SoundBufferPtr sound = std::make_shared<sf::SoundBuffer>();
sound->loadFromFile(_fileName);
sounds[_fileName] = sound;
return *sound;
}
GetFont:
sf::Font& Game::GetFont(std::string _fileName)
{
auto iter = fonts.find(_fileName);
if (iter != fonts.end())
{
return *iter->second;
}
FontPtr font = std::make_shared<sf::Font>();
font->loadFromFile(_fileName);
fonts[_fileName] = font;
return *font;
}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.18)
set(PROJECT_NAME "MyGame")
project(MyGame)
set(SFML_DIR "${CMAKE_CURRENT_LIST_DIR}/libs/SFML-2.5.1/lib/cmake/SFML")
file(GLOB ALL_REQUIRED_DLL "libs/required_dlls/*.dll")
file(COPY ${ALL_REQUIRED_DLL} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
set(CMAKE_CXX_STANDARD 17)
set(SOURCE_FILES
...
${RES_FILES})
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
find_package(SFML 2.5.1 COMPONENTS system window graphics network audio REQUIRED)
target_link_libraries(${PROJECT_NAME} sfml-audio sfml-graphics sfml-window sfml-system)
项目组织结构如下:
Build:
(Cmake build stuff)
Engine:
(All engine codes, no problem here)
Scenes:
Scene1:
include:
(All .h files)
src:
(All .cpp files, here is where i call GetTexture, GetSoundBuffer
and GetFont)
Resources:
(All the images, sounds and fonts)
CMakeLists.txt
main.cpp
对于所有这些,值得一提的是我正在使用 Linux。
当您 运行 在另一个位置执行可执行文件时,相对路径将与编译时的路径不同。
一个解决方案是使所有内容都与可执行文件的位置相关,如:
namespace fs = std::filesystem;
int main( int argc, char* argv[] ) {
fs::path path( fs::canonical( argv[0] ) );
fs::path file = path.parent_path() / "sound.wav";
std::cout << file << std::endl;
}
结果:
Program stdout
"/app/sound.wav"
代码:https://godbolt.org/z/K7PPchdjT
另一个解决方案是将文件合并到实际的可执行文件中。我在这里回答过类似的问题: