refactor fish prepare for polymorphism
This commit is contained in:
13
src/Entity.h
13
src/Entity.h
@@ -5,15 +5,20 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
struct AssetPair {
|
||||||
|
std::vector<std::string> image;
|
||||||
|
std::vector<std::string> mask;
|
||||||
|
};
|
||||||
|
|
||||||
class Entity {
|
class Entity {
|
||||||
protected:
|
protected:
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Entity() : x(0), y(0) {}
|
Entity() : x(0.0f), y(0.0f) {}
|
||||||
virtual ~Entity() {}
|
virtual ~Entity() = default;
|
||||||
|
|
||||||
inline float getX() const { return x; }
|
float getX() const noexcept { return x; }
|
||||||
inline float getY() const { return y; }
|
float getY() const noexcept { return y; }
|
||||||
};
|
};
|
||||||
|
|||||||
91
src/Fish.cpp
91
src/Fish.cpp
@@ -4,81 +4,98 @@
|
|||||||
#include "assets/FishAssets.h"
|
#include "assets/FishAssets.h"
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
|
|
||||||
Fish::Fish() : Fish(getRandomFishAsset()) {}
|
std::unordered_map<char, char> Fish::color_map;
|
||||||
|
|
||||||
Fish::Fish(const FishAssetRef &pair)
|
Fish::Fish() : Fish(getRandomAssetIndex()) {}
|
||||||
: 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());
|
|
||||||
|
|
||||||
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();
|
randomizeMask();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fish::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) {
|
for (char digit = '1'; digit <= '9'; ++digit) {
|
||||||
if (digit != '4') {
|
if (digit != '4') {
|
||||||
colorMap[digit] =
|
color_map[digit] = AVAILABLE_COLORS[Random::intInRange(
|
||||||
availableColors[Random::intInRange(0, availableColors.size() - 1)];
|
0, static_cast<int>(AVAILABLE_COLORS.size()) - 1)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply color mapping to mask
|
||||||
for (auto &line : mask) {
|
for (auto &line : mask) {
|
||||||
for (char &ch : line) {
|
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;
|
ch = it->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Fish::FishAssetRef Fish::getRandomFishAsset() {
|
int Fish::getRandomAssetIndex() {
|
||||||
int index =
|
return Random::intInRange(0, static_cast<int>(fishAssetPairs.size()) - 1);
|
||||||
Random::intInRange(0, static_cast<int>(fishAssetPairs.size()) - 1);
|
|
||||||
return FishAssetRef{index, fishAssetPairs[index]};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fish::update() { x += speed; }
|
void Fish::update() noexcept { x += moving_right ? speed : -speed; }
|
||||||
|
|
||||||
void Fish::draw(int layer) {
|
void Fish::draw(int layer) const {
|
||||||
Aquarium &aq = Aquarium::getInstance();
|
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);
|
||||||
|
|
||||||
|
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) {
|
for (size_t i = 0; i < image.size(); ++i) {
|
||||||
const std::string &row = image[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 cursor_x = base_x;
|
||||||
int cursorX = static_cast<int>(x);
|
current_segment.clear();
|
||||||
std::string currentSegment;
|
current_colors.clear();
|
||||||
std::string currentColors;
|
|
||||||
|
|
||||||
for (size_t j = 0; j < row.size(); ++j) {
|
for (size_t j = 0; j < row.size(); ++j) {
|
||||||
char ch = row[j];
|
const char ch = row[j];
|
||||||
|
|
||||||
if (ch == '?') {
|
if (ch == '?') {
|
||||||
if (!currentSegment.empty()) {
|
// Flush current segment if not empty
|
||||||
aq.drawToBackBuffer(baseY, cursorX, layer, currentSegment,
|
if (!current_segment.empty()) {
|
||||||
currentColors);
|
aquarium.drawToBackBuffer(base_y + static_cast<int>(i), cursor_x,
|
||||||
cursorX += currentSegment.size();
|
layer, current_segment, current_colors);
|
||||||
currentSegment.clear();
|
cursor_x += static_cast<int>(current_segment.size());
|
||||||
currentColors.clear();
|
current_segment.clear();
|
||||||
|
current_colors.clear();
|
||||||
}
|
}
|
||||||
cursorX += 1;
|
++cursor_x; // Skip transparent character
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentSegment.push_back(ch);
|
current_segment.push_back(ch);
|
||||||
currentColors.push_back((j < maskRow.size()) ? maskRow[j] : 'k');
|
current_colors.push_back((j < mask_row.size()) ? mask_row[j] : 'k');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!currentSegment.empty()) {
|
// Flush remaining segment
|
||||||
aq.drawToBackBuffer(baseY, cursorX, layer, currentSegment, currentColors);
|
if (!current_segment.empty()) {
|
||||||
|
aquarium.drawToBackBuffer(base_y + static_cast<int>(i), cursor_x, layer,
|
||||||
|
current_segment, current_colors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
27
src/Fish.h
27
src/Fish.h
@@ -5,28 +5,23 @@
|
|||||||
|
|
||||||
class Fish : public Entity {
|
class Fish : public Entity {
|
||||||
private:
|
private:
|
||||||
struct FishAssetRef {
|
static constexpr std::array<char, 12> AVAILABLE_COLORS = {
|
||||||
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 = {
|
|
||||||
'c', 'C', 'r', 'R', 'y', 'Y', 'b', 'B', 'g', 'G', 'm', 'M'};
|
'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;
|
const float speed;
|
||||||
static FishAssetRef getRandomFishAsset();
|
const bool moving_right;
|
||||||
|
|
||||||
static void initializeFishAssets();
|
// Static color map to avoid recreation
|
||||||
|
static std::unordered_map<char, char> color_map;
|
||||||
|
|
||||||
|
explicit Fish(int asset_index);
|
||||||
|
static int getRandomAssetIndex();
|
||||||
void randomizeMask();
|
void randomizeMask();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Fish();
|
Fish();
|
||||||
void update();
|
void update() noexcept;
|
||||||
void draw(int layer);
|
void draw(int layer) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include "../Entity.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct FishAsset {
|
inline std::vector<AssetPair> fishAssetPairs = {
|
||||||
std::vector<std::string> image;
|
|
||||||
std::vector<std::string> mask;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline std::vector<FishAsset> fishAssetPairs = {
|
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
R"(???\)",
|
R"(???\)",
|
||||||
|
|||||||
Reference in New Issue
Block a user