#include "SpriteManager.h" #include #include namespace NGame { TSpriteManager::TSpriteManager(TFileManager& fileManager, TRenderManager& renderManager, std::size_t cacheSize) : FileManager_(fileManager), RenderManager_(renderManager), Cache_(cacheSize) { } std::shared_ptr TSpriteManager::Get(const std::string& path) { if (Cache_.Contains(path)) { return Cache_.Get(path); } auto result = std::make_shared(ParseInfoFile(path)); Cache_.Set(path, result); return result; } void TSpriteManager::Draw(const std::shared_ptr& 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(flip)); } TSpriteManager::TSprite TSpriteManager::ParseInfoFile(const std::string& path) { std::string data = FileManager_.Get(path); std::istringstream inputStream(data); std::shared_ptr currentTexture; std::vector 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