diff --git a/TEST.txt b/TEST.txt index a6f203a..622a721 100644 --- a/TEST.txt +++ b/TEST.txt @@ -1,7 +1,7 @@ -Für einen automatisierten Test, führe das Programm mit dem Argument --test aus +Für einen automatisierten Test, führe das Programm mit dem Argument --test aus. Zum Spielen einfach ohne Parameter. asdddddddddddddddwwwwwwddddddwwwwdddd aaaaaaassssssddddssssdddddddddddwwwwwddddddwwwwdddddddddddddddddddd ddddddddddddddddddddddddddddddddddwwwwwdddddddddd aaddddddddddwwwwwwddddddddddddddddddddddd -ddddwwwwwwddddddddddddddddddddddddddddddddddddaaaaaaaaaaaaaaaaaaaaassssdddddddddddddddddddddddddddddddddddddddddddddddddwwwwwwddddddddddddddd \ No newline at end of file +ddddwwwwwwddddddddddddddddddddddddddddddddddddaaaaaaaaaaaaaaaaaaaaasssssdddddddddddddddddddddddddddddddddddddddddddddddddwwwwwwddddddddddddddd \ No newline at end of file diff --git a/blockRegistry.hpp b/blockRegistry.hpp index 5c3961f..34e1aae 100644 --- a/blockRegistry.hpp +++ b/blockRegistry.hpp @@ -32,6 +32,14 @@ public: registerBlock(SAND); } + /** + * Gets a block by its encoding. + * + * If the block is not registered, a non-solid decoration block is created for it. + * + * @param encoding The encoding of the block to get. + * @return The block with the given encoding. + */ const Block getByEncoding(char encoding) { for (Block block : registeredBlocks) { if (block.getEncoding() == encoding) return block; diff --git a/blockSettings.hpp b/blockSettings.hpp index 1d38947..25cc788 100644 --- a/blockSettings.hpp +++ b/blockSettings.hpp @@ -2,27 +2,78 @@ class BlockSettings { public: BlockSettings() {} + + /** + * Checks if the block is solid ground, meaning players and objects will + * not fall through. + * + * @return true if the block is solid, false otherwise. + */ bool isSolid() { return isSolid_; } + + /** + * Checks if the block has collision, disallowing players to pass through it. + * + * @return true if the block has collision, false otherwise. + */ bool hasCollision() { return hasCollision_; } + + /** + * Checks if the block is affected by gravity, meaning it will fall down + * until it reaches stable ground. + * + * @return true if the block is affected by gravity, false otherwise. + */ bool hasGravity() { return hasGravity_; } + + /** + * Checks if the block can be pushed by players. + * + * @return true if the block can be pushed, false otherwise. + */ bool isPushable() { return isPushable_; } + + /** + * Checks if the block is lethal to players, causing them to be killed instantly upon contact. + * + * @return true if the block is lethal, false otherwise. + */ bool isLethal() { return isLethal_; } + + /** + * Checks if the block is brittle, meaning it will fall or break + * when a player passes over it. + * + * @return true if the block is brittle, false otherwise. + */ bool isBrittle() { return isBrittle_; } + + /** + * Checks if the block is climbable from the top, allowing players above to climb down. + * + * @return true if the block is climbable from the top, false otherwise. + */ bool isClimbableFromTop() { return isClimbableFromTop_; } + + /** + * Checks if the block is climbable from the bottom, allowing players to climb up. + * + * @return true if the block is climbable from the bottom, false otherwise. + */ bool isClimbableFromBottom() { return isClimbableFromBottom_; } @@ -41,38 +92,83 @@ class BlockSettings { }; class BlockSettingsBuilder { public: + /** + * Marks the block non-solid, letting players and objects fall through. + * + * @return BlockSettingsBuilder with changed settings + */ BlockSettingsBuilder nonSolid() { blockSettings.isSolid_ = false; return *this; } + /** + * Makes the block pushable by players. + * + * @return BlockSettingsBuilder with changed settings + */ BlockSettingsBuilder pushable() { blockSettings.isPushable_ = true; return *this; } + /** + * Marks the block as collidable, disallowing players to pass through it. + * + * @return BlockSettingsBuilder with changed settings + */ BlockSettingsBuilder collidable() { blockSettings.hasCollision_ = true; return *this; } + /** + * Marks the block as affected by gravity, making it fall down until it reaches stable ground. + * + * @return BlockSettingsBuilder with changed settings + */ BlockSettingsBuilder gravity() { blockSettings.hasGravity_ = true; return *this; } + /** + * Makes the block lethal to players, killing them instantly if they touch it. + * + * @return BlockSettingsBuilder with changed settings + */ BlockSettingsBuilder lethal() { blockSettings.isLethal_ = true; return *this; } + /** + * Makes the block brittle, making it fall down when a player passes over it. + * + * @return BlockSettingsBuilder with changed settings + */ BlockSettingsBuilder brittle() { blockSettings.isBrittle_ = true; return *this; } + /** + * Marks the block as climbable from the top, allowing players above to climb down. + * + * @return BlockSettingsBuilder with changed settings + */ BlockSettingsBuilder climbableFromTop() { blockSettings.isClimbableFromTop_ = true; return *this; } + /** + * Marks the block as climbable from the bottom, allowing players below to climb up. + * + * @return BlockSettingsBuilder with changed settings + */ BlockSettingsBuilder climbableFromBottom() { blockSettings.isClimbableFromBottom_ = true; return *this; } + /** + * Returns the built BlockSettings object. + * + * @return BlockSettings object with the set properties + */ BlockSettings build() { return blockSettings; } diff --git a/fileutils.hpp b/fileutils.hpp index d2bef13..6b66f5b 100644 --- a/fileutils.hpp +++ b/fileutils.hpp @@ -1,10 +1,8 @@ #pragma once -#include #include #include #include -#include #include #include @@ -16,21 +14,6 @@ using std::endl; using std::string; using std::vector; -string readInput(string feedback); - -/** - * Reads a string from the user. The string is expected to be the first - * argument before a comma. - * - * @return The string read from the user. - */ -string readInput(string feedback) { - string name; - cout << feedback << endl; - getline(std::cin, name); - return name; -} - /** * Get a list of all files in the specified directory, sorted alphabetically. * @@ -38,11 +21,11 @@ string readInput(string feedback) { * * @param dir The directory to get the file names from * @param extension The file extension to filter by - * @return A list of all file names in the specified directory, sorted alphabetically. + * @return A list of all filtered file names in the specified directory, sorted alphabetically. */ vector getOrderedFileNames(string dir, string extension) { vector worlds; - // This used to be so elegant and iterate over all files in the worlds directory, + // This used to be elegant and iterate over all files in the worlds directory, // but because of the weird restriction with no folders being allowed, we just filter the files based on their extension. for (auto & entry : std::filesystem::directory_iterator(dir)) { if (static_cast(entry.path()).ends_with(extension)) worlds.push_back(entry.path()); @@ -62,22 +45,10 @@ vector getOrderedFileNames(string dir, string extension) { * @return The content of the file as a vector of strings. */ vector readFileAsVector(const string& fileLocation) { - - vector lines; - // string currentLine = ""; - // for (char c : readFile(fileLocation)) { - // if (c == '\n' || c == '\r') { - // file.push_back(currentLine); - // currentLine = ""; - // } - // else { - // currentLine += c; - // } - // } - // file.push_back(currentLine); + vector lines; std::ifstream file(fileLocation); - // Read the file line by line into a string + // Read the file line by line string line; while (std::getline(file, line)) { lines.push_back(line); @@ -87,7 +58,8 @@ vector readFileAsVector(const string& fileLocation) { } /** - * Prints the content of a file line by line into the console (in the specified color). + * Prints the content of a file into the console line by line. + * * We use this to print our death and victory screens. * * @param fileLocation Path to the file to be printed. diff --git a/help.screen.txt b/help.screen.txt index 72a17b4..b21350d 100644 --- a/help.screen.txt +++ b/help.screen.txt @@ -2,4 +2,5 @@ Welcome to Adventura v1.0 by Martin Prokoph! No Arguments: Play through all levels inside the world folder (in alphabetical order) --level, -l : Load (only) the specified level +--test, -t: Automatically play through all levels --help, -h: Show this screen \ No newline at end of file diff --git a/main.cpp b/main.cpp index 29bb5f1..d58f839 100644 --- a/main.cpp +++ b/main.cpp @@ -15,6 +15,7 @@ using std::cout; using std::endl; bool startWorld(string worldFile); +bool parseArgs(int argc, char *argv[]); bool testMode = false; unsigned int worldIndex = 2; @@ -27,27 +28,8 @@ unsigned int worldIndex = 2; * If the player reaches the goal of the final level, print the victory screen and exit. */ int main(int argc, char *argv[]) { - if (argc > 1) { - for (int i = 1; i < argc; i++) { - string arg = string(argv[i]); - if (arg == "-h" || arg == "--help") - break; - else if (arg == "-t" || arg == "--test") - testMode = true; - - else if ((arg == "-l" || arg == "--level") && argc > i + 1) { - if (!startWorld("./worlds/" + string(argv[i+1]))) - return 0; // Load only the specified world - else - printFile("./completed_single_level.screen.txt", Color::BRIGHT_GREEN); - return 0; - } - } - if (!testMode) { - printFile("./help.screen.txt", Color::BRIGHT_BLUE); // Print help screen - return 0; - } - } + if (parseArgs(argc, argv)) return 0; + if (!testMode) { printFile("./start.screen.txt", Color::BRIGHT_YELLOW); waitForInput(); @@ -83,4 +65,44 @@ bool startWorld(string worldFile) { worldIndex++; if (!player.isAlive()) printFile("./death.screen.txt", Color::BRIGHT_RED); return player.hasReachedGoal(); +} + +/** + * Parses command-line arguments to set the game's configuration. + * + * Recognizes the following arguments: + * - "-h" or "--help": Displays the help screen and exits. + * - "-t" or "--test": Enables test mode, starting an automated playthrough. + * - "-l" or "--level ": Loads and plays only the specified level. + * + * If a custom action is specified, the function returns true to indicate + * immediate termination after executing the requested action. + * + * @param argc The number of command-line arguments. + * @param argv The array containing the command-line arguments. + * @return true if the program should exit after handling the arguments, false otherwise. + */ +bool parseArgs(int argc, char *argv[]) { + if (argc > 1) { + for (int i = 1; i < argc; i++) { + string arg = string(argv[i]); + if (arg == "-h" || arg == "--help") + break; + else if (arg == "-t" || arg == "--test") + testMode = true; + + else if ((arg == "-l" || arg == "--level") && argc > i + 1) { + if (!startWorld("./" + string(argv[i+1]))) + return true; // Load only the specified world + else + printFile("./completed_single_level.screen.txt", Color::BRIGHT_GREEN); + return true; + } + } + if (!testMode) { + printFile("./help.screen.txt", Color::BRIGHT_BLUE); // Print help screen + return true; + } + } + return false; } \ No newline at end of file diff --git a/movementHandler.hpp b/movementHandler.hpp index d64b595..b8629c7 100644 --- a/movementHandler.hpp +++ b/movementHandler.hpp @@ -27,7 +27,7 @@ bool is_in(First &&first, T && ... t) { } /** - * Waits until the user enters a key. + * Waits until the user enters a valid key. * Used to prompt the user to press any key to continue. */ void waitForInput() { diff --git a/output.hpp b/output.hpp index 0a2c2cf..dad7010 100644 --- a/output.hpp +++ b/output.hpp @@ -80,4 +80,5 @@ void printGuide() { for (std::pair p : guide) { cout << p.second << p.first << endl; } + cout << endl << Color::RESET << "WASD + Enter -> Spiel starten" << endl; } \ No newline at end of file