From 937875c4e1432b418f0f5051759e02c8d4c9ffa4 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Fri, 5 Mar 2021 18:53:06 -0500 Subject: Added the mask sprite layer This layer is below the normal sprite layer. Sprites on it are only rendered within the area of a zone that is defined per-map. --- src/consts.h | 2 -- src/game.cpp | 2 +- src/map.cpp | 10 ++++++++++ src/map.h | 4 ++++ src/renderer.cpp | 30 ++++++++++++++++++++++++++++++ src/sprite.h | 4 +++- src/transform_system.h | 2 +- 7 files changed, 49 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/consts.h b/src/consts.h index e0af6cd..65e4558 100644 --- a/src/consts.h +++ b/src/consts.h @@ -12,6 +12,4 @@ const int PARTY_FRAME_DELAY = 20; // true delay is this divided by movement spee const int MESSAGE_TEXT_WIDTH = 196; -const int NUM_SPRITE_LAYERS = 2; - #endif /* end of include guard: CONSTS_H_9561E49C */ diff --git a/src/game.cpp b/src/game.cpp index 5b5c506..7e3c88f 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -56,7 +56,7 @@ void Game::loadMap(std::string filename) { if (spritesByAlias_.count(p.name)) continue; int spriteId = emplaceSprite(p.name); - getSystem().initSprite(spriteId, p.pos); + getSystem().initSprite(spriteId, p.pos, p.masked ? SpriteLayer::Mask : SpriteLayer::Normal); getSystem().setUpCollision(spriteId, p.collisionOffset, p.collisionSize, true); if (!p.animationFilename.empty()) { getSystem().initSprite(spriteId, p.animationFilename); diff --git a/src/map.cpp b/src/map.cpp index c3ac828..8d0ada6 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -71,12 +71,20 @@ Map::Map(std::string_view name) : name_(name) { } else if (layer->getType() == tmx::Layer::Type::Object) { const auto& objectLayer = layer->getLayerAs(); + bool masked = false; + for (const tmx::Property& property : objectLayer.getProperties()) { + if (property.getName() == "masked" && property.getBoolValue()) { + masked = true; + } + } + for (const tmx::Object& object : objectLayer.getObjects()) { if (object.getType() == "sprite") { Prototype p; p.name = object.getName(); p.pos.x() = object.getPosition().x; p.pos.y() = object.getPosition().y; + p.masked = masked; for (const tmx::Property& property : object.getProperties()) { if (property.getName() == "collisionOffsetX") { @@ -159,6 +167,8 @@ Map::Map(std::string_view name) : name_(name) { for (const tmx::Property& property : mapfile.getProperties()) { if (property.getName() == "music") { music_ = property.getStringValue(); + } else if (property.getName() == "maskZone") { + maskZone_ = property.getStringValue(); } } } diff --git a/src/map.h b/src/map.h index a125082..1167290 100644 --- a/src/map.h +++ b/src/map.h @@ -31,6 +31,7 @@ struct Prototype { bool wander = false; int movementSpeed = -1; std::string enclosureZone; + bool masked = false; }; struct Trigger { @@ -82,6 +83,8 @@ public: const std::string& getMusic() const { return music_; } + const std::string& getMaskZone() const { return maskZone_; } + private: std::string name_; @@ -96,6 +99,7 @@ private: std::vector triggers_; std::map zones_; std::string music_; + std::string maskZone_; }; #endif /* end of include guard: MAP_H_D95D6D47 */ diff --git a/src/renderer.cpp b/src/renderer.cpp index 5ab623a..ea8a2ac 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -178,6 +178,36 @@ void Renderer::render(Game& game) { SDL_RenderCopy(ren_.get(), mapSwapTex_.get(), nullptr, nullptr); } + // Render mask sprite layer + if (!game.getMap().getMaskZone().empty()) { + texture_ptr spritesTex( + SDL_CreateTexture( + ren_.get(), + SDL_PIXELFORMAT_RGBA8888, + SDL_TEXTUREACCESS_TARGET, + mapBounds.w(), + mapBounds.h())); + + if (!spritesTex) { + throw sdl_error(); + } + + SDL_SetRenderTarget(ren_.get(), spritesTex.get()); + SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 0); + SDL_RenderClear(ren_.get()); + + for (const Sprite& sprite : game.getSystem().getSpritesByY(SpriteLayer::Mask) | game.spriteView()) { + renderSprite(sprite); + } + + const Zone& zone = game.getMap().getZone(game.getMap().getMaskZone()); + SDL_Rect zoneArea { zone.ul.x(), zone.ul.y(), zone.dr.x() - zone.ul.x(), zone.dr.y() - zone.ul.y() }; + + SDL_SetRenderTarget(ren_.get(), canvas.get()); + SDL_SetTextureBlendMode(spritesTex.get(), SDL_BLENDMODE_BLEND); + SDL_RenderCopy(ren_.get(), spritesTex.get(), &zoneArea, &zoneArea); + } + // Render normal sprite layer for (const Sprite& sprite : game.getSystem().getSpritesByY(SpriteLayer::Normal) | game.spriteView()) { renderSprite(sprite); diff --git a/src/sprite.h b/src/sprite.h index 13d0383..6538c1d 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -11,8 +11,10 @@ #include "step_type.h" enum class SpriteLayer { + Mask, Normal, - Above + Above, + NUM_SPRITE_LAYERS // do not use }; struct SpriteFrame { diff --git a/src/transform_system.h b/src/transform_system.h index 6707347..7fa3423 100644 --- a/src/transform_system.h +++ b/src/transform_system.h @@ -54,7 +54,7 @@ public: private: Game& game_; - std::set> spritesByY_[NUM_SPRITE_LAYERS]; + std::set> spritesByY_[static_cast(SpriteLayer::NUM_SPRITE_LAYERS)]; struct Collidable { int lower; -- cgit 1.4.1