Files
jam-game/src/SpriteManager.cpp
T

120 lines
3.9 KiB
C++
Raw Normal View History

2025-07-17 21:52:37 +03:00
#include "SpriteManager.h"
#include <SDL2/SDL_render.h>
#include <sstream>
namespace NGame {
TSpriteManager::TSpriteManager(TFileManager& fileManager, TRenderManager& renderManager, std::size_t cacheSize)
: FileManager_(fileManager), RenderManager_(renderManager), Cache_(cacheSize) {
}
std::shared_ptr<TSpriteManager::TSprite> TSpriteManager::Get(const std::string& path) {
if (Cache_.Contains(path)) {
return Cache_.Get(path);
}
auto result = std::make_shared<TSprite>(ParseInfoFile(path));
Cache_.Set(path, result);
return result;
}
void TSpriteManager::Draw(const std::shared_ptr<TSprite>& sprite, size_t frame, const Vec2i& position, const Vec2f& scale) {
const auto& frameData = sprite->Frames[frame];
int flip = 0;
Vec2i size = frameData.Size * scale;
if (size.X < 0) {
size.X = -size.X;
flip |= SDL_FLIP_HORIZONTAL;
}
if (size.Y < 0) {
size.Y = -size.Y;
flip |= SDL_FLIP_VERTICAL;
}
RenderManager_.SetTexture(sprite->Texture);
RenderManager_.DrawSprite(frameData.Position, frameData.Size, position, size, static_cast<SDL_RendererFlip>(flip));
}
TSpriteManager::TSprite TSpriteManager::ParseInfoFile(const std::string& path) {
std::string data = FileManager_.Get(path);
std::istringstream inputStream(data);
std::shared_ptr<SDL_Texture> currentTexture;
std::vector<TFrame> currentFrames;
for (std::string line; std::getline(inputStream, line); ) {
auto remainder = Trim(std::string_view(line));
auto action = RightTrim(NextToken(remainder, " "));
if (action == "Texture") {
auto textureString = Trim(NextToken(remainder, " "));
if (textureString.empty()) {
throw std::runtime_error("texture name should not be empty for " + path);
}
currentTexture = RenderManager_.Get(std::string(textureString));
} else if (action == "Frame") {
auto xString = Trim(NextToken(remainder, " "));
auto yString = Trim(NextToken(remainder, " "));
auto widthString = Trim(NextToken(remainder, " "));
auto heightString = Trim(NextToken(remainder, " "));
TFrame frame;
if (xString.empty() && yString.empty()) {
frame.Position.X = 0;
frame.Position.Y = 0;
} else {
frame.Position.X = std::stoi(std::string(xString));
frame.Position.Y = std::stoi(std::string(yString));
}
if (widthString.empty() && heightString.empty()) {
int width, height;
if (SDL_QueryTexture(currentTexture.get(), NULL, NULL, &width, &height)) {
throw std::runtime_error("can't query texture information for " + path);
}
frame.Size.X = width;
frame.Size.Y = height;
} else {
frame.Size.X = std::stoi(std::string(widthString));
frame.Size.Y = std::stoi(std::string(heightString));
}
if (xString.empty() || yString.empty() || widthString.empty() || heightString.empty()) {
throw std::runtime_error("frame should have x, y, width, height parameters for " + path);
}
currentFrames.push_back(frame);
}
}
if (!currentTexture) {
std::runtime_error("no texture for " + path);
}
if (currentFrames.empty()) {
TFrame frame;
int width, height;
if (SDL_QueryTexture(currentTexture.get(), NULL, NULL, &width, &height)) {
throw std::runtime_error("can't query texture information for " + path);
}
frame.Position.X = 0;
frame.Position.Y = 0;
frame.Size.X = width;
frame.Size.Y = height;
currentFrames.push_back(frame);
}
return {currentTexture, currentFrames};
}
} // namespace NGame