diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d9b1ab..7040175 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 4.2) project(Text-Adventure) -set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp) +set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ui/window.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Common/fileCommon.cpp) find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3-shared) find_package(SDL3_ttf REQUIRED) @@ -16,4 +16,4 @@ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Editor) #add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/) target_link_libraries(Text-Adventure PUBLIC Engine SDL3::SDL3 SDL3_ttf::SDL3_ttf) -target_include_directories(Text-Adventure PUBLIC ${CMAKE_SOURCE_DIR}/Extern) +target_include_directories(Text-Adventure PUBLIC ${CMAKE_SOURCE_DIR}/Extern ${CMAKE_SOURCE_DIR}/ui ${CMAKE_SOURCE_DIR}/Common) diff --git a/Common/fileCommon.cpp b/Common/fileCommon.cpp new file mode 100644 index 0000000..ccf66c7 --- /dev/null +++ b/Common/fileCommon.cpp @@ -0,0 +1,44 @@ +#include "fileCommon.h" +#include "json.hpp" + + +bool OpenFile(fs::path path) { + path = fs::absolute(path); + + if (!fs::exists(path)) { + printf("File Read error! Could not find file at: \n"); + printf("%s\n", path.c_str()); + return false; + } + + stream.open(absolute(path)); + if (!stream) { + printf("Error opening stream \n"); + return false; + } + + return true; +} + + +nlohmann::json GetData() { + if (!stream) { + printf("Open the file first! \n"); + return nlohmann::json(); + } + + return nlohmann::json::parse(stream); +} + +bool SaveJsonFile(fs::path path, nlohmann::json j) { + + if (stream) { + printf("Stream open for reading! Please close stream before saving \n"); + return false; + } + + stream.open(absolute(path), std::fstream::in | std::fstream::out | std::fstream::app); + stream << std::setw(4) << j << std::endl; + + stream.close(); +} diff --git a/Common/fileCommon.h b/Common/fileCommon.h new file mode 100644 index 0000000..b801893 --- /dev/null +++ b/Common/fileCommon.h @@ -0,0 +1,14 @@ +#include +#include +#include "json.hpp" + +namespace fs = std::filesystem; + +static std::fstream stream; + +extern bool OpenFile(fs::path path); +extern nlohmann::json GetData(); +/// Note we have a specific function for json for pretty printing purpose +bool SaveJsonFile(fs::path path, nlohmann::json j); +// bool SaveFile(fs::path path, void *dataToSave); // Leaving it commented out until later +inline void CloseFileStream() { stream.close(); } diff --git a/Engine/CMakeLists.txt b/Engine/CMakeLists.txt index 0310a87..df6afe7 100644 --- a/Engine/CMakeLists.txt +++ b/Engine/CMakeLists.txt @@ -12,4 +12,4 @@ set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/room.cpp add_library(Engine SHARED ${SOURCES}) target_include_directories(Engine PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/headers) -target_include_directories(Engine PUBLIC ${CMAKE_SOURCE_DIR}/Extern) +target_include_directories(Engine PUBLIC ${CMAKE_SOURCE_DIR}/Extern ${CMAKE_SOURCE_DIR}/Common) diff --git a/Engine/src/CommandParser.cpp b/Engine/src/CommandParser.cpp index 7865c47..8462223 100644 --- a/Engine/src/CommandParser.cpp +++ b/Engine/src/CommandParser.cpp @@ -50,39 +50,39 @@ int CommandParser::Parse() { FUNCTION toRun; - printf("Please Enter a command \n"); - printf("> "); - getline(std::cin, cmd); - std::cin.clear(); - cmd[0] = toupper(cmd[0]); - std::stringstream c(cmd); + /* + printf("Please Enter a command \n"); + printf("> "); - verbs = Verb(c); - nouns = Noun(c); + cmd[0] = toupper(cmd[0]); + std::stringstream c(cmd); - for (const auto &verb: verbs) { - if (!commands[verb]) { - CommandUnrecognized(); - break; + verbs = Verb(c); + nouns = Noun(c); + + for (const auto &verb: verbs) { + if (!commands[verb]) { + CommandUnrecognized(); + break; + } + + for (const auto &n: nouns) { + noun = n; + } + + toRun = commands[verb]; } - for (const auto &n: nouns) { - noun = n; + if (toRun) { + toRun(noun); } - - toRun = commands[verb]; - } + cmd.clear(); + word.clear(); + verbs.clear(); + nouns.clear(); + c.clear(); - if (toRun) { - toRun(noun); - } - cmd.clear(); - word.clear(); - verbs.clear(); - nouns.clear(); - c.clear(); - - toRun = nullptr; + toRun = nullptr;*/ return 0; } diff --git a/Engine/src/game.cpp b/Engine/src/game.cpp index 5636a3f..683cce3 100644 --- a/Engine/src/game.cpp +++ b/Engine/src/game.cpp @@ -1,7 +1,7 @@ #include "game.h" #include #include -#include +#include "fileCommon.h" #include "player.h" std::vector> rooms; @@ -21,38 +21,30 @@ bool Game::Init() { rooms[i].resize(MAP_WIDTH); } - filePath = fs::absolute(filePath); - - if (!fs::exists(filePath)) { - printf("File Read error! Could not find Json at: \n"); - printf("%s", filePath.c_str()); - isActive = false; - return false; - } - - - // Read rooms into buffer - stream.open(absolute(filePath)); - json = nlohmann::json::parse(stream); + isActive = OpenFile(filePath); + json = GetData(); + isActive = (json != NULL); rooms = json.get>>(); player.Init(); - parser = CommandParser(); + CloseFileStream(); // We're done with it. Let's make sure it's closed! + + parser = CommandParser(); parser.AddCommand("Exit", Quit); parser.AddCommand("Move", Move); parser.AddCommand("Look", Look); ChangeRoom(rooms[0][0]); - return true; + return isActive; } void Game::Run() { - parser.Parse(); - // Process game logic in here + parser.Parse(); + // Process game logic in here } bool Game::Save() { return false; } diff --git a/Resources/Pixelzone-E4MV4.ttf b/Resources/Pixelzone-E4MV4.ttf new file mode 100644 index 0000000..4cacfa8 Binary files /dev/null and b/Resources/Pixelzone-E4MV4.ttf differ diff --git a/Resources/Rooms.json b/Resources/Rooms.json index 04baad9..1eddacd 100644 --- a/Resources/Rooms.json +++ b/Resources/Rooms.json @@ -1,101 +1,101 @@ [ - [ - { - "description": "First Test Room", - "exits": [ + [ { - "dir": 1, - "exitID": 0, - "isLocked": false + "description": "First Test Room", + "exits": [ + { + "dir": 1, + "exitID": 0, + "isLocked": false + }, + { + "dir": 2, + "exitID": 1, + "isLocked": false + } + ], + "id": 0, + "name": "Test Room 1", + "scenery": [ + { + "canTake": false, + "description": "A Grey Rock", + "id": 0, + "keywords": [ + "Rock" + ], + "name": "Rock", + "roomIdItBelongsTo": 0, + "type": 1 + } + ] }, { - "dir": 2, - "exitID": 1, - "isLocked": false + "description": "A court yard", + "exits": [ + { + "dir": 3, + "exitID": 2, + "isLocked": false + }, + { + "dir": 2, + "exitID": 3, + "isLocked": false + }, + { + "dir": 1, + "exitID": 4, + "isLocked": false + } + ], + "id": 1, + "name": "Test Room 2", + "scenery": [ + { + "canTake": false, + "description": "A fine looking Tree stands in the courtyard", + "id": 1, + "keywords": [ + "Tree" + ], + "name": "Tree", + "roomIdItBelongsTo": 1, + "type": 1 + } + ] } - ], - "id": 0, - "name": "Test Room 1", - "scenery": [ + ], + [ { - "canTake": false, - "description": "A Grey Rock", - "id": 0, - "keywords": [ - "Rock" - ], - "name": "Rock", - "roomIdItBelongsTo": 0, - "type": 1 + "description": "You can hear the sound of a waterfall nearby", + "exits": [ + { + "dir": 0, + "exitID": 5, + "isLocked": false + }, + { + "dir": 2, + "exitID": 6, + "isLocked": false + } + ], + "id": 3, + "name": "Test Room 3", + "scenery": [ + { + "canTake": false, + "description": "A fine waterfall on a cliff", + "id": 3, + "keywords": [ + "Waterfall" + ], + "name": "Waterfall", + "roomIdItBelongsTo": 3, + "type": 1 + } + ] } - ] - }, - { - "description": "A court yard", - "exits": [ - { - "dir": 3, - "exitID": 2, - "isLocked": false - }, - { - "dir": 2, - "exitID": 3, - "isLocked": false - }, - { - "dir": 1, - "exitID": 4, - "isLocked": false - } - ], - "id": 1, - "name": "Test Room 2", - "scenery": [ - { - "canTake": false, - "description": "A fine looking Tree stands in the courtyard", - "id": 1, - "keywords": [ - "Tree" - ], - "name": "Tree", - "roomIdItBelongsTo": 1, - "type": 1 - } - ] - } - ], - [ - { - "description": "You can hear the sound of a waterfall nearby", - "exits": [ - { - "dir": 0, - "exitID": 5, - "isLocked": false - }, - { - "dir": 2, - "exitID": 6, - "isLocked": false - } - ], - "id": 3, - "name": "Test Room 3", - "scenery": [ - { - "canTake": false, - "description": "A fine waterfall on a cliff", - "id": 3, - "keywords": [ - "Waterfall" - ], - "name": "Waterfall", - "roomIdItBelongsTo": 3, - "type": 1 - } - ] - } - ] + ] ] diff --git a/main.cpp b/main.cpp index 340a362..30bd6ba 100644 --- a/main.cpp +++ b/main.cpp @@ -1,16 +1,21 @@ +#include +#include +#include +#include +#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ + #include #include #include #include #include #include +#include "fileCommon.h" #include "game.h" +#include "window.h" -/* We will use this renderer to draw into this window every frame. */ -static SDL_Window *window = nullptr; -static SDL_Renderer *renderer = nullptr; -static int width = 800, height = 600; -static Game game; +Game game; +Window window; void EditRooms() { @@ -47,78 +52,79 @@ void EditRooms() { {{3, "Waterfall", "A fine waterfall on a cliff", {"Waterfall"}, ObjectType::SCENERY, false, 3}}}}}; nlohmann::json j(roomDat); - - std::fstream outFile(absolute(path), std::fstream::in | std::fstream::out | std::fstream::app); - outFile << std::setw(4) << j << std::endl; - - outFile.close(); + SaveJsonFile(path, j); } -int Init() -{ +SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) { if (SDL_Init(SDL_INIT_VIDEO) == false) { SDL_Log("SDL could not initialize! SDL error: %s\n", SDL_GetError()); } - TTF_Init(); + SDL_AppResult result = window.CreateWindow(600, 800); - window = SDL_CreateWindow("Text Adventure", width, height, 0); - - if (window == nullptr) { - SDL_Log("SDL_CreateWindow Error: %s\n", SDL_GetError()); - SDL_Quit(); - return -1; + if (result != SDL_APP_CONTINUE) { + return result; } - renderer = SDL_CreateRenderer(window, nullptr); - if (renderer == nullptr) { - SDL_Log("SDL_CreateRenderer Error: %s\n", SDL_GetError()); - SDL_Quit(); - return -1; + if (!TTF_Init()) { + SDL_Log("Couldn't initialize SDL_ttf: %s\n", SDL_GetError()); + return SDL_APP_FAILURE; } + if (!game) { game.Init(); Game::SetGameInstance(&game); - } - else { + game.SetIsActive(true); + SDL_StartTextInput(window.GetWindow()); + } else { printf("Game Initalization failed! \n"); - return -1; + return SDL_APP_FAILURE; } - return 1; + return SDL_APP_CONTINUE; } +SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) { + if (event->type == SDL_EVENT_QUIT || !game.GetIsActive()) { + return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ + } -int main(int argc, char *argv[]) { - - SDL_Event e; - - game.SetIsActive(Init()); - - while (game.GetIsActive()) { - while (SDL_PollEvent(&e)) { - if (e.type == SDL_EVENT_QUIT) { - game.SetIsActive(false); - } + if (event->type == SDL_EVENT_KEY_DOWN) { + if (event->key.key == SDLK_ESCAPE) { + SDL_StopTextInput(window.GetWindow()); + game.SetIsActive(false); } - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // Set render draw color to black - SDL_RenderClear(renderer); // Clear the renderer - - SDL_RenderPresent(renderer); // Render the screen - - //game.Run(); - + if (event->key.key == SDLK_RETURN) { + SDL_StopTextInput(window.GetWindow()); + } } - return 0; + + if (event->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) { + window.Resize(event->window.data1, event->window.data2); + } + + return SDL_APP_CONTINUE; } +SDL_AppResult SDL_AppIterate(void *appstate) { + if (game.GetIsActive()) { -void Close() -{ - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); - SDL_Quit(); -} \ No newline at end of file + SDL_SetRenderDrawColor(window.GetRenderer(), 0, 0, 0, 255); // Set render draw color to black + SDL_RenderClear(window.GetRenderer()); // Clear the renderer + SDL_RenderPresent(window.GetRenderer()); // Render the screen + + // game.Run(); + } + + return SDL_APP_CONTINUE; +} + +void SDL_AppQuit(void *appstate, SDL_AppResult result) { + if (result == SDL_APP_SUCCESS) { + window.Close(); + SDL_Quit(); + } +} diff --git a/ui/window.cpp b/ui/window.cpp new file mode 100644 index 0000000..02e2c74 --- /dev/null +++ b/ui/window.cpp @@ -0,0 +1,40 @@ +#include "window.h" +#include +#include +#include + + +SDL_AppResult Window::CreateWindow(int height, int width) { + w = width; + h = height; + + SDL_SetHint(SDL_HINT_MAIN_CALLBACK_RATE, "60"); + + window = SDL_CreateWindow("Text Adventure", width, height, SDL_WINDOW_RESIZABLE); + + if (window == nullptr) { + SDL_Log("SDL_CreateWindow Error: %s\n", SDL_GetError()); + SDL_Quit(); + return SDL_APP_FAILURE; + } + + renderer = SDL_CreateRenderer(window, nullptr); + if (renderer == nullptr) { + SDL_Log("SDL_CreateRenderer Error: %s\n", SDL_GetError()); + SDL_Quit(); + return SDL_APP_FAILURE; + } + + return SDL_APP_CONTINUE; +} + +void Window::Resize(int width, int height) { + w = width; + h = height; + SDL_SetWindowSize(window, w, h); +} + +void Window::Close() { + SDL_DestroyWindow(window); + SDL_DestroyRenderer(renderer); +} diff --git a/ui/window.h b/ui/window.h new file mode 100644 index 0000000..2fcc62a --- /dev/null +++ b/ui/window.h @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +class Window { +private: + SDL_Window *window = nullptr; + SDL_Renderer *renderer = nullptr; + int w, h; + +public: + SDL_AppResult CreateWindow(int w, int h); + void Resize(int w, int h); + void Close(); + + SDL_Window *GetWindow() { return window; } + SDL_Renderer *GetRenderer() { return renderer; } +}; + + +extern Window window;