diff --git a/COMPILE.txt b/COMPILE.txt index 174c397..29720f1 100644 --- a/COMPILE.txt +++ b/COMPILE.txt @@ -1 +1,5 @@ -g++ -std=c++23 -Wall ./main.cpp -o ./adventura && ./adventura \ No newline at end of file +g++ -std=c++23 -Wall main.cpp -o adventura +ODER +clang++ -std=c++23 -Weverything -Wno-c++98-compat -Wno-padded -Wall main.cpp -o adventura + +Ausführen mit: ./adventura \ No newline at end of file diff --git a/TEST.txt b/TEST.txt index 622a721..e3bd3ea 100644 --- a/TEST.txt +++ b/TEST.txt @@ -1,4 +1,4 @@ -Für einen automatisierten Test, führe das Programm mit dem Argument --test aus. Zum Spielen einfach ohne Parameter. +Für einen automatisierten Test, führe das Programm mit dem Argument --test aus. Zum Spielen einfach ohne Parameter. Die untenstehenden Eingaben sind eine mögliche Kombination zum durchspielen – jede Zeile steht dabei für ein Level. asdddddddddddddddwwwwwwddddddwwwwdddd aaaaaaassssssddddssssdddddddddddwwwwwddddddwwwwdddddddddddddddddddd diff --git a/adventura b/adventura index edc148b..9d77931 100755 Binary files a/adventura and b/adventura differ diff --git a/block.hpp b/block.hpp index 5679c19..a8c78ee 100644 --- a/block.hpp +++ b/block.hpp @@ -5,10 +5,10 @@ class Block { private: - Identifier id = Identifier("adventure", "missing"); - char encoding; - Color color; - BlockSettings settings; + Identifier id_ = Identifier("adventure", "missing"); + char encoding_; + Color color_; + BlockSettings settings_; public: /** @@ -18,7 +18,7 @@ public: * @param encoding The encoding of the block, which is the character used to represent it in the game world. * @param settings The settings of the block, which define how the block behaves in the game world. */ - Block(Identifier id, char encoding, BlockSettings settings) : Block(id, encoding, Color::RESET, settings) {}; + Block(Identifier id, char encoding, BlockSettings settings) : Block(id, encoding, Color::RESET, settings) {} /** * Constructs a block with the given identifier, encoding, color and settings. * @@ -28,11 +28,11 @@ public: * @param settings The settings of the block, which define how the block behaves in the game world. */ Block(Identifier id, char encoding, Color color, BlockSettings settings) { - this->id = id; - this->encoding = encoding; - this->color = color; - this->settings = settings; - }; + this->id_ = id; + this->encoding_ = encoding; + this->color_ = color; + this->settings_ = settings; + } /** * Returns the settings associated with the block. @@ -40,7 +40,7 @@ public: * @return The settings of the block, including solidity, pushability, and more. */ BlockSettings getSettings() { - return settings; + return settings_; } /** @@ -51,7 +51,7 @@ public: * @return The identifier of the block. */ Identifier getId() { - return id; + return id_; } /** @@ -62,7 +62,7 @@ public: * @return The color of the block. */ Color getColor() { - return color; + return color_; } /** @@ -73,7 +73,7 @@ public: * @return The character encoding of the block. */ char getEncoding() { - return encoding; + return encoding_; } /** @@ -84,11 +84,11 @@ public: * @param encoding The character encoding to set for the block. */ void setEncoding(char encoding) { - this->encoding = encoding; + this->encoding_ = encoding; } std::ostream& operator<<(std::ostream& out) { - out << encoding; + out << encoding_; return out; } bool operator==(Block otherBlock) { diff --git a/blockPos.hpp b/blockPos.hpp index 8356205..524d1c2 100644 --- a/blockPos.hpp +++ b/blockPos.hpp @@ -6,12 +6,22 @@ public: /** * Define an in-world position. * - * @param x The x-coordinate of the BlockPos. - * @param y The y-coordinate of the BlockPos. + * @param xCoord The x-coordinate of the BlockPos. + * @param yCoord The y-coordinate of the BlockPos. */ - BlockPos(int x, int y) { - this->x = x; - this->y = y; + BlockPos(int xCoord, int yCoord) { + this->x = xCoord; + this->y = yCoord; + } + /** + * Define an in-world position. + * + * @param xCoord The x-coordinate of the BlockPos. + * @param yCoord The y-coordinate of the BlockPos. + */ + BlockPos(unsigned int xCoord, unsigned int yCoord) { + this->x = static_cast(xCoord); + this->y = static_cast(yCoord); } /** @@ -56,12 +66,12 @@ public: /** * Add the given coordinates to the BlockPos. * - * @param x The x-coordinate to add. - * @param y The y-coordinate to add. + * @param xOffset The x-coordinate to add. + * @param yOffset The y-coordinate to add. * @return The BlockPos with the given coordinates added. */ - BlockPos add(int x, int y) { - return BlockPos(this->x + x, this->y + y); + BlockPos add(int xOffset, int yOffset) { + return BlockPos(this->x + xOffset, this->y + yOffset); } BlockPos operator+(BlockPos offset) { @@ -70,4 +80,4 @@ public: BlockPos operator-(BlockPos offset) { return BlockPos(this->getX() - offset.getX(), this->getY() - offset.getY()); } -}; \ No newline at end of file +}; diff --git a/blockRegistry.hpp b/blockRegistry.hpp index 30934b2..c7862e4 100644 --- a/blockRegistry.hpp +++ b/blockRegistry.hpp @@ -60,4 +60,4 @@ private: registeredBlocks.push_back(block); } vector registeredBlocks; -}; \ No newline at end of file +}; diff --git a/blockSettings.hpp b/blockSettings.hpp index 25cc788..ab404b5 100644 --- a/blockSettings.hpp +++ b/blockSettings.hpp @@ -174,4 +174,4 @@ class BlockSettingsBuilder { } private: BlockSettings blockSettings = BlockSettings(); -}; \ No newline at end of file +}; diff --git a/color.hpp b/color.hpp index 7bf8a4c..0a79931 100644 --- a/color.hpp +++ b/color.hpp @@ -13,6 +13,6 @@ enum class Color { BRIGHT_WHITE= 97 }; -std::ostream& operator<<(std::ostream& os, Color color) { +static std::ostream& operator<<(std::ostream& os, Color color) { return os << "\033[" << static_cast(color) << "m"; -} \ No newline at end of file +} diff --git a/fileUtils.hpp b/fileUtils.hpp index 6b66f5b..195d927 100644 --- a/fileUtils.hpp +++ b/fileUtils.hpp @@ -23,7 +23,7 @@ using std::vector; * @param extension The file extension to filter by * @return A list of all filtered file names in the specified directory, sorted alphabetically. */ -vector getOrderedFileNames(string dir, string extension) { +static vector getOrderedFileNames(string dir, string extension) { vector worlds; // 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. @@ -44,7 +44,7 @@ vector getOrderedFileNames(string dir, string extension) { * @param fileLocation The location of the file to read. * @return The content of the file as a vector of strings. */ -vector readFileAsVector(const string& fileLocation) { +static vector readFileAsVector(const string& fileLocation) { vector lines; std::ifstream file(fileLocation); @@ -65,10 +65,10 @@ vector readFileAsVector(const string& fileLocation) { * @param fileLocation Path to the file to be printed. * @param color Color to be used for the output. */ -void printFile(string fileLocation, Color color) { +static void printFile(string fileLocation, Color color) { cout << color; vector file = readFileAsVector(fileLocation); for (unsigned int y = 0; y < file.size(); y++) { cout << file.at(y) << endl; } -} \ No newline at end of file +} diff --git a/identifier.hpp b/identifier.hpp index ec0e9c0..b023675 100644 --- a/identifier.hpp +++ b/identifier.hpp @@ -5,8 +5,8 @@ using std::string; class Identifier { public: - std::string nameSpace; - std::string path; + std::string nameSpace_; + std::string path_; /** @@ -16,22 +16,20 @@ public: * @param nameSpace The namespace of the Identifier. * @param path The path of the Identifier. */ - Identifier(std::string nameSpace, std::string path) : nameSpace(nameSpace), path(path) { - - } + Identifier(std::string nameSpace, std::string path) : nameSpace_(nameSpace), path_(path) {} std::ostream& operator<<(std::ostream& out) { - out << nameSpace << ":" << path; + out << nameSpace_ << ":" << path_; return out; } std::istream& operator>>(std::istream& in) { string input; in >> input; - nameSpace = input.substr(0, input.find(":")); - path = input.substr(input.find(":") + 1, input.length()); + nameSpace_ = input.substr(0, input.find(":")); + path_ = input.substr(input.find(":") + 1, input.length()); return in; } bool operator==(Identifier otherId) { - return this->nameSpace == otherId.nameSpace && this->path == otherId.path; + return this->nameSpace_ == otherId.nameSpace_ && this->path_ == otherId.path_; } }; diff --git a/main.cpp b/main.cpp index d58f839..5d11f62 100644 --- a/main.cpp +++ b/main.cpp @@ -17,8 +17,8 @@ using std::endl; bool startWorld(string worldFile); bool parseArgs(int argc, char *argv[]); -bool testMode = false; -unsigned int worldIndex = 2; +static bool testMode = false; +static unsigned int worldIndex = 2; /** * Entry point of the program. @@ -31,15 +31,16 @@ int main(int argc, char *argv[]) { if (parseArgs(argc, argv)) return 0; if (!testMode) { - printFile("./start.screen.txt", Color::BRIGHT_YELLOW); + printFile("./start.screen.txt", Color::BRIGHT_YELLOW); // Show the story introduction waitForInput(); - printGuide(); + printGuide(); // Show the block guide waitForInput(); } // Load every world in order for (const auto & world : getOrderedFileNames("./", ".world.txt")) - if (!startWorld(world)) return 0; + if (!startWorld(world)) return 0; // If the player dies, exit + // Print the victory screen once all levels have been completed printFile("./victory.screen.txt", Color::BRIGHT_GREEN); @@ -85,14 +86,14 @@ bool startWorld(string worldFile) { bool parseArgs(int argc, char *argv[]) { if (argc > 1) { for (int i = 1; i < argc; i++) { - string arg = string(argv[i]); + string arg = string(argv[i]); // Unsafe buffer usage warnings can be safely ignored, as we do check for the size 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]))) + if (!startWorld("./" + string(argv[i+1]))) // This warning can also be ignored, again – we do this in a safe way return true; // Load only the specified world else printFile("./completed_single_level.screen.txt", Color::BRIGHT_GREEN); @@ -105,4 +106,4 @@ bool parseArgs(int argc, char *argv[]) { } } return false; -} \ No newline at end of file +} diff --git a/movementHandler.hpp b/movementHandler.hpp index b8629c7..8c8ea3f 100644 --- a/movementHandler.hpp +++ b/movementHandler.hpp @@ -6,8 +6,8 @@ #include "blockRegistry.hpp" #include "output.hpp" -void tryPushBlock(BlockPos& blockPos, World& world, bool left); -void tryBlockGravity(BlockPos& blockPos, World& world); +static void tryPushBlock(BlockPos& blockPos, World& world, bool left); +static void tryBlockGravity(BlockPos& blockPos, World& world); /** * Checks if a given value is in a parameter pack of values. @@ -22,7 +22,7 @@ void tryBlockGravity(BlockPos& blockPos, World& world); * @return true if the value is found in the parameter pack, false otherwise. */ template -bool is_in(First &&first, T && ... t) { +static bool is_in(First &&first, T && ... t) { return ((first == t) || ...); } @@ -30,7 +30,7 @@ bool is_in(First &&first, T && ... t) { * Waits until the user enters a valid key. * Used to prompt the user to press any key to continue. */ -void waitForInput() { +static void waitForInput() { char lastChar = ' '; while (!is_in(lastChar, 'w', 'a', 's', 'd')) cin >> lastChar; } @@ -48,7 +48,7 @@ void waitForInput() { * @param left Whether to move left (true) or right (false). * @return true if the player's position was successfully updated, false otherwise. */ -bool tryWalk(World& world, Player& player, bool left) { +static bool tryWalk(World& world, Player& player, bool left) { BlockPos playerPos = player.getPos(); BlockPos neighbourPosTorso = playerPos+(left ? BlockPos(-1, 0) : BlockPos(1, 0)); BlockPos neighbourPosFeet = playerPos+(left ? BlockPos(-1, 1) : BlockPos(1, 1)); @@ -76,7 +76,7 @@ bool tryWalk(World& world, Player& player, bool left) { * @param player Reference to the Player object representing the player's state. * @return true if the player's position was successfully updated, false otherwise. */ -bool tryGoDown(World& world, Player& player) { +static bool tryGoDown(World& world, Player& player) { if (world.getBlockAt(player.getPos()+BlockPos(0, 2)).getSettings().isClimbableFromTop() || world.getBlockAt(player.getPos()+BlockPos(0, 3)).getSettings().isClimbableFromTop()) { player.move(0, 1); return true; @@ -95,7 +95,7 @@ bool tryGoDown(World& world, Player& player) { * @param player Reference to the Player object representing the player's state. * @return true if the player's position was successfully updated, false otherwise. */ -bool tryGoUp(World& world, Player& player) { +static bool tryGoUp(World& world, Player& player) { if (world.getBlockAt(player.getPos()+BlockPos(0, 1)).getSettings().isClimbableFromBottom() || world.getBlockAt(player.getPos()+BlockPos(0, 2)).getSettings().isClimbableFromBottom()) { player.move(0, -1); return true; @@ -115,7 +115,7 @@ bool tryGoUp(World& world, Player& player) { * @param world Reference to the World object representing the current world. * @param left Whether to push the block to the left (true) or right (false). */ -void tryPushBlock(BlockPos& blockPos, World& world, bool left) { +static void tryPushBlock(BlockPos& blockPos, World& world, bool left) { BlockPos neighbourBlockPos = blockPos+(left ? BlockPos(-1, 0) : BlockPos(1, 0)); if (world.getBlockAt(blockPos).getSettings().isPushable()) { if (world.getBlockAt(neighbourBlockPos).getSettings().isPushable()) { @@ -135,7 +135,7 @@ void tryPushBlock(BlockPos& blockPos, World& world, bool left) { * @param playerPos The position of the player. * @param world Reference to the World object representing the current world. */ -void tryBlockGravity(BlockPos& playerPos, World& world) { +static void tryBlockGravity(BlockPos& playerPos, World& world) { if (world.getBlockAt(playerPos.add(0, 2)).getSettings().hasGravity() && world.getBlockAt(playerPos.add(0, 3)) == world.getBlockRegistry().AIR) { world.setBlockAt(playerPos.add(0, 3), world.getBlockAt(playerPos.add(0, 2))); world.setBlockAt(playerPos.add(0, 2), world.getBlockRegistry().AIR); @@ -153,7 +153,7 @@ void tryBlockGravity(BlockPos& playerPos, World& world) { * @return true if the player's position was successfully updated, false otherwise. */ -bool onInput(char lastChar, World& world, Player& player) { +static bool onInput(char lastChar, World& world, Player& player) { switch (lastChar) { case ' ': case 'w': @@ -182,7 +182,7 @@ bool onInput(char lastChar, World& world, Player& player) { * In this case, the game state is updated every 100 milliseconds (to simulate the player's input). * If the player dies or reaches the goal, exit the loop. */ -void inputLoop(Player& player, World& world, bool testMode, unsigned int worldIndex) { +static void inputLoop(Player& player, World& world, bool testMode, unsigned int worldIndex) { vector testFile = readFileAsVector("TEST.txt"); unsigned int inputIndex = 0; while (player.isAlive() && !player.hasReachedGoal()) { @@ -204,4 +204,4 @@ void inputLoop(Player& player, World& world, bool testMode, unsigned int worldIn } } inputIndex = 0; -} \ No newline at end of file +} diff --git a/output.hpp b/output.hpp index dad7010..c506320 100644 --- a/output.hpp +++ b/output.hpp @@ -12,7 +12,7 @@ using std::endl; * Move the console cursor up by one line. * Used to overwrite the previous line. */ -void jumpBackOneLine() { +static void jumpBackOneLine() { std::cout << "\033[1A"; } @@ -22,9 +22,9 @@ void jumpBackOneLine() { * On positions that overlap with the player texture, the relevant character of the player's texture is printed instead. * * @param world Reference to the World object representing the current world. - * @param player Reference to the Player object representing the player's state. + * @param playerTexture Reference to the current Player texture. */ -void render(World &world, vector> playerTexture) { +static void render(World &world, vector> playerTexture) { vector> canvas = world.getFieldState(); @@ -51,9 +51,9 @@ void render(World &world, vector> playerTexture) { * and the player. * * @param world Reference to the World object representing the current world. - * @param player Reference to the Player object representing the player's state. + * @param playerTexture Reference to the current Player texture. */ -void redraw(World &world, vector> playerTexture) { +static void redraw(World &world, vector> playerTexture) { for (unsigned int y = 0; y <= world.getMaxY(); y++) { jumpBackOneLine(); } @@ -64,7 +64,7 @@ void redraw(World &world, vector> playerTexture) { * Prints a guide for the player, explaining what each block in the game * represents. */ -void printGuide() { +static void printGuide() { // We use a vector here instead of a map, because we want to keep this order std::vector> guide = { {"- Plattform", Color::RESET}, @@ -81,4 +81,4 @@ void printGuide() { cout << p.second << p.first << endl; } cout << endl << Color::RESET << "WASD + Enter -> Spiel starten" << endl; -} \ No newline at end of file +} diff --git a/player.hpp b/player.hpp index e655fdd..9991424 100644 --- a/player.hpp +++ b/player.hpp @@ -11,16 +11,16 @@ public: /** * Initializes a new Player at the specified starting position in the provided world. * - * @param pos The initial position of the player within the world. - * @param world A reference to the World object representing the game world. + * @param initialPos The initial position of the player within the world. + * @param currentWorld A reference to the World object representing the game world. */ - Player(BlockPos pos, World& world) : world(world) { - this->pos = pos; - this->world = world; + Player(BlockPos initialPos, World& currentWorld) : world(currentWorld) { + this->pos = initialPos; + this->world = currentWorld; playerTexture = REGULAR_PLAYER_TEXTURE; } - /** + /*initialP * Retrieves the current position of the player in the world. * * @return The current BlockPos representing the player's position. @@ -52,20 +52,20 @@ public: /** * Updates the player's position and checks for any conditions that would update the state of the player. * - * @param pos The position to move the player to. + * @param newPos The position to move the player to. */ - void setPos(BlockPos pos) { - if (!world.containsPos(pos)) { + void setPos(BlockPos newPos) { + if (!world.containsPos(newPos)) { alive = false; return; } - this->pos = pos; + this->pos = newPos; - if (world.getBlockAt(pos) == world.getBlockRegistry().GOAL) reachedGoal = true; + if (world.getBlockAt(newPos) == world.getBlockRegistry().GOAL) reachedGoal = true; - if (world.getBlockAt(pos.add(0, 2)) == world.getBlockRegistry().WATER) fallLength = 0; + if (world.getBlockAt(newPos.add(0, 2)) == world.getBlockRegistry().WATER) fallLength = 0; - isFreeFalling = !world.getBlockAt(pos.add(0, 2)).getSettings().isSolid(); + isFreeFalling = !world.getBlockAt(newPos.add(0, 2)).getSettings().isSolid(); if (isFreeFalling) { fallLength += 1; if (fallLength > 2) playerTexture = FALLING_PLAYER_TEXTURE; @@ -79,7 +79,7 @@ public: fallLength = 0; } - if (world.getBlockAt(pos.add(0, 2)).getSettings().isLethal()) unalive(); + if (world.getBlockAt(newPos.add(0, 2)).getSettings().isLethal()) unalive(); } /** @@ -121,13 +121,13 @@ public: while (map.size() <= y) map.push_back({}); while (map[y].size() <= x) map[y].push_back(' '); - int yOffset = y-pos.getY() + 1; - int xOffset = x-pos.getX() + 1; + int yOffset = static_cast(y)-static_cast(pos.getUnsignedY()) + 1; + int xOffset = static_cast(x)-static_cast(pos.getUnsignedX()) + 1; char encoding = ' '; - if (yOffset >= 0 && yOffset < static_cast(playerTexture.size()) && - xOffset >= 0 && xOffset < static_cast(playerTexture.at(yOffset).size())) { - encoding = playerTexture.at(yOffset).at(xOffset); + if (yOffset >= 0 && yOffset < (static_cast(static_cast(playerTexture.size()))) && + xOffset >= 0 && xOffset < (static_cast(playerTexture.at(static_cast(yOffset)).size()))) { + encoding = playerTexture.at(static_cast(yOffset)).at(static_cast(xOffset)); } map[y][x] = encoding; @@ -161,4 +161,4 @@ private: {'/', '-', 'X'}, {'/', ' ', '\\'} }}; -}; \ No newline at end of file +}; diff --git a/world.hpp b/world.hpp index 084b2e4..88bf8be 100644 --- a/world.hpp +++ b/world.hpp @@ -13,10 +13,10 @@ public: /** * Create a World object using the blocks defined in BlockRegistry. * - * @param blockRegistry The BlockRegistry to use. + * @param worldBlockRegistry The BlockRegistry to use. */ - World(BlockRegistry blockRegistry) { - this->blockRegistry = blockRegistry; + World(BlockRegistry worldBlockRegistry) { + this->blockRegistry = worldBlockRegistry; } /** @@ -54,7 +54,7 @@ public: while (field.size() <= pos.getUnsignedY()) field.push_back({}); while (field[pos.getUnsignedY()].size() <= pos.getUnsignedX()) field[pos.getUnsignedY()].push_back(blockRegistry.AIR); - field[pos.getUnsignedY()][pos.getX()] = block; + field[pos.getUnsignedY()][pos.getUnsignedX()] = block; if (block.getSettings().hasGravity() && containsPos(pos.add(0, 1)) && getBlockAt(pos.add(0, 1)) == blockRegistry.AIR) { setBlockAt(pos.add(0, 1), block); setBlockAt(pos, blockRegistry.AIR); @@ -71,7 +71,7 @@ public: */ Block& getBlockAt(BlockPos pos) { if (pos.getUnsignedY() < field.size() && pos.getUnsignedX() < field[pos.getUnsignedY()].size()) { - return field[pos.getY()][pos.getX()]; + return field[pos.getUnsignedY()][pos.getUnsignedX()]; } //cout << "Out of bounds: " << pos.getX() << ", " << pos.getY() << endl; return blockRegistry.AIR; @@ -136,4 +136,4 @@ private: unsigned int maxX = 0; unsigned int maxY = 0; BlockPos startPos = BlockPos(0, 0); -}; \ No newline at end of file +};