#include "renderer.h" #include "consts.h" #include "game.h" Renderer::Renderer() { win_ = window_ptr( SDL_CreateWindow( "Tanetane", 100, 100, GAME_WIDTH, GAME_HEIGHT, SDL_WINDOW_SHOWN)); if (!win_) { throw sdl_error(); } ren_ = renderer_ptr( SDL_CreateRenderer( win_.get(), -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC)); if (!ren_) { throw sdl_error(); } } texture_ptr Renderer::renderMapLayer(const tson::Layer& layer) { texture_ptr canvas( SDL_CreateTexture( ren_.get(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, layer.getMap()->getSize().x * layer.getMap()->getTileSize().x, layer.getMap()->getSize().y * layer.getMap()->getTileSize().y)); SDL_SetTextureBlendMode(canvas.get(), SDL_BLENDMODE_BLEND); SDL_SetRenderTarget(ren_.get(), canvas.get()); SDL_SetRenderDrawBlendMode(ren_.get(), SDL_BLENDMODE_BLEND); SDL_SetRenderDrawColor(ren_.get(), 255, 255, 255, 0); SDL_RenderClear(ren_.get()); for (auto& [pos, tileObject] : layer.getTileObjects()) { int x = tileObject.getPosition().x; int y = tileObject.getPosition().y; tson::Rect tileDestRect = tileObject.getDrawingRect(); SDL_Rect srcRect { tileDestRect.x, tileDestRect.y, tileDestRect.width, tileDestRect.height }; SDL_Rect destRect { x, y, tileObject.getTile()->getTileSize().x, tileObject.getTile()->getTileSize().y }; SDL_RendererFlip flip = SDL_FLIP_NONE; if (tileObject.getTile()->hasFlipFlags(tson::TileFlipFlags::Horizontally | tson::TileFlipFlags::Vertically)) { flip = static_cast(SDL_FLIP_HORIZONTAL | SDL_FLIP_VERTICAL); } else if (tileObject.getTile()->hasFlipFlags(tson::TileFlipFlags::Horizontally)) { flip = SDL_FLIP_HORIZONTAL; } else if (tileObject.getTile()->hasFlipFlags(tson::TileFlipFlags::Vertically)) { flip = SDL_FLIP_VERTICAL; } SDL_RenderCopyEx(ren_.get(), textures_[tilesetTexId_].get(), &srcRect, &destRect, 0, nullptr, flip); } return canvas; } void Renderer::render(Game& game) { if (tilesetTexId_ == -1) { tilesetTexId_ = loadImageFromFile(game.getMap()->getTileset("fromRom")->getImage().c_str()); } if (!renLay1_) { renLay1_ = renderMapLayer(*game.getMap()->getLayer("Layer 1")); } if (!renLay0_) { renLay0_ = renderMapLayer(*game.getMap()->getLayer("Layer 0")); } texture_ptr canvas( SDL_CreateTexture( ren_.get(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, CANVAS_WIDTH, CANVAS_HEIGHT)); if (!canvas) { throw sdl_error(); } SDL_SetRenderTarget(ren_.get(), canvas.get()); SDL_SetRenderDrawBlendMode(ren_.get(), SDL_BLENDMODE_NONE); SDL_SetRenderDrawColor(ren_.get(), 255, 255, 255, 255); SDL_RenderClear(ren_.get()); { SDL_Rect dest { -80, -80, game.getMap()->getSize().x * game.getMap()->getTileSize().x, game.getMap()->getSize().y * game.getMap()->getTileSize().y }; SDL_RenderCopy(ren_.get(), renLay1_.get(), nullptr, &dest); } for (const Sprite& sprite : game.getSpritesByY() | game.spriteView()) { const SpriteFrame& frame = sprite.getFrame(); const SDL_Rect& src = frame.srcRect; SDL_Rect dest { sprite.loc().x() - frame.center.x(), sprite.loc().y() - frame.center.y(), frame.size.w(), frame.size.h() }; SDL_RenderCopy(ren_.get(), textures_.at(sprite.getTextureId()).get(), &src, &dest); } { SDL_Rect dest { -80, -80, game.getMap()->getSize().x * game.getMap()->getTileSize().x, game.getMap()->getSize().y * game.getMap()->getTileSize().y }; SDL_RenderCopy(ren_.get(), renLay0_.get(), nullptr, &dest); } SDL_SetRenderTarget(ren_.get(), nullptr); SDL_RenderCopy(ren_.get(), canvas.get(), nullptr, nullptr); SDL_RenderPresent(ren_.get()); } int Renderer::loadImageFromFile(std::string_view filename) { surface_ptr pfs(IMG_Load(filename.data())); if (!pfs) { throw img_error(); } texture_ptr tex = texture_ptr(SDL_CreateTextureFromSurface(ren_.get(), pfs.get())); //SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND); int texId = textures_.size(); textures_.push_back(std::move(tex)); return texId; }