Last active
April 25, 2024 22:33
-
-
Save fallenthereaper/dbd6361b4525fe2b24cecb9e6396b853 to your computer and use it in GitHub Desktop.
Game class
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "src/core/shop/game.h" | |
| namespace ShopGame { | |
| Game::Game() : running(true), gameName("Default"), canvas(new GameRenderer::TextCanvas(0, 0)), currentState(nullptr), prevState(nullptr) { | |
| registerCommands(); | |
| } | |
| Game::Game(int canvasWidth, int canvasHeight, std::string name) : canvas(new GameRenderer::TextCanvas(canvasWidth, canvasHeight)), running(true), gameName(name), currentState(nullptr), prevState(nullptr) { | |
| registerCommands(); | |
| } | |
| // Destructor | |
| Game::~Game() { | |
| registerCommands(); | |
| } | |
| void Game::addCommand(const std::string& command, const std::function<void(Game*)> consumer) { | |
| // commandMap[command] = (consumer); | |
| commandMap.emplace(command, consumer); | |
| } | |
| std::string Game::getName() { | |
| return gameName; | |
| } | |
| void displayItemList(GameRenderer::TextCanvas* canvas, const std::unordered_map<std::string, ItemRegistry::ItemFactory>& itemList, const std::string& displayTitle, const Vec2& topLeft, int maxWidth, int itemWidth, int itemHeight, int maxItemCount) { | |
| int itemCount = std::min(static_cast<int>(itemList.size()), maxItemCount); | |
| // Calculate the number of rows needed based on the item count | |
| int numRows = (itemCount + (maxWidth - 1)) / maxWidth; | |
| int numCols = (itemCount + numRows - 1) / numRows; | |
| // Draw the title of the item list | |
| canvas->drawSquare(topLeft + Vec2{2, - 1}, itemWidth * numRows + 3 , itemHeight, '*', displayTitle, true); | |
| int row = topLeft.y + 2; // Start rendering items below the title | |
| int col = topLeft.x + 2; | |
| int itemIndex = 0; | |
| for (const auto& itemPair : itemList) { | |
| if (itemIndex >= maxItemCount) { | |
| break; // Stop rendering if maximum item count is reached | |
| } | |
| // Check if we need to move to the next row | |
| if (col + itemWidth > topLeft.x + numCols * itemWidth) { | |
| col = topLeft.x + 2; // Reset column position to start a new row | |
| row += itemHeight ; // Move to the next row | |
| } | |
| // Get the item name from the item pair | |
| std::string itemName = itemPair.first; | |
| // Render the item at the current position | |
| canvas->drawSquare(Vec2(col, row + 1), itemWidth, itemHeight, '*', itemName, true); | |
| // Move to the next column position | |
| col += itemWidth + 1; | |
| ++itemIndex; | |
| } | |
| } | |
| void Game::registerCommands() { | |
| GameRenderer::TextCanvas* canvas = this->getCanvas(); | |
| addCommand("shop", [canvas](Game* g) { | |
| std::cout << "Opening shop..." << std::endl; | |
| const auto& itemMap = ItemRegistry::getInstance()->getItemMap(); | |
| // Define the dimensions and layout of the item shop display | |
| Vec2 shopTopLeft(16 , 3); | |
| int maxWidth = 6; // Maximum items per row | |
| int itemWidth = 18; | |
| int itemHeight = 3; | |
| int maxItemCount = 30; // Maximum items to display | |
| displayItemList(canvas, itemMap, "Item Shop", shopTopLeft, maxWidth, itemWidth, itemHeight, maxItemCount); | |
| }); | |
| addCommand("exit", [canvas](Game* g) { | |
| std::cout << "Closing game..." << std::endl; | |
| canvas->drawSquare(Vec2(46, 10), 20, 5, '*', "Game Closed", true); | |
| g->running = false; // Set running flag to false to exit the game loop | |
| }); | |
| addCommand("clear", [canvas](Game* g) { | |
| std::cout << "Clearing canvas..." << std::endl; | |
| canvas->clear(); // Clear the canvas | |
| canvas->drawSquare(Vec2(46, 10), 20, 5, '*', "Cleared Canvas", true); | |
| }); | |
| addCommand("help", [canvas](Game* g) { | |
| canvas->drawSquare(Vec2(46, 10), 20, 5, '*', "Help Menu", false); | |
| canvas->drawSquare(Vec2(48, 12), 16, 3, '*', "Commands:", false); | |
| canvas->drawSquare(Vec2(50, 14), 12, 3, '*', "shop - Open shop", false); | |
| canvas->drawSquare(Vec2(50, 16), 12, 3, '*', "exit - Exit game", false); | |
| canvas->drawSquare(Vec2(50, 18), 12, 3, '*', "clear - Clear canvas", false); | |
| canvas->drawSquare(Vec2(50, 20), 12, 3, '*', "info - Game info", false); | |
| canvas->drawSquare(Vec2(50, 22), 12, 3, '*', "help - Display help", false); | |
| }); | |
| addCommand("info", [canvas](Game* g) { | |
| std::cout << "Displaying info..." << std::endl; | |
| canvas->drawSquare(Vec2(46, 3), 20, 5, '*', "Game Information", true); | |
| canvas->drawText(Vec2(46, 14), "Version: 1.0"); | |
| canvas->drawText(Vec2(46, 16), "Developer: " + g->getName()); | |
| // Display screen size | |
| int screenWidth = g->getCanvas()->getWidth(); | |
| int screenHeight = g->getCanvas()->getHeight(); | |
| canvas->drawText(Vec2(46, 18), "Screen Size:"); | |
| canvas->drawText(Vec2(46, 20), "Width: " + std::to_string(screenWidth)); | |
| canvas->drawText(Vec2(46, 22), "Height: " + std::to_string(screenHeight)); | |
| // Display available commands | |
| int x = 6; | |
| canvas->drawSquare(Vec2(x - 2, 2), 28, 14, '*', "", true); | |
| canvas->drawText(Vec2(x, 3), "Available Commands:"); | |
| canvas->drawText(Vec2(x, 5), "shop - Open shop"); | |
| canvas->drawText(Vec2(x, 7), "exit - Exit game"); | |
| canvas->drawText(Vec2(x, 9), "clear - Clear canvas"); | |
| canvas->drawText(Vec2(x, 11), "info - Display game info"); | |
| canvas->drawText(Vec2(x, 13), "help - Display help menu"); | |
| }); | |
| } | |
| // Method to process input and trigger associated consumers | |
| void Game::processInput(const std::string& input) { | |
| auto it = commandMap.find(input); | |
| if (it != commandMap.end()) { | |
| it->second(this); | |
| } | |
| else { | |
| if (currentState) { | |
| currentState->handleInput(this, input); | |
| } | |
| else { | |
| std::cout << "Command not recognized. Try again." << std::endl; | |
| } | |
| } | |
| } | |
| void Game::update(GameRenderer::TextCanvas* canvas) { | |
| canvas->drawSquare(Vec2(0, 0), 112, 28, '*', "", true); | |
| std::string input; | |
| std::cout << "Enter a command: "; | |
| std::cin >> input; | |
| processInput(input); | |
| } | |
| void Game::clean() { | |
| } | |
| void Game::render() { | |
| if (currentState) { | |
| currentState->render(canvas); | |
| canvas->render(); // Render the canvas after updating its content | |
| } | |
| } | |
| const bool Game::isRunning() { | |
| return this->running; | |
| } | |
| void Game::setRunning(bool val) { | |
| this->running = val; | |
| } | |
| GameRenderer::TextCanvas* Game::getCanvas() { | |
| return canvas; | |
| } | |
| void Game::setGameState(ShopGame::GameState* state) { | |
| prevState = currentState; | |
| if (currentState != nullptr) { | |
| delete currentState; // Clean up the previous state | |
| } | |
| std::cout << "Switching GameState.."; | |
| currentState = state; | |
| } | |
| GameState* Game::getGameState() { | |
| return currentState; | |
| } | |
| GameState* Game::getPreviousState() { | |
| return prevState; | |
| } | |
| // Method to start the game | |
| void Game::start() { | |
| std::cout << "[Game Started]" << std::endl; | |
| std::cout << "Type 'exit' to quit the game." << std::endl; | |
| } | |
| // Helper method for handling user input | |
| void Game::handleInput(const std::string& input) { | |
| std::cout << "Command not recognized. Try again." << std::endl; | |
| } | |
| } // namespace ShopGame |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #include <iostream> | |
| #include <unordered_map> | |
| #include <functional> | |
| #include "src/core/text_canvas.h" | |
| #include "src/core/shop/registry/item_registry.h" | |
| #include "src/core/shop/game_state.h" | |
| namespace ShopGame { | |
| class Game { | |
| public: | |
| Game(); | |
| ~Game(); | |
| Game(int canvasWidth, int canvasHeight, std::string gameName); | |
| void start(); | |
| void update(GameRenderer::TextCanvas* canvas); | |
| void clean(); | |
| void render(); | |
| const bool isRunning(); | |
| void setRunning(bool val); | |
| GameRenderer::TextCanvas* getCanvas(); | |
| void addCommand(const std::string& command, const std::function<void(Game*)> function); | |
| void processInput(const std::string& input); | |
| std::string getName(); | |
| void setGameState(ShopGame::GameState* state); | |
| ShopGame::GameState* getGameState(); | |
| ShopGame::GameState* getPreviousState(); | |
| private: | |
| ShopGame::GameState* prevState; | |
| ShopGame::GameState* currentState; | |
| bool running; | |
| std::string gameName; | |
| GameRenderer::TextCanvas* canvas; | |
| std::unordered_map<std::string, std::function<void(Game*)>> commandMap; | |
| void handleInput(const std::string& input); | |
| void registerCommands(); | |
| friend void displayItemList(GameRenderer::TextCanvas* canvas, const std::unordered_map<std::string, ItemRegistry::ItemFactory>& itemList, const std::string& displayTitle, const Vec2& topLeft, int maxWidth, int itemWidth, int itemHeight, int maxItemCount); | |
| }; | |
| } // namespace ShopGame |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "src/core/shop/game_state.h" | |
| namespace ShopGame { | |
| //GAME STATE | |
| GameState::GameState(Game* game) { | |
| init(game); | |
| } | |
| void GameState::handleInput(Game* game, const std::string& input) { | |
| auto it = commandMap.find(input); | |
| if (it != commandMap.end()) { | |
| // Execute the consumer associated with the input command | |
| it->second(game); // Pass 'this' pointer to the Game object | |
| } | |
| else { | |
| game->getCanvas()->drawSquare(Vec2(38, 10), 38, 5, '*', "Command not recognized. Try again.", true); | |
| } | |
| }; | |
| void GameState::update(Game* game) { | |
| }; | |
| void GameState::init(Game* game) { | |
| registerCommands(); | |
| } | |
| void GameState::addCommand(const std::string& command, const std::function<void(Game*)> consumer) { | |
| // commandMap[command] = (consumer); | |
| commandMap.emplace(command, consumer); | |
| } | |
| Game* GameState::getGame() { | |
| return game; | |
| } | |
| void GameState::registerCommands() { | |
| addCommand("menu", [this](Game* g) { | |
| GameState* menu = new MenuState(g); | |
| g->setGameState(menu); | |
| }); | |
| } | |
| void GameState::render(GameRenderer::TextCanvas* canvas) { | |
| } | |
| //MENU STATE | |
| void MenuState::update(ShopGame::Game* game) { | |
| // Update logic for the menu state | |
| } | |
| void MenuState::registerCommands() { | |
| GameState::registerCommands(); | |
| GameRenderer::TextCanvas* canvas = getGame()->getCanvas(); | |
| addCommand("shop", [canvas](Game* g) { | |
| std::cout << "Opening shop..." << std::endl; | |
| const auto& itemMap = ItemRegistry::getInstance()->getItemMap(); | |
| // Define the dimensions and layout of the item shop display | |
| Vec2 shopTopLeft(16, 3); | |
| int maxWidth = 6; // Maximum items per row | |
| int itemWidth = 18; | |
| int itemHeight = 3; | |
| int maxItemCount = 30; // Maximum items to display | |
| displayItemList(canvas, itemMap, "Item Shop", shopTopLeft, maxWidth, itemWidth, itemHeight, maxItemCount); | |
| }); | |
| addCommand("exit", [canvas](Game* g) { | |
| std::cout << "Closing game..." << std::endl; | |
| canvas->drawSquare(Vec2(46, 10), 20, 5, '*', "Game Closed", true); | |
| g->setRunning(false); // Set running flag to false to exit the game loop | |
| }); | |
| addCommand("clear", [canvas](Game* g) { | |
| std::cout << "Clearing canvas..." << std::endl; | |
| canvas->clear(); // Clear the canvas | |
| canvas->drawSquare(Vec2(46, 10), 20, 5, '*', "Cleared Canvas", true); | |
| }); | |
| addCommand("help", [canvas](Game* g) { | |
| canvas->drawSquare(Vec2(46, 10), 20, 5, '*', "Help Menu", false); | |
| canvas->drawSquare(Vec2(48, 12), 16, 3, '*', "Commands:", false); | |
| canvas->drawSquare(Vec2(50, 14), 12, 3, '*', "shop - Open shop", false); | |
| canvas->drawSquare(Vec2(50, 16), 12, 3, '*', "exit - Exit game", false); | |
| canvas->drawSquare(Vec2(50, 18), 12, 3, '*', "clear - Clear canvas", false); | |
| canvas->drawSquare(Vec2(50, 20), 12, 3, '*', "info - Game info", false); | |
| canvas->drawSquare(Vec2(50, 22), 12, 3, '*', "help - Display help", false); | |
| }); | |
| addCommand("info", [canvas](Game* g) { | |
| std::cout << "Displaying info..." << std::endl; | |
| canvas->drawSquare(Vec2(46, 3), 20, 5, '*', "Game Information", true); | |
| canvas->drawText(Vec2(46, 14), "Version: 1.0"); | |
| canvas->drawText(Vec2(46, 16), "Developer: " + g->getName()); | |
| // Display screen size | |
| int screenWidth = g->getCanvas()->getWidth(); | |
| int screenHeight = g->getCanvas()->getHeight(); | |
| canvas->drawText(Vec2(46, 18), "Screen Size:"); | |
| canvas->drawText(Vec2(46, 20), "Width: " + std::to_string(screenWidth)); | |
| canvas->drawText(Vec2(46, 22), "Height: " + std::to_string(screenHeight)); | |
| // Display available commands | |
| int x = 6; | |
| canvas->drawSquare(Vec2(x - 2, 2), 28, 14, '*', "", true); | |
| canvas->drawText(Vec2(x, 3), "Available Commands:"); | |
| canvas->drawText(Vec2(x, 5), "shop - Open shop"); | |
| canvas->drawText(Vec2(x, 7), "exit - Exit game"); | |
| canvas->drawText(Vec2(x, 9), "clear - Clear canvas"); | |
| canvas->drawText(Vec2(x, 11), "info - Display game info"); | |
| canvas->drawText(Vec2(x, 13), "help - Display help menu"); | |
| }); | |
| } | |
| void MenuState::render(GameRenderer::TextCanvas* canvas) { | |
| // Render the menu state on the canvas | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #pragma once | |
| #include <string> | |
| #include <unordered_map> | |
| #include <functional> | |
| #include "src/core/shop/game.h" // Include the necessary header | |
| namespace ShopGame { | |
| class GameState { | |
| protected: | |
| ShopGame::Game* game; | |
| std::unordered_map<std::string, std::function<void(ShopGame::Game*)>> commandMap; | |
| public: | |
| GameState(ShopGame::Game* game); | |
| virtual ~GameState() = default; | |
| void handleInput(ShopGame::Game* game, const std::string& input); | |
| virtual void update(ShopGame::Game* game) = 0; | |
| virtual void registerCommands() = 0; | |
| void init(ShopGame::Game* game); | |
| void addCommand(const std::string& command, const std::function<void(ShopGame::Game*)> function); | |
| ShopGame::Game* getGame(); | |
| virtual void render(GameRenderer::TextCanvas* canvas) = 0; | |
| }; | |
| class MenuState : public GameState { | |
| public: | |
| MenuState(ShopGame::Game* game) : GameState(game) {} | |
| void registerCommands() override; | |
| void update(ShopGame::Game* game) override; | |
| void render(GameRenderer::TextCanvas* canvas) override; | |
| }; | |
| } // namespace ShopGame |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // main.cpp : Defines the entry point for the application. | |
| // | |
| #define MAX_CANVAS_WIDTH 112 | |
| #define MAX_CANVAS_HEIGHT 28 | |
| #include "src/core/main.h" | |
| #include "src/core/utils/utility.h" | |
| #include "src/core/utils/containers.h" | |
| #include <vector> | |
| #include "src/core/bank/bank.h" | |
| #include "src/core/bank/bank_account.h" | |
| #include "src/core//tictac_game.h" | |
| #include <sstream> | |
| #include <iomanip> | |
| #include "src/core/shop/registry/item_registry.h" | |
| #include "src/core/shop/registry/items.h"; | |
| #include "src/core/shop/game.h"; | |
| #include "src/core/Game_renderer.h"; | |
| using namespace std; | |
| using namespace Utility; | |
| using namespace Utility::Mth; | |
| //using Vec3 = Utility::Mth::Vec3; | |
| ///int argc, char * argv[] | |
| static const std::vector<std::string> BELOW_TWENTY = { | |
| "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", | |
| "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", | |
| "seventeen", "eighteen", "nineteen" | |
| }; | |
| unsigned long long hexToDecimal(const std::string& hexString) { | |
| unsigned long long decimalValue; | |
| std::stringstream ss; | |
| ss << std::hex << hexString; | |
| ss >> decimalValue; | |
| return decimalValue; | |
| } | |
| // Function to convert a decimal integer to a hexadecimal string | |
| std::string decimalToHex(unsigned long long decimalValue) { | |
| std::stringstream ss; | |
| ss << std::hex << std::uppercase << decimalValue; | |
| return ss.str(); | |
| } | |
| ShopGame::Game* game = nullptr; | |
| void coreInit() { | |
| ShopGame::registerItems(); | |
| } | |
| // Function to compare two canvas data arrays | |
| bool compareData(const char** canvas1, const char** canvas2, int width, int height) { | |
| for (int y = 0; y < height; ++y) { | |
| for (int x = 0; x < width; ++x) { | |
| if (canvas1[y][x] != canvas2[y][x]) { | |
| return false; // Found a difference in the canvas content | |
| } | |
| } | |
| } | |
| return true; // Canvases are identical | |
| } | |
| // Function to copy canvas data | |
| const char** copyData(const char** canvas, int width, int height) { | |
| char** copiedCanvas = new char* [height]; | |
| for (int y = 0; y < height; ++y) { | |
| copiedCanvas[y] = new char[width]; | |
| for (int x = 0; x < width; ++x) { | |
| copiedCanvas[y][x] = canvas[y][x]; | |
| } | |
| } | |
| return const_cast<const char**>(copiedCanvas); | |
| } | |
| void deleteData(const char** canvas, int height) { | |
| if (canvas != nullptr) { | |
| for (int y = 0; y < height; ++y) { | |
| delete[] canvas[y]; // Free each row of the canvas | |
| } | |
| delete[] canvas; // Free the array of rows | |
| } | |
| } | |
| using Game = ShopGame::Game; | |
| int main(int argc, const char * argv[]) { | |
| coreInit(); | |
| game = new Game(MAX_CANVAS_WIDTH, MAX_CANVAS_HEIGHT, "Exolor"); | |
| game->start(); | |
| const char** prevCanvas = nullptr; | |
| GameRenderer::TextCanvas* canvas = game->getCanvas(); | |
| while (game->isRunning()) { | |
| game->update(canvas); | |
| const char** currentCanvas = canvas->getData(); | |
| // Check if the canvas content has changed | |
| if (prevCanvas == nullptr || !compareData(prevCanvas, currentCanvas, canvas->getWidth(), canvas->getHeight())) { | |
| // Render the game only if the canvas content has changed | |
| GameRenderer::render(game); | |
| // Update the previous canvas to match the current canvas | |
| if (prevCanvas != nullptr) { | |
| delete[] prevCanvas; // Free the previously allocated memory | |
| } | |
| prevCanvas = copyData(currentCanvas, canvas->getWidth(), canvas->getHeight()); | |
| } | |
| // GameRenderer::render(game); | |
| } | |
| // Clean up allocated memory for the last recorded canvas | |
| if (prevCanvas != nullptr) { | |
| delete[] prevCanvas; | |
| } | |
| return 0; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment