commit b0ea0d087b1218f73451036ddc1fa5177420f0c3
parent b6a82e69043c927059c8367b8d0221fabd812534
Author: amrfti <andrew@kloet.net>
Date: Fri, 23 May 2025 11:06:54 -0400
refactor fish prepare for polymorphism
Diffstat:
4 files changed, 76 insertions(+), 64 deletions(-)
diff --git a/src/Entity.h b/src/Entity.h
@@ -5,15 +5,20 @@
#include <unordered_map>
#include <vector>
+struct AssetPair {
+ std::vector<std::string> image;
+ std::vector<std::string> mask;
+};
+
class Entity {
protected:
float x;
float y;
public:
- Entity() : x(0), y(0) {}
- virtual ~Entity() {}
+ Entity() : x(0.0f), y(0.0f) {}
+ virtual ~Entity() = default;
- inline float getX() const { return x; }
- inline float getY() const { return y; }
+ float getX() const noexcept { return x; }
+ float getY() const noexcept { return y; }
};
diff --git a/src/Fish.cpp b/src/Fish.cpp
@@ -4,81 +4,98 @@
#include "assets/FishAssets.h"
#include <ncurses.h>
-Fish::Fish() : Fish(getRandomFishAsset()) {}
+std::unordered_map<char, char> Fish::color_map;
-Fish::Fish(const FishAssetRef &pair)
- : Entity(),
- speed((pair.index % 2 == 0) ? Random::floatInRange(0.25, 2.25)
- : -Random::floatInRange(0.25, 2.25)),
- image(pair.asset.image), mask(pair.asset.mask) {
- y = Random::intInRange(image.size() + 6,
- Aquarium::getInstance().getHeight() - image.size());
+Fish::Fish() : Fish(getRandomAssetIndex()) {}
- x = (speed < 0) ? Aquarium::getInstance().getWidth() : -20;
+Fish::Fish(int asset_index)
+ : Entity(), image(fishAssetPairs[asset_index].image),
+ mask(fishAssetPairs[asset_index].mask),
+ speed(Random::floatInRange(0.25f, 2.25f)),
+ moving_right(asset_index % 2 == 0) {
+ const auto &aquarium = Aquarium::getInstance();
+
+ y = Random::intInRange(static_cast<int>(image.size()) + 6,
+ aquarium.getHeight() - static_cast<int>(image.size()));
+
+ x = moving_right ? -20.0f : static_cast<float>(aquarium.getWidth());
randomizeMask();
}
void Fish::randomizeMask() {
- std::unordered_map<char, char> colorMap{{'4', 'W'}};
+ // Clear and rebuild color map
+ color_map.clear();
+ color_map['4'] = 'W'; // White is always '4'
+ // Assign random colors to digits 1-3, 5-9
for (char digit = '1'; digit <= '9'; ++digit) {
if (digit != '4') {
- colorMap[digit] =
- availableColors[Random::intInRange(0, availableColors.size() - 1)];
+ color_map[digit] = AVAILABLE_COLORS[Random::intInRange(
+ 0, static_cast<int>(AVAILABLE_COLORS.size()) - 1)];
}
}
+ // Apply color mapping to mask
for (auto &line : mask) {
for (char &ch : line) {
- if (auto it = colorMap.find(ch); it != colorMap.end()) {
+ if (auto it = color_map.find(ch); it != color_map.end()) {
ch = it->second;
}
}
}
}
-Fish::FishAssetRef Fish::getRandomFishAsset() {
- int index =
- Random::intInRange(0, static_cast<int>(fishAssetPairs.size()) - 1);
- return FishAssetRef{index, fishAssetPairs[index]};
+int Fish::getRandomAssetIndex() {
+ return Random::intInRange(0, static_cast<int>(fishAssetPairs.size()) - 1);
}
-void Fish::update() { x += speed; }
+void Fish::update() noexcept { x += moving_right ? speed : -speed; }
+
+void Fish::draw(int layer) const {
+ auto &aquarium = Aquarium::getInstance();
+
+ // Pre-allocate strings to avoid repeated allocations
+ std::string current_segment;
+ std::string current_colors;
+ current_segment.reserve(32); // Reserve reasonable capacity
+ current_colors.reserve(32);
-void Fish::draw(int layer) {
- Aquarium &aq = Aquarium::getInstance();
+ const int base_x = static_cast<int>(x);
+ const int base_y = static_cast<int>(y);
for (size_t i = 0; i < image.size(); ++i) {
const std::string &row = image[i];
- const std::string &maskRow = (i < mask.size()) ? mask[i] : "";
+ const std::string &mask_row = (i < mask.size()) ? mask[i] : "";
- int baseY = y + static_cast<int>(i);
- int cursorX = static_cast<int>(x);
- std::string currentSegment;
- std::string currentColors;
+ int cursor_x = base_x;
+ current_segment.clear();
+ current_colors.clear();
for (size_t j = 0; j < row.size(); ++j) {
- char ch = row[j];
+ const char ch = row[j];
if (ch == '?') {
- if (!currentSegment.empty()) {
- aq.drawToBackBuffer(baseY, cursorX, layer, currentSegment,
- currentColors);
- cursorX += currentSegment.size();
- currentSegment.clear();
- currentColors.clear();
+ // Flush current segment if not empty
+ if (!current_segment.empty()) {
+ aquarium.drawToBackBuffer(base_y + static_cast<int>(i), cursor_x,
+ layer, current_segment, current_colors);
+ cursor_x += static_cast<int>(current_segment.size());
+ current_segment.clear();
+ current_colors.clear();
}
- cursorX += 1;
+ ++cursor_x; // Skip transparent character
continue;
}
- currentSegment.push_back(ch);
- currentColors.push_back((j < maskRow.size()) ? maskRow[j] : 'k');
+ current_segment.push_back(ch);
+ current_colors.push_back((j < mask_row.size()) ? mask_row[j] : 'k');
}
- if (!currentSegment.empty()) {
- aq.drawToBackBuffer(baseY, cursorX, layer, currentSegment, currentColors);
+ // Flush remaining segment
+ if (!current_segment.empty()) {
+ aquarium.drawToBackBuffer(base_y + static_cast<int>(i), cursor_x, layer,
+ current_segment, current_colors);
}
}
}
diff --git a/src/Fish.h b/src/Fish.h
@@ -5,28 +5,23 @@
class Fish : public Entity {
private:
- struct FishAssetRef {
- int index;
- FishAsset &asset;
- };
-
- Fish(const FishAssetRef &ref);
- static bool initialized;
-
- const std::vector<std::string> ℑ
- std::vector<std::string> &mask;
-
- static constexpr std::array<char, 12> availableColors = {
+ static constexpr std::array<char, 12> AVAILABLE_COLORS = {
'c', 'C', 'r', 'R', 'y', 'Y', 'b', 'B', 'g', 'G', 'm', 'M'};
+ const std::vector<std::string> ℑ
+ std::vector<std::string> mask; // Copy needed for color randomization
const float speed;
- static FishAssetRef getRandomFishAsset();
+ const bool moving_right;
+
+ // Static color map to avoid recreation
+ static std::unordered_map<char, char> color_map;
- static void initializeFishAssets();
+ explicit Fish(int asset_index);
+ static int getRandomAssetIndex();
void randomizeMask();
public:
Fish();
- void update();
- void draw(int layer);
+ void update() noexcept;
+ void draw(int layer) const;
};
diff --git a/src/assets/FishAssets.h b/src/assets/FishAssets.h
@@ -1,14 +1,9 @@
#pragma once
-#include <string>
+#include "../Entity.h"
#include <vector>
-struct FishAsset {
- std::vector<std::string> image;
- std::vector<std::string> mask;
-};
-
-inline std::vector<FishAsset> fishAssetPairs = {
+inline std::vector<AssetPair> fishAssetPairs = {
{
{
R"(???\)",