From 5706c90f87275118c21c2d7186a415b56623a038 Mon Sep 17 00:00:00 2001 From: Andrew Kloet Date: Mon, 7 Jul 2025 14:57:52 -0400 Subject: [PATCH] store only one direction of sprites --- Makefile | 2 +- src/Entity.cpp | 24 ++++ src/Entity.h | 6 +- src/assets/FishAssets.h | 272 +++++++-------------------------------- src/assets/SpriteUtils.h | 68 ++++++++++ 5 files changed, 143 insertions(+), 229 deletions(-) create mode 100644 src/assets/SpriteUtils.h diff --git a/Makefile b/Makefile index 21495d5..e60560d 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # Compiler and flags CXX = g++ -CXXFLAGS = -std=c++17 -Wall -Wextra -O3 -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables +CXXFLAGS = -std=c++17 -Wall -Wextra -Os -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables LDFLAGS = -lncurses -ltinfo -Wl,--gc-sections -s # Directories diff --git a/src/Entity.cpp b/src/Entity.cpp index 9a1e9c3..1237940 100644 --- a/src/Entity.cpp +++ b/src/Entity.cpp @@ -1,5 +1,6 @@ #include "Entity.h" #include "Aquarium.h" +#include void Entity::draw() const { auto &aquarium = Aquarium::getInstance(); @@ -55,3 +56,26 @@ void Entity::draw() const { } } } + +size_t Entity::getMaxRowWidth(const std::vector &image) noexcept { + if (image.empty()) { + return 0; + } + + size_t max_width = 0; + for (const auto &row : image) { + max_width = std::max(max_width, row.length()); + } + + return max_width; +} + +bool Entity::shouldBeRemoved() const noexcept { + const auto &aquarium = Aquarium::getInstance(); + const auto ¤t_image = getImage(); + const float entity_width = static_cast(getMaxRowWidth(current_image)); + + // Default implementation: remove if completely off-screen + return (x + entity_width < 0) || + (x > static_cast(aquarium.getWidth())); +} diff --git a/src/Entity.h b/src/Entity.h index 0d8c65b..8e8fe1b 100644 --- a/src/Entity.h +++ b/src/Entity.h @@ -30,9 +30,13 @@ public: virtual const std::vector &getMask() const = 0; virtual char getDefaultColor() const noexcept = 0; - virtual bool shouldBeRemoved() const noexcept = 0; + virtual bool shouldBeRemoved() const noexcept; virtual std::unique_ptr createReplacement() const { return nullptr; } virtual int getPreferredLayer() const noexcept = 0; void draw() const; + +protected: + // Helper function to get the maximum width of any row in an image + static size_t getMaxRowWidth(const std::vector &image) noexcept; }; diff --git a/src/assets/FishAssets.h b/src/assets/FishAssets.h index 9bd29ec..86b592a 100644 --- a/src/assets/FishAssets.h +++ b/src/assets/FishAssets.h @@ -1,235 +1,53 @@ #pragma once #include "../Entity.h" +#include "SpriteUtils.h" #include -inline std::vector fishAssetPairs = { - { - { - R"(???\)", - R"(??/ \)", - R"(>=_('>)", - R"(??\_/)", - R"(???/)" +// Store only right-facing fish assets (half the data!) +const std::vector rightFacingFishAssets = { + {{R"(???\??)", R"(??/ \?)", R"(>=_('>)", R"(??\_/?)", R"(???/??)"}, + {R"( 1 )", R"( 1 1 )", R"(663745)", R"( 111 )", R"( 3 )"}}, + {{R"(?????,????)", R"(?????}\???)", R"(\??.' `\?)", R"(}}< ( 6>)", + R"(/??`, .'?)", R"(?????}/???)", R"(?????'????)"}, + {R"( 2 )", R"( 22 )", R"(6 11 11 )", R"(661 7 45)", + R"(6 11 11 )", R"( 33 )", R"( 3 )"}}, + {{R"(???????,--,_????)", R"(__????_\.---'-.?)", R"(\ '.-" // o\)", + R"(/_.'-._ \\ /)", R"(???????`"--(/"`?)"}, + {R"( 22222 )", R"(66 121111211 )", R"(6 6111 77 41)", + R"(6661111 77 1)", R"( 11113311 )"}}, + {{R"(??__?)", R"(><_'>)", R"(???'?)"}, + {R"( 11 )", R"(61145)", R"( 3 )"}}, + {{R"(????????_.-`\??????)", R"(?????-:`_..,_\?????)", + R"(('-..:-` , '-.,?)", R"(?} _ ;':( o :)", + R"((.-`/'-.,__'` _.-`?)", R"(???`'-.,/??//`?????)"}, + {R"( 22222 )", R"( 222111112 )", + R"(66661111 7 1111 )", R"( 6 1 7777 4 1)", + R"(6666211111177 1111 )", R"( 222222 333 )"}}, + {{ + R"(????????/\??????)", + R"(????????\.\_????)", + R"(\'-,.:-` '-,?)", + R"( ) _ (>( o <)", + R"(/.-`?':._ _.-`?)", + R"(??????;/?``?????)", }, { - R"( 1)", - R"( 1 1)", - R"(663745)", - R"( 111)", - R"( 3)" - } - }, - { + R"( 22 )", + R"( 2121 )", + R"(66661111 111 )", + R"( 6 1 777 4 1)", + R"(6666 1111 1111 )", + R"( 22 33 )", + }}, + {{R"(_?????????_.*"\??????)", R"(\'-._..-*` `'*-.??)", + R"(?) , (( o >)", R"(/.`"*--.__)_.`_.-*`??)"}, { - R"(??/)", - R"(?/ \)", - R"(<')_=<)", - R"(?\_/)", - R"(??\)" - }, - { - R"( 2)", - R"( 111)", - R"(547366)", - R"( 111)", - R"( 3)" - } - }, - { - { - R"(?????,)", - R"(?????}\)", - R"(\??.' `\)", - R"(}}< ( 6>)", - R"(/??`, .')", - R"(?????}/)", - R"(?????')" - }, - { - R"( 2)", - R"( 22)", - R"(6 11 11)", - R"(661 7 45)", - R"(6 11 11)", - R"( 33)", - R"( 3)" - } - }, - { - { - R"(????,)", - R"(???/{)", - R"(?/' `. /)", - R"(<6 ) >{{)", - R"(?`. ,' \)", - R"(???\{)", - R"(????`)" - }, - { - R"( 2)", - R"( 22)", - R"( 11 11 6)", - R"(54 7 166)", - R"( 11 11 6)", - R"( 33)", - R"( 3)" - } - }, - { - { - R"(???????,--,_)", - R"(__????_\.---'-.)", - R"(\ '.-" // o\)", - R"(/_.'-._ \\ /)", - R"(???????`"--(/"`)" - }, - { - R"( 22222)", - R"(66 121111211)", - R"(6 6111 77 41)", - R"(6661111 77 1)", - R"( 11113311)" - } - }, - { - { - R"(????_,--,)", - R"(?.-'---./_????__)", - R"(/o \\ "-.' /)", - R"(\ // _.-'._\)", - R"(?`"\)--"`)" - }, - { - R"( 22222)", - R"( 112111121 66)", - R"(14 77 1116 6)", - R"(1 77 1111666)", - R"( 11331111)" - } - }, - { - { - R"(??__)", - R"(><_'>)", - R"(???')" - }, - { - R"( 11)", - R"(61145)", - R"( 3)" - } - }, - { - { - R"(?__)", - R"(<'_><)", - R"(?`)" - }, - { - R"( 11)", - R"(54116)", - R"( 3)" - } - }, - { - { - R"(????????_.-`\)", - R"(?????-:`_..,_\)", - R"(('-..:-` , '-.,)", - R"(?} _ ;':( o :)", - R"((.-`/'-.,__'` _.-`)", - R"(???`'-.,/??//`)" - }, - { - R"( 22222)", - R"( 222111112)", - R"(66661111 7 1111)", - R"( 6 1 7777 4 1)", - R"(6666211111177 1111)", - R"( 222222 333)" - } - }, - { - { - R"(??????/`-._)", - R"(?????/_,.._`:-)", - R"(?,.-' , `-:..-'))", - R"(: o ):'; _ {)", - R"(?`-._ `'__,.-'\`-.))", - R"(?????`\\??\,.-'`)" - }, - { - R"( 22222)", - R"( 211111222)", - R"( 1111 7 11116666)", - R"(1 4 7777 1 6)", - R"( 1111 7711111126666)", - R"( 333 222222)" - } - }, - { - { - R"(????????/\)", - R"(????????\.\_)", - R"(\'-,.:-` '-,)", - R"( ) _ (>( o <)", - R"(/.-`?':._ _.-`)", - R"(??????;/?``)", - }, - { - R"( 22)", - R"( 2121)", - R"(66661111 111)", - R"( 6 1 777 4 1)", - R"(6666 1111 1111)", - R"( 22 33)", - } - }, - { - { - R"(??????/\)", - R"(????_/./)", - R"(?,-' `-:.,-'/)", - R"(> o )<) _ ()", - R"(?`-._ _.:'?`-.\)", - R"(?????``?\;)", - }, - { - R"( 22)", - R"( 1212)", - R"( 111 11116666)", - R"(1 4 777 1 6)", - R"( 1111 1111 6666)", - R"( 33 22)", - } - }, - { - { - R"(_?????????_.*"\)", - R"(\'-._..-*` `'*-.)", - R"(?) , (( o >)", - R"(/.`"*--.__)_.`_.-*`)" - }, - { - R"(6 11222)", - R"(6661111111 11111)", - R"( 6 3 77 4 1)", - R"(6661111111311311111)", - } - }, - { - { - R"(??????/"*._?????????_)", - R"(??.-*'` `*-.._.-'/)", - R"(< o )) , ()", - R"(??`*-._`._(__.--*"`.\)", - }, - { - R"( 22211 6)", - R"( 11111 1111111666)", - R"(1 4 77 3 6)", - R"( 1111131131111111666)", - }, - } -}; + R"(6 11222 )", + R"(6661111111 11111 )", + R"( 6 3 77 4 1)", + R"(6661111111311311111 )", + }}}; + +inline const std::vector fishAssetPairs = + SpriteUtils::createBidirectionalAssets(rightFacingFishAssets); diff --git a/src/assets/SpriteUtils.h b/src/assets/SpriteUtils.h new file mode 100644 index 0000000..6b5c94d --- /dev/null +++ b/src/assets/SpriteUtils.h @@ -0,0 +1,68 @@ +#pragma once +#include +#include +#include +#include + +struct AssetPair; + +namespace SpriteUtils { +// Character mapping for directional elements +const std::unordered_map charFlipMap = { + {'(', ')'}, {')', '('}, {'[', ']'}, {']', '['}, {'{', '}'}, {'}', '{'}, + {'<', '>'}, {'>', '<'}, {'/', '\\'}, {'\\', '/'}, {'`', '\''}, {'\'', '`'}, +}; + +// Mirror a single character (handle directional flipping) +inline char mirrorChar(char c) { + auto it = charFlipMap.find(c); + return (it != charFlipMap.end()) ? it->second : c; +} + +// Mirror a single row with proper character flipping +inline std::string mirrorRow(std::string row) { + // First reverse the string + std::reverse(row.begin(), row.end()); + + // Then flip directional characters + for (char &c : row) { + c = mirrorChar(c); + } + + return row; +} + +// Mirror an entire sprite +inline std::vector +mirrorSprite(const std::vector &sprite) { + std::vector mirrored; + mirrored.reserve(sprite.size()); + + for (const auto &row : sprite) { + mirrored.push_back(mirrorRow(row)); + } + + return mirrored; +} + +// Mirror an AssetPair +inline AssetPair mirrorAssetPair(const AssetPair &asset) { + return {mirrorSprite(asset.image), mirrorSprite(asset.mask)}; +} + +// Create bidirectional asset pairs from right-facing assets +inline std::vector +createBidirectionalAssets(const std::vector &rightFacingAssets) { + std::vector result; + result.reserve(rightFacingAssets.size() * 2); + + for (const auto &asset : rightFacingAssets) { + // Add right-facing version + result.push_back(asset); + // Add left-facing (mirrored) version + result.push_back(mirrorAssetPair(asset)); + } + + return result; +} +} // namespace SpriteUtils