diff --git a/CMakeLists.txt b/CMakeLists.txt index c6e058a..7ae932d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ include_directories( src include "${PROJECT_BINARY_DIR}" + lib/physfs-2.0.3 ) configure_file( @@ -22,6 +23,8 @@ configure_file( "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.h" ) +add_subdirectory(lib/physfs-2.0.3) + add_executable(${PROJECT_NAME} src/main.cpp src/texture.cpp @@ -31,9 +34,10 @@ add_executable(${PROJECT_NAME} src/gamebase.cpp src/character.cpp src/placeable.cpp - src/path.cpp + src/physicsfswrapper.cpp ) target_link_libraries(${PROJECT_NAME} ${SDL2_LIBRARIES} + physfs ) diff --git a/src/character.cpp b/src/character.cpp index 52afc89..632d234 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -11,6 +11,14 @@ namespace cloonel { { } + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + Character::Character (const std::string&& parPath, SDLMain* parMain) : + Placeable(0.0f, 0.0f), + m_texture(new Texture(parPath, parMain, false)) + { + } + ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- Character::~Character() noexcept { diff --git a/src/character.hpp b/src/character.hpp index 1543152..6fd2a8a 100644 --- a/src/character.hpp +++ b/src/character.hpp @@ -13,6 +13,7 @@ namespace cloonel { class Character : public Placeable { public: Character ( const std::string& parPath, SDLMain* parMain ); + Character ( const std::string&& parPath, SDLMain* parMain ); ~Character ( void ) noexcept; void Prepare ( void ); diff --git a/src/game.cpp b/src/game.cpp index 4981430..137d85f 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -3,14 +3,14 @@ namespace cloonel { namespace { - const char g_characterTexture[] = "resources/graphics/duck.bmp"; + const char g_characterTexture[] = "/resources/graphics/duck.bmp"; } //unnamed namespace ///------------------------------------------------------------------------ ///------------------------------------------------------------------------ - Game::Game (SDLMain* parSdlMain, const char* parBasePath) : - GameBase(parSdlMain, parBasePath), - m_character(new Character(m_path.GetFullPath(g_characterTexture), parSdlMain)) + Game::Game (SDLMain* parSdlMain) : + GameBase(parSdlMain), + m_character(new Character(g_characterTexture, parSdlMain)) { } diff --git a/src/game.hpp b/src/game.hpp index 685b4d5..bdbac17 100644 --- a/src/game.hpp +++ b/src/game.hpp @@ -10,7 +10,7 @@ namespace cloonel { class Game : public GameBase { public: - Game ( SDLMain* parSdlMain, const char* parBasePath ); + explicit Game ( SDLMain* parSdlMain ); virtual ~Game ( void ) noexcept; virtual void Prepare ( void ); diff --git a/src/gamebase.cpp b/src/gamebase.cpp index 510ea75..0fd9b20 100644 --- a/src/gamebase.cpp +++ b/src/gamebase.cpp @@ -23,8 +23,7 @@ namespace cloonel { ///------------------------------------------------------------------------ ///------------------------------------------------------------------------ - GameBase::GameBase (SDLMain* parSdlMain, const char* parBasePath) : - m_path(parBasePath), + GameBase::GameBase (SDLMain* parSdlMain) : m_sdlmain(parSdlMain), m_time0(SDL_GetTicks()), m_wantsToQuit(false) diff --git a/src/gamebase.hpp b/src/gamebase.hpp index 17df130..68cea7d 100644 --- a/src/gamebase.hpp +++ b/src/gamebase.hpp @@ -1,7 +1,6 @@ #ifndef id8C7FE975525B4329BFBEAF364D934EAD #define id8C7FE975525B4329BFBEAF364D934EAD -#include "path.hpp" #include namespace cloonel { @@ -14,14 +13,12 @@ namespace cloonel { bool WantsToQuit ( void ) const; protected: - GameBase ( SDLMain* parSdlMain, const char* parBasePath ); + explicit GameBase ( SDLMain* parSdlMain ); virtual ~GameBase ( void ) noexcept; virtual void Prepare ( void ) = 0; virtual void Destroy ( void ) noexcept = 0; - const Path m_path; - private: virtual void OnRender ( void ) = 0; virtual void OnUpdate ( float parDelta ) = 0; diff --git a/src/main.cpp b/src/main.cpp index e944d45..753b0ac 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ #include "CloonelJumpConfig.h" #include "sdlmain.hpp" #include "game.hpp" +#include "physicsfswrapper.hpp" #include #include #include @@ -20,22 +21,31 @@ namespace { ///---------------------------------------------------------------------------- ///following http://twinklebeardev.blogspot.co.uk/2012/07/lesson-1-hello-world.html ///---------------------------------------------------------------------------- -int main() { +int main (int parArgc, char* parArgv[]) { std::cout << GameName << " v" << GameVersionMajor << "." << GameVersionMinor << std::endl; + int retVal = 0; cloonel::SDLMain sdlmain(GameName, DEF_WIN_WIDTH, DEF_WIN_HEIGHT); try { +#if defined(NDEBUG) + cloonel::PhysicsFSWrapper physfs(parArgc[0]); +#else + cloonel::PhysicsFSWrapper physfs(GAME_BASE_PATH); +#endif + physfs.Append("resources", "resources"); + sdlmain.Init(); + + cloonel::Game game(&sdlmain); + game.Prepare(); + RunMainLoop(game); } catch (const std::runtime_error& e) { std::cerr << "Error during SDL2 initialization:\n"; std::cerr << e.what() << std::endl; + retVal = 1; } - cloonel::Game game(&sdlmain, GAME_BASE_PATH); - game.Prepare(); - RunMainLoop(game); - std::cout << "Quitting now" << std::endl; - return 0; + return retVal; } diff --git a/src/path.cpp b/src/path.cpp deleted file mode 100644 index 2ba9257..0000000 --- a/src/path.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "path.hpp" -#include -#include -#include - -namespace cloonel { - namespace { - ///--------------------------------------------------------------------- - ///--------------------------------------------------------------------- - std::string GetCleanBasePath (const std::string&& parPath) { - const size_t pathlen = parPath.size(); - switch (pathlen) { - case 0: - return std::string("/"); - case 1: - return parPath; - default: - if (parPath[pathlen - 1] == '/') - return parPath.substr(0, pathlen - 1); - else - return parPath; - } - } - } //unnamed namespace - - ///------------------------------------------------------------------------- - ///------------------------------------------------------------------------- - Path::Path (const char* parBasePath) : - m_basePath(GetCleanBasePath(std::string(parBasePath))) - { - } - - ///------------------------------------------------------------------------- - ///------------------------------------------------------------------------- - std::string Path::GetFullPath (const std::string& parPath) const { - std::ostringstream oss; - oss << m_basePath << '/' << parPath; - return oss.str(); - } - - ///------------------------------------------------------------------------- - ///------------------------------------------------------------------------- - std::string Path::GetFullPath (const char* parPath) const { - assert(parPath); - std::ostringstream oss; - oss << m_basePath << '/' << parPath; - return oss.str(); - } -} // namespace cloonel diff --git a/src/path.hpp b/src/path.hpp deleted file mode 100644 index 2bde7a8..0000000 --- a/src/path.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef id6B8B06CEFCED4E48A76E27CE5D65052F -#define id6B8B06CEFCED4E48A76E27CE5D65052F - -#include - -namespace cloonel { - class Path { - public: - explicit Path ( const char* parBasePath ); - ~Path ( void ) noexcept = default; - - std::string GetFullPath ( const std::string& parPath ) const; - std::string GetFullPath ( const char* parPath ) const; - - private: - const std::string m_basePath; - }; -} //namespace cloonel - -#endif diff --git a/src/physicsfswrapper.cpp b/src/physicsfswrapper.cpp new file mode 100644 index 0000000..eca7a79 --- /dev/null +++ b/src/physicsfswrapper.cpp @@ -0,0 +1,128 @@ +#include "physicsfswrapper.hpp" +#include "physfs.h" +#include +#include +#include +#include + +namespace cloonel { + namespace { + ///--------------------------------------------------------------------- + ///--------------------------------------------------------------------- + PHYSFS_File* OpenPhysFSFile (const char* parPath, PhysycsFSFile::OpenMode parMode) { + switch (parMode) { + case PhysycsFSFile::OpenMode_Read: + return PHYSFS_openRead(parPath); + case PhysycsFSFile::OpenMode_Write: + return PHYSFS_openWrite(parPath); + case PhysycsFSFile::OpenMode_Append: + return PHYSFS_openAppend(parPath); + default: + return nullptr; + } + } + } //unnamed namespace + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + PhysicsFSWrapper::PhysicsFSWrapper (const char* parBasePath) { + if (not PHYSFS_init(parBasePath)) { + std::ostringstream oss; + oss << "Error during PhysicsFS initialization: " << PHYSFS_getLastError(); + throw std::runtime_error(oss.str()); + } + } + + ///------------------------------------------------------------------------- + ///Note that the deinit function could fail, but since we're in a dtor we + ///are not checking in its return value as we can't throw anyways. + ///------------------------------------------------------------------------- + PhysicsFSWrapper::~PhysicsFSWrapper() noexcept { + const bool succeeded = static_cast(PHYSFS_deinit()); + assert(succeeded); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + void PhysicsFSWrapper::Append (const char* parRelativePath, const char* parMountPoint) { + assert(parRelativePath); + assert(parMountPoint); + if (not PHYSFS_mount(parRelativePath, parMountPoint, 1)) { + std::ostringstream oss; + oss << "Error while adding \"" << parRelativePath << + "\" to PhysicsFS' mount point \"" << parMountPoint << "\": "; + oss << PHYSFS_getLastError(); + throw std::runtime_error(oss.str()); + } + } + + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + PhysycsFSFile::PhysycsFSFile (const char* parPath, OpenMode parMode, bool parBuffered, const char* parDescCategory) : + m_handle(OpenPhysFSFile(parPath, parMode)) + { + if (not m_handle) { + std::ostringstream oss; + oss << "Error opening " << parDescCategory << " file: \"" << + oss << parPath << "\": "; + oss << PHYSFS_getLastError(); + throw std::runtime_error(oss.str()); + } + + if (parBuffered) { + //TODO: try to guess a buffer size + PHYSFS_setBuffer(static_cast(m_handle), 1024); + } + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + PhysycsFSFile::~PhysycsFSFile() noexcept { + if (IsOpen()) { + PHYSFS_close(static_cast(m_handle)); + } + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + bool PhysycsFSFile::IsOpen() const noexcept { + return (m_handle != nullptr); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + int64_t PhysycsFSFile::Read (void* parBuff, uint32_t parSize, uint32_t parCount) { + return PHYSFS_read(static_cast(m_handle), parBuff, parSize, parCount); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + int64_t PhysycsFSFile::Write (void* parBuff, uint32_t parSize, uint32_t parCount) { + return PHYSFS_write(static_cast(m_handle), parBuff, parSize, parCount); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + bool PhysycsFSFile::IsEof() const noexcept { + return PHYSFS_eof(static_cast(const_cast(m_handle))); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + int64_t PhysycsFSFile::Tell() const { + return PHYSFS_tell(static_cast(const_cast(m_handle))); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + int PhysycsFSFile::Seek (uint64_t parPos) { + return PHYSFS_seek(static_cast(m_handle), parPos); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + void PhysycsFSFile::Flush() noexcept { + PHYSFS_flush(static_cast(m_handle)); + } +} //namespace cloonel diff --git a/src/physicsfswrapper.hpp b/src/physicsfswrapper.hpp new file mode 100644 index 0000000..9ae766f --- /dev/null +++ b/src/physicsfswrapper.hpp @@ -0,0 +1,38 @@ +#ifndef idC54817CCCC0F454F931AE9082DFE9FDA +#define idC54817CCCC0F454F931AE9082DFE9FDA + +#include + +namespace cloonel { + class PhysicsFSWrapper { + public: + explicit PhysicsFSWrapper ( const char* parBasePath ); + ~PhysicsFSWrapper ( void ) noexcept; + + void Append ( const char* parRelativePath, const char* parMountPoint ); + }; + + class PhysycsFSFile { + public: + enum OpenMode { + OpenMode_Read, + OpenMode_Write, + OpenMode_Append + }; + + PhysycsFSFile ( const char* parPath, OpenMode parMode, bool parBuffered, const char* parDescCategory ); + ~PhysycsFSFile ( void ) noexcept; + + bool IsOpen ( void ) const noexcept; + int64_t Read ( void* parBuff, uint32_t parSize, uint32_t parCount ); + int64_t Write ( void* parBuff, uint32_t parSize, uint32_t parCount ); + bool IsEof ( void ) const noexcept; + int64_t Tell ( void ) const; + int Seek ( uint64_t parPos ); + void Flush ( void ) noexcept; + + private: + void* const m_handle; + }; +} // namespace cloonel +#endif diff --git a/src/texture.cpp b/src/texture.cpp index 164ebda..4567845 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -1,11 +1,22 @@ #include "texture.hpp" #include "sdlerror.hpp" #include "sdlmain.hpp" +#include "physicsfswrapper.hpp" #include #include #include +#include namespace cloonel { + namespace { + ///--------------------------------------------------------------------- + ///--------------------------------------------------------------------- + SDL_Surface* LoadNewSurface (const std::string& parPath) { + assert(false); + return nullptr; + } + } //unnamed namespace + ///------------------------------------------------------------------------ ///------------------------------------------------------------------------ Texture::Texture (const std::string& parPath, SDLMain* parMain, bool parLoadNow) :