#pragma once #include #include #include #include #include #include #include #include #include "Log.hpp" #include "Asset.hpp" #include "Collider.hpp" #include "Sand.hpp" #include "Spike.hpp" #define CW 20 #define CH 12 using json = nlohmann::json; using Block = std::array; class BlockLayer final: public sf::Drawable { public: BlockLayer() = delete; BlockLayer(const std::string& filename, const std::string& tileset): m_tex(&Asset::texture(tileset)), m_tileSize(32.f) { std::ifstream ifs(filename); json j; ifs >> j; auto layer = j["layers"][2]; m_size.x = layer["width"]; m_size.y = layer["height"]; m_blocks.reserve(m_size.x * m_size.y); for(std::size_t i = 0; i < layer["data"].size(); ++i) { int tile = layer["data"][i]; size_t x = i % m_size.x; size_t y = i / m_size.x; int collide_type = Collider::AIR; switch(tile) { case 1: collide_type = Collider::SOLID; break; case 2: collide_type = Collider::SAND; break; case 3: collide_type = Collider::LEVER; break; case 4: collide_type = Collider::SPIKE; break; default: break; } m_map.push_back(collide_type); if(0 && tile == 2) { sf::Vector2f tileOffset(x * m_tileSize, y * m_tileSize); std::size_t tileIndex = tile - 1; m_blocks.emplace_back( tileOffset, sf::Color::White, sf::Vector2f(tileIndex * m_tileSize, 0.f) ); m_blocks.emplace_back( tileOffset + sf::Vector2f(m_tileSize, 0.f), sf::Color::White, sf::Vector2f((tileIndex + 1) * m_tileSize, 0.f) ); m_blocks.emplace_back( tileOffset + sf::Vector2f(m_tileSize, m_tileSize), sf::Color::White, sf::Vector2f((tileIndex + 1) * m_tileSize, m_tileSize) ); m_blocks.emplace_back( tileOffset + sf::Vector2f(0.f, m_tileSize), sf::Color::White, sf::Vector2f(tileIndex * m_tileSize, m_tileSize) ); } else { for(std::size_t i = 0; i < 4; ++i) { m_blocks.emplace_back(sf::Vector2f(0.f, 0.f), sf::Color::White, sf::Vector2f(0.f, 0.f)); } } } } ~BlockLayer() { /*for(std::size_t i = 0; i < m_blocks.size(); ++i) { if(m_blocks[i]) { delete m_blocks[i]; } }*/ } std::vector rebuildCollider(int focus) { std::vector res; res.reserve(CW * CH); for(int j = 0; j < CH; ++j) { for(int i = focus * CW; i < focus * CW + CW; ++i) { int curr = m_map[i + j * m_size.x]; if(curr != Collider::SPIKE && curr != Collider::SAND) { res.push_back(m_map[i + j * m_size.x]); } else { res.push_back(Collider::AIR); } } } return res; } std::vector reloadSpikes(int focus, Collider* collider) { std::vector res; for(int j = 1; j < CH; ++j) { for(int i = focus * CW; i < focus * CW + CW; ++i) { if(m_map[i + j * m_size.x] == Collider::SPIKE) { res.emplace_back(collider, m_map[i + (j - 1) * m_size.x] == Collider::LEVER); res.back().setPosition(i * 32.f, j * 32.f); res.back().setTexture(Asset::texture("data/tileset.png")); res.back().setTextureRect(sf::IntRect( 96, 0, 32, 32 )); } } } return res; } std::vector reloadSand(int focus, Collider* collider) { std::vector res; for(int j = 0; j < CH; ++j) { for(int i = focus * CW; i < focus * CW + CW; ++i) { if(m_map[i + j * m_size.x] == Collider::SAND) { res.emplace_back(collider); res.back().setPosition(i * 32.f, j * 32.f); res.back().setTexture(Asset::texture("data/tileset.png")); res.back().setTextureRect(sf::IntRect( 32, 0, 32, 32 )); } } } return res; } std::vector m_blocks; std::vector m_map; BlockLayer(const BlockLayer&) = delete; BlockLayer& operator=(const BlockLayer&) = delete; //const sf::FloatRect& getGlobalBounds() const { // return m_globalBounds; //} private: const sf::Texture* m_tex; sf::Vector2u m_size; float m_tileSize; void draw(sf::RenderTarget& rt, sf::RenderStates states) const override { states.texture = m_tex; rt.draw(m_blocks.data(), m_blocks.size(), sf::Quads, states); } };