diff --git a/Makefile b/Makefile index 7c32ed7..6784c0b 100644 --- a/Makefile +++ b/Makefile @@ -1,27 +1,30 @@ CXX = c++ -CXXFLAGS = -Wall -Wextra -O3 +CXXFLAGS = -Wall -Wextra -O3 -Isrc LDFLAGS = -static - SRC_DIR = src OBJ_DIR = build BIN_DIR = bin - SRC_EXT = cpp OBJ_EXT = o -SOURCES = $(wildcard $(SRC_DIR)/*.$(SRC_EXT)) +# Find all source files recursively in subdirectories +SOURCES = $(shell find $(SRC_DIR) -name '*.$(SRC_EXT)') +# Create corresponding object files maintaining directory structure OBJECTS = $(SOURCES:$(SRC_DIR)/%.$(SRC_EXT)=$(OBJ_DIR)/%.$(OBJ_EXT)) - EXEC = $(BIN_DIR)/fissh +# Get all unique subdirectories for build structure +OBJ_DIRS = $(sort $(dir $(OBJECTS))) + all: $(EXEC) $(EXEC): $(OBJECTS) - @mkdir -p $(BIN_DIR) # Make sure the bin dir exists + @mkdir -p $(BIN_DIR) $(CXX) $(OBJECTS) -o $(EXEC) $(LDFLAGS) -$(OBJ_DIR)/%.o: $(SRC_DIR)/%.$(SRC_EXT) - @mkdir -p $(OBJ_DIR) # Make sure the obj dir exists +# Create object files, maintaining directory structure +$(OBJ_DIR)/%.$(OBJ_EXT): $(SRC_DIR)/%.$(SRC_EXT) + @mkdir -p $(dir $@) $(CXX) $(CXXFLAGS) -c $< -o $@ clean: @@ -30,4 +33,4 @@ clean: install: $(EXEC) install -m 755 $(EXEC) /usr/local/bin/ -.PHONY: all clean run +.PHONY: all clean install diff --git a/src/assets/FishAssets.h b/src/assets/FishAssets.h index 1fe7488..a7b7ebf 100644 --- a/src/assets/FishAssets.h +++ b/src/assets/FishAssets.h @@ -1,7 +1,7 @@ #pragma once -#include "../Entity.h" -#include "../SpriteUtils.h" +#include "../entities/Entity.h" +#include "../utils/SpriteUtils.h" #include /* diff --git a/src/assets/SeaMonsterAssets.h b/src/assets/SeaMonsterAssets.h index 8f44773..ed208e4 100644 --- a/src/assets/SeaMonsterAssets.h +++ b/src/assets/SeaMonsterAssets.h @@ -1,6 +1,6 @@ #pragma once -#include "../Entity.h" -#include "../SpriteUtils.h" +#include "../entities/Entity.h" +#include "../utils/SpriteUtils.h" #include struct SeaMonsterAsset { diff --git a/src/assets/ShipAssets.h b/src/assets/ShipAssets.h index 20905c9..328979f 100644 --- a/src/assets/ShipAssets.h +++ b/src/assets/ShipAssets.h @@ -1,6 +1,6 @@ #pragma once -#include "../Entity.h" -#include "../SpriteUtils.h" +#include "../entities/Entity.h" +#include "../utils/SpriteUtils.h" #include inline const AssetPair &getShip() { diff --git a/src/assets/WhaleAssets.h b/src/assets/WhaleAssets.h index 6274915..cc50e0e 100644 --- a/src/assets/WhaleAssets.h +++ b/src/assets/WhaleAssets.h @@ -1,6 +1,6 @@ #pragma once -#include "../Entity.h" -#include "../SpriteUtils.h" +#include "../entities/Entity.h" +#include "../utils/SpriteUtils.h" #include struct WhaleAsset { diff --git a/src/Aquarium.cpp b/src/core/Aquarium.cpp similarity index 71% rename from src/Aquarium.cpp rename to src/core/Aquarium.cpp index 46536f7..a53a973 100644 --- a/src/Aquarium.cpp +++ b/src/core/Aquarium.cpp @@ -1,17 +1,21 @@ #include "Aquarium.h" -#include "Bubble.h" -#include "Castle.h" -#include "Fish.h" -#include "SeaMonster.h" -#include "Seaweed.h" -#include "Ship.h" -#include "Waterline.h" -#include "Whale.h" +#include "../core/Config.h" +#include "../entities/Bubble.h" +#include "../entities/Castle.h" +#include "../entities/Fish.h" +#include "../entities/SeaMonster.h" +#include "../entities/Seaweed.h" +#include "../entities/Ship.h" +#include "../entities/Waterline.h" +#include "../entities/Whale.h" #include +#include #include #include +#include #include #include +#include #include #include #include @@ -128,7 +132,10 @@ void Aquarium::ensureEntitiesSorted() { void Aquarium::redraw() { clearCurrentFrame(); - ensureBigEntityExists(); + + if (g_config.enable_big_entities) { + ensureBigEntityExists(); + } static std::vector> newEntities; static std::vector entitiesToRemove; @@ -136,26 +143,40 @@ void Aquarium::redraw() { newEntities.clear(); entitiesToRemove.clear(); + // Count current bubbles + int bubble_count = 0; + for (const auto &entity : entities) { + if (dynamic_cast(entity.get())) { + bubble_count++; + } + } + // Update all entities and collect changes for (size_t i = 0; i < entities.size(); ++i) { auto &entity = entities[i]; entity->update(); - // Handle fish bubble spawning - if (auto *fish = dynamic_cast(entity.get())) { - if (fish->shouldSpawnBubble()) { - newEntities.emplace_back( - std::make_unique(fish->getX(), fish->getY())); + // Handle fish bubble spawning with configuration + if (g_config.enable_bubbles && bubble_count < g_config.max_bubbles) { + if (auto *fish = dynamic_cast(entity.get())) { + if (fish->shouldSpawnBubble()) { + // Use configured bubble rate + if (rand() % g_config.fish_bubble_rate == 0) { + newEntities.emplace_back( + std::make_unique(fish->getX(), fish->getY())); + bubble_count++; + } + } } } if (entity->shouldBeRemoved()) { auto replacement = entity->createReplacement(); if (replacement) { - entity = std::move(replacement); // Replace in-place + entity = std::move(replacement); entities_need_sorting = true; } else { - entitiesToRemove.push_back(i); // Mark for removal + entitiesToRemove.push_back(i); } } } @@ -167,11 +188,10 @@ void Aquarium::redraw() { entities_need_sorting = true; } - // Add new entities if we have them - if (!newEntities.empty()) { - // Reserve space to minimize reallocations + // Add new entities if we have them and haven't exceeded max + if (!newEntities.empty() && + entities.size() < static_cast(g_config.max_entities)) { entities.reserve(entities.size() + newEntities.size()); - for (auto &newEntity : newEntities) { entities.emplace_back(std::move(newEntity)); } @@ -185,9 +205,49 @@ void Aquarium::redraw() { entity->draw(); } + // Draw debug information + if (g_config.show_fps || g_config.show_entity_count) { + drawDebugInfo(); + } + renderToScreen(); } +void Aquarium::drawDebugInfo() { + static double last_fps = 0.0; + static int frame_counter = 0; + static auto last_time = std::chrono::steady_clock::now(); + + frame_counter++; + auto current_time = std::chrono::steady_clock::now(); + auto elapsed = std::chrono::duration_cast( + current_time - last_time) + .count(); + + if (elapsed >= 1000) { + last_fps = (frame_counter * 1000.0) / elapsed; + frame_counter = 0; + last_time = current_time; + } + + std::stringstream debug_info; + if (g_config.show_fps) { + debug_info << "FPS: " << std::fixed << std::setprecision(1) << last_fps; + } + if (g_config.show_entity_count) { + if (g_config.show_fps) + debug_info << " | "; + debug_info << "Entities: " << entities.size(); + } + + std::string debug_str = debug_info.str(); + if (!debug_str.empty()) { + std::string color_str(debug_str.length(), 'w'); // White color + drawToFrame(0, width - static_cast(debug_str.length()), debug_str, + color_str); + } +} + void Aquarium::resize() { printf("%s%s%s", ANSI::CLEAR_SCREEN, ANSI::CURSOR_HOME, ANSI::BG_BLACK); fflush(stdout); @@ -202,10 +262,24 @@ void Aquarium::resize() { addWaterline(); addCastle(); - for (int i = 0; i < width / 15; i++) + + // Use configured seaweed count or auto-calculate + int seaweed_count = g_config.initial_seaweed_count; + if (seaweed_count == -1) { + seaweed_count = width / 15; + } + for (int i = 0; i < seaweed_count; i++) { addSeaweed(); - for (int i = 0; i < width * (height - 9) / 350; i++) + } + + // Use configured fish count or auto-calculate + int fish_count = g_config.initial_fish_count; + if (fish_count == -1) { + fish_count = width * (height - 9) / 350; + } + for (int i = 0; i < fish_count; i++) { addFish(); + } } void Aquarium::addFish() { addEntityImpl(); } @@ -240,8 +314,10 @@ void Aquarium::ensureBigEntityExists() { } void Aquarium::clearCurrentFrame() { + static const Cell empty_cell{}; + for (auto &row : currentFrame) { - std::fill(row.begin(), row.end(), Cell()); + row.assign(width, empty_cell); } } @@ -303,11 +379,18 @@ void Aquarium::renderToScreen() { // Apply cell formatting and character output += ANSI::RESET_BLACK_BG; - if (newCell.bold) - output += ANSI::BOLD; - output += colorLookup[static_cast(newCell.colorChar)]; - output += newCell.ch; + // Only apply bold if configured + if (g_config.use_bold && newCell.bold) { + output += ANSI::BOLD; + } + + // Only apply colors if configured + if (g_config.use_colors) { + output += colorLookup[static_cast(newCell.colorChar)]; + } + + output += newCell.ch; ++cursor_x; } } diff --git a/src/Aquarium.h b/src/core/Aquarium.h similarity index 97% rename from src/Aquarium.h rename to src/core/Aquarium.h index 5464b87..1b3f603 100644 --- a/src/Aquarium.h +++ b/src/core/Aquarium.h @@ -1,5 +1,5 @@ #pragma once -#include "Entity.h" +#include "../entities/Entity.h" #include #include @@ -29,6 +29,7 @@ private: bool entities_need_sorting = true; static inline const char *colorLookup[256] = {nullptr}; static inline bool colorLookupInitialized = false; + void drawDebugInfo(); public: Aquarium(); diff --git a/src/core/Config.cpp b/src/core/Config.cpp new file mode 100644 index 0000000..6f12ebb --- /dev/null +++ b/src/core/Config.cpp @@ -0,0 +1,175 @@ +#include "Config.h" +#include +#include +#include +#include + +AquariumConfig g_config; + +void printUsage(const char *program_name) { + std::cout << "Usage: " << program_name << " [OPTIONS]\n\n"; + std::cout << "Aquarium screensaver with customizable settings\n\n"; + std::cout << "OPTIONS:\n"; + std::cout << " -h, --help Show this help message\n"; + std::cout + << " -f, --fish COUNT Number of initial fish (default: auto)\n"; + std::cout << " -s, --seaweed COUNT Number of seaweed plants (default: " + "auto)\n"; + std::cout << " -b, --max-bubbles COUNT Maximum bubbles on screen " + "(default: 50)\n"; + std::cout << " -d, --delay MS Frame delay in milliseconds " + "(default: 100)\n"; + std::cout << " -r, --bubble-rate RATE Fish bubble spawn rate 1/N " + "(default: 10)\n"; + std::cout << " -m, --max-entities COUNT Maximum entities on screen " + "(default: 200)\n"; + std::cout << " --no-big-entities Disable ships, whales, and sea " + "monsters\n"; + std::cout << " --no-bubbles Disable bubble generation\n"; + std::cout << " --no-colors Disable colors (monochrome mode)\n"; + std::cout << " --no-bold Disable bold text\n"; + std::cout << " --show-fps Display FPS counter\n"; + std::cout << " --show-count Display entity count\n"; + std::cout << " --debug Enable debug mode\n"; + std::cout << "\nShort options can be combined: -f20 -s5 -d50\n"; + std::cout << "Long options accept = syntax: --fish=20 --delay=50\n"; + std::cout << "\nExamples:\n"; + std::cout << " " << program_name + << " -f20 -s5 -d50 # Fast aquarium with lots of fish\n"; + std::cout << " " << program_name + << " --fish=10 --no-colors # 10 fish, monochrome\n"; + std::cout << " " << program_name + << " --debug --show-fps # Debug mode with FPS\n"; +} + +bool parseArguments(int argc, char *argv[]) { + // Define long options + static const struct option long_options[] = { + {"help", no_argument, nullptr, 'h'}, + {"fish", required_argument, nullptr, 'f'}, + {"seaweed", required_argument, nullptr, 's'}, + {"max-bubbles", required_argument, nullptr, 'b'}, + {"delay", required_argument, nullptr, 'd'}, + {"bubble-rate", required_argument, nullptr, 'r'}, + {"max-entities", required_argument, nullptr, 'm'}, + {"no-big-entities", no_argument, nullptr, 'B'}, + {"no-bubbles", no_argument, nullptr, 'N'}, + {"no-colors", no_argument, nullptr, 'C'}, + {"no-bold", no_argument, nullptr, 'O'}, + {"show-fps", no_argument, nullptr, 'F'}, + {"show-count", no_argument, nullptr, 'S'}, + {"debug", no_argument, nullptr, 'D'}, + {nullptr, 0, nullptr, 0}}; + + // Short options string - : after letter means it takes an argument + const char *short_options = "hf:s:b:d:r:m:BNCOFSD"; + + int option; + int option_index = 0; + + // Reset getopt state (important for testing) + optind = 1; + + while ((option = getopt_long(argc, argv, short_options, long_options, + &option_index)) != -1) { + switch (option) { + case 'h': + printUsage(argv[0]); + return false; + + case 'f': + g_config.initial_fish_count = std::atoi(optarg); + if (g_config.initial_fish_count < -1) { + std::cerr << "Error: Fish count must be >= -1\n"; + return false; + } + break; + + case 's': + g_config.initial_seaweed_count = std::atoi(optarg); + if (g_config.initial_seaweed_count < -1) { + std::cerr << "Error: Seaweed count must be >= -1\n"; + return false; + } + break; + + case 'b': + g_config.max_bubbles = std::atoi(optarg); + if (g_config.max_bubbles < 0) { + std::cerr << "Error: Max bubbles must be >= 0\n"; + return false; + } + break; + + case 'd': + g_config.frame_delay_ms = std::atoi(optarg); + if (g_config.frame_delay_ms < 1) { + std::cerr << "Error: Frame delay must be >= 1ms\n"; + return false; + } + break; + + case 'r': + g_config.fish_bubble_rate = std::atoi(optarg); + if (g_config.fish_bubble_rate < 1) { + std::cerr << "Error: Bubble rate must be >= 1\n"; + return false; + } + break; + + case 'm': + g_config.max_entities = std::atoi(optarg); + if (g_config.max_entities < 1) { + std::cerr << "Error: Max entities must be >= 1\n"; + return false; + } + break; + + case 'B': + g_config.enable_big_entities = false; + break; + + case 'N': + g_config.enable_bubbles = false; + break; + + case 'C': + g_config.use_colors = false; + break; + + case 'O': + g_config.use_bold = false; + break; + + case 'F': + g_config.show_fps = true; + break; + + case 'S': + g_config.show_entity_count = true; + break; + + case 'D': + g_config.debug_mode = true; + break; + + case '?': + // getopt_long already printed an error message + std::cerr << "Use --help for usage information\n"; + return false; + + default: + std::cerr << "Error: Unexpected option character\n"; + return false; + } + } + + // Check for non-option arguments + if (optind < argc) { + std::cerr << "Error: Unexpected argument: " << argv[optind] << "\n"; + std::cerr << "Use --help for usage information\n"; + return false; + } + + return true; +} diff --git a/src/core/Config.h b/src/core/Config.h new file mode 100644 index 0000000..a0f3277 --- /dev/null +++ b/src/core/Config.h @@ -0,0 +1,33 @@ +#pragma once +#include + +struct AquariumConfig { + // Entity spawn settings + int initial_fish_count = -1; // -1 means auto-calculate + int initial_seaweed_count = -1; // -1 means auto-calculate + int max_bubbles = 50; + + // Animation settings + int frame_delay_ms = 100; + bool enable_big_entities = true; + bool enable_bubbles = true; + + // Visual settings + bool use_colors = true; + bool use_bold = true; + + // Spawn rates (lower = more frequent) + int fish_bubble_rate = 10; // 1 in N chance per frame + int big_entity_spawn_delay = 100; // frames between big entities + + // Performance settings + bool optimize_rendering = true; + int max_entities = 200; + + // Debug settings + bool show_fps = false; + bool show_entity_count = false; + bool debug_mode = false; +}; + +extern AquariumConfig g_config; diff --git a/src/core/main.cpp b/src/core/main.cpp new file mode 100644 index 0000000..9c304df --- /dev/null +++ b/src/core/main.cpp @@ -0,0 +1,115 @@ +#include "Aquarium.h" +#include "Config.h" +#include +#include +#include + +#ifdef __OpenBSD__ +#include +#endif + +// Forward declaration +bool parseArguments(int argc, char *argv[]); + +int main(int argc, char *argv[]) { + // Parse command line arguments + if (!parseArguments(argc, argv)) { + return 1; // Exit if parsing failed or help was shown + } + + // Print configuration if debug mode is enabled + if (g_config.debug_mode) { + std::cout << "Configuration:\n"; + std::cout << " Fish count: " + << (g_config.initial_fish_count == -1 + ? "auto" + : std::to_string(g_config.initial_fish_count)) + << "\n"; + std::cout << " Seaweed count: " + << (g_config.initial_seaweed_count == -1 + ? "auto" + : std::to_string(g_config.initial_seaweed_count)) + << "\n"; + std::cout << " Max bubbles: " << g_config.max_bubbles << "\n"; + std::cout << " Frame delay: " << g_config.frame_delay_ms << "ms\n"; + std::cout << " Big entities: " + << (g_config.enable_big_entities ? "enabled" : "disabled") + << "\n"; + std::cout << " Bubbles: " + << (g_config.enable_bubbles ? "enabled" : "disabled") << "\n"; + std::cout << " Colors: " << (g_config.use_colors ? "enabled" : "disabled") + << "\n"; + std::cout << " Bold text: " << (g_config.use_bold ? "enabled" : "disabled") + << "\n"; + std::cout << " Max entities: " << g_config.max_entities << "\n"; + std::cout << "Press any key to continue...\n"; + std::cin.get(); + } + + Aquarium &aquarium = Aquarium::getInstance(); + +#ifdef __OpenBSD__ + if (pledge("stdio tty", NULL) == -1) { + perror("pledge"); + return 1; + } +#endif + + // Initialize the aquarium display + aquarium.resize(); // Setup initial entities + + // Variables for FPS calculation + auto last_time = std::chrono::steady_clock::now(); + int frame_count = 0; + double fps = 0.0; + + // Main game loop + while (true) { + auto frame_start = std::chrono::steady_clock::now(); + + int input = aquarium.checkInput(); + if (input == 'q' || input == 'Q' || input == 27) { // ESC key + break; + } + + // Toggle debug info with 'd' key + if (input == 'd' || input == 'D') { + g_config.show_fps = !g_config.show_fps; + g_config.show_entity_count = !g_config.show_entity_count; + } + + if (aquarium.checkResize()) { + aquarium.resize(); + } + + aquarium.redraw(); + + // Calculate FPS + if (g_config.show_fps) { + ++frame_count; + auto current_time = std::chrono::steady_clock::now(); + auto elapsed = std::chrono::duration_cast( + current_time - last_time) + .count(); + + if (elapsed >= 1000) { // Update FPS every second + fps = (frame_count * 1000.0) / elapsed; + frame_count = 0; + last_time = current_time; + } + } + + // Sleep for configured frame delay + auto frame_end = std::chrono::steady_clock::now(); + auto frame_duration = std::chrono::duration_cast( + frame_end - frame_start); + auto sleep_duration = + std::chrono::milliseconds(g_config.frame_delay_ms) - frame_duration; + + if (sleep_duration > std::chrono::milliseconds(0)) { + std::this_thread::sleep_for(sleep_duration); + } + } + + return 0; +} diff --git a/src/Bubble.cpp b/src/entities/Bubble.cpp similarity index 100% rename from src/Bubble.cpp rename to src/entities/Bubble.cpp diff --git a/src/Bubble.h b/src/entities/Bubble.h similarity index 100% rename from src/Bubble.h rename to src/entities/Bubble.h diff --git a/src/Castle.cpp b/src/entities/Castle.cpp similarity index 76% rename from src/Castle.cpp rename to src/entities/Castle.cpp index 33bd46b..98a861b 100644 --- a/src/Castle.cpp +++ b/src/entities/Castle.cpp @@ -1,6 +1,6 @@ #include "Castle.h" -#include "Aquarium.h" -#include "assets/CastleAssets.h" +#include "../assets/CastleAssets.h" +#include "../core/Aquarium.h" Castle::Castle() : Entity(Aquarium::getInstance().getWidth() - 32, diff --git a/src/Castle.h b/src/entities/Castle.h similarity index 100% rename from src/Castle.h rename to src/entities/Castle.h diff --git a/src/Entity.cpp b/src/entities/Entity.cpp similarity index 98% rename from src/Entity.cpp rename to src/entities/Entity.cpp index 0b97388..b99e791 100644 --- a/src/Entity.cpp +++ b/src/entities/Entity.cpp @@ -1,5 +1,5 @@ #include "Entity.h" -#include "Aquarium.h" +#include "../core/Aquarium.h" void Entity::draw() const { auto &aquarium = Aquarium::getInstance(); diff --git a/src/Entity.h b/src/entities/Entity.h similarity index 100% rename from src/Entity.h rename to src/entities/Entity.h diff --git a/src/Fish.cpp b/src/entities/Fish.cpp similarity index 93% rename from src/Fish.cpp rename to src/entities/Fish.cpp index d7ae5d4..6d5ced0 100644 --- a/src/Fish.cpp +++ b/src/entities/Fish.cpp @@ -1,8 +1,8 @@ #include "Fish.h" -#include "Aquarium.h" -#include "Random.h" -#include "assets/FishAssets.h" -#include "defs.h" +#include "../assets/FishAssets.h" +#include "../core/Aquarium.h" +#include "../utils/Random.h" +#include "../utils/defs.h" std::unordered_map Fish::color_map; diff --git a/src/Fish.h b/src/entities/Fish.h similarity index 96% rename from src/Fish.h rename to src/entities/Fish.h index 9addd0e..f4839ba 100644 --- a/src/Fish.h +++ b/src/entities/Fish.h @@ -1,6 +1,6 @@ #pragma once +#include "../assets/FishAssets.h" #include "Entity.h" -#include "assets/FishAssets.h" #include #include diff --git a/src/SeaMonster.cpp b/src/entities/SeaMonster.cpp similarity index 92% rename from src/SeaMonster.cpp rename to src/entities/SeaMonster.cpp index 1df34d5..333e0c6 100644 --- a/src/SeaMonster.cpp +++ b/src/entities/SeaMonster.cpp @@ -1,7 +1,7 @@ #include "SeaMonster.h" -#include "Aquarium.h" -#include "Random.h" -#include "assets/SeaMonsterAssets.h" +#include "../assets/SeaMonsterAssets.h" +#include "../core/Aquarium.h" +#include "../utils/Random.h" SeaMonster::SeaMonster() : SeaMonster(getRandomDirection()) {} diff --git a/src/SeaMonster.h b/src/entities/SeaMonster.h similarity index 95% rename from src/SeaMonster.h rename to src/entities/SeaMonster.h index d6b1bcc..989f4dd 100644 --- a/src/SeaMonster.h +++ b/src/entities/SeaMonster.h @@ -1,6 +1,6 @@ #pragma once +#include "../assets/SeaMonsterAssets.h" #include "Entity.h" -#include "assets/SeaMonsterAssets.h" class SeaMonster : public Entity { private: diff --git a/src/Seaweed.cpp b/src/entities/Seaweed.cpp similarity index 94% rename from src/Seaweed.cpp rename to src/entities/Seaweed.cpp index 0d1087f..a6e5b5a 100644 --- a/src/Seaweed.cpp +++ b/src/entities/Seaweed.cpp @@ -1,7 +1,7 @@ #include "Seaweed.h" -#include "Aquarium.h" -#include "Random.h" -#include "defs.h" +#include "../core/Aquarium.h" +#include "../utils/Random.h" +#include "../utils/defs.h" Seaweed::Seaweed() : Entity(), diff --git a/src/Seaweed.h b/src/entities/Seaweed.h similarity index 100% rename from src/Seaweed.h rename to src/entities/Seaweed.h diff --git a/src/Ship.cpp b/src/entities/Ship.cpp similarity index 87% rename from src/Ship.cpp rename to src/entities/Ship.cpp index e7e1ff9..f662607 100644 --- a/src/Ship.cpp +++ b/src/entities/Ship.cpp @@ -1,7 +1,7 @@ #include "Ship.h" -#include "Aquarium.h" -#include "Random.h" -#include "assets/ShipAssets.h" +#include "../assets/ShipAssets.h" +#include "../core/Aquarium.h" +#include "../utils/Random.h" Ship::Ship() : Ship(getRandomDirection()) {} diff --git a/src/Ship.h b/src/entities/Ship.h similarity index 94% rename from src/Ship.h rename to src/entities/Ship.h index 4acfee4..4028574 100644 --- a/src/Ship.h +++ b/src/entities/Ship.h @@ -1,6 +1,6 @@ #pragma once +#include "../assets/ShipAssets.h" #include "Entity.h" -#include "assets/ShipAssets.h" class Ship : public Entity { private: diff --git a/src/Waterline.cpp b/src/entities/Waterline.cpp similarity index 96% rename from src/Waterline.cpp rename to src/entities/Waterline.cpp index 03522ba..048ac9f 100644 --- a/src/Waterline.cpp +++ b/src/entities/Waterline.cpp @@ -1,7 +1,7 @@ #include "Waterline.h" -#include "Aquarium.h" -#include "Random.h" -#include "defs.h" +#include "../core/Aquarium.h" +#include "../utils/Random.h" +#include "../utils/defs.h" Waterline::Waterline() : Entity(0, WATERLINE_Y) { shape[0] = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; diff --git a/src/Waterline.h b/src/entities/Waterline.h similarity index 100% rename from src/Waterline.h rename to src/entities/Waterline.h diff --git a/src/Whale.cpp b/src/entities/Whale.cpp similarity index 92% rename from src/Whale.cpp rename to src/entities/Whale.cpp index 435e980..cbcb47e 100644 --- a/src/Whale.cpp +++ b/src/entities/Whale.cpp @@ -1,7 +1,7 @@ #include "Whale.h" -#include "Aquarium.h" -#include "Random.h" -#include "assets/WhaleAssets.h" +#include "../assets/WhaleAssets.h" +#include "../core/Aquarium.h" +#include "../utils/Random.h" Whale::Whale() : Whale(getRandomDirection()) {} diff --git a/src/Whale.h b/src/entities/Whale.h similarity index 95% rename from src/Whale.h rename to src/entities/Whale.h index 0768b90..15f095d 100644 --- a/src/Whale.h +++ b/src/entities/Whale.h @@ -1,6 +1,6 @@ #pragma once +#include "../assets/WhaleAssets.h" #include "Entity.h" -#include "assets/WhaleAssets.h" class Whale : public Entity { private: diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index 359297c..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "Aquarium.h" -#ifdef __OpenBSD__ -#include -#endif - -int main() { - Aquarium &aquarium = Aquarium::getInstance(); - -#ifdef __OpenBSD__ - if (pledge("stdio tty", NULL) == -1) { - perror("pledge"); - return 1; - } -#endif - - // Initialize the aquarium display - aquarium.resize(); // Setup initial entities - - // Main game loop - while (true) { - int input = aquarium.checkInput(); - if (input == 'q' || input == 'Q' || input == 27) { // ESC key - break; - } - - if (aquarium.checkResize()) { - aquarium.resize(); - } - - aquarium.redraw(); - } - - return 0; -} diff --git a/src/Random.h b/src/utils/Random.h similarity index 100% rename from src/Random.h rename to src/utils/Random.h diff --git a/src/SpriteUtils.h b/src/utils/SpriteUtils.h similarity index 100% rename from src/SpriteUtils.h rename to src/utils/SpriteUtils.h diff --git a/src/defs.h b/src/utils/defs.h similarity index 100% rename from src/defs.h rename to src/utils/defs.h