diff --git a/src/engine/GameObjects/MapNode.cxx b/src/engine/GameObjects/MapNode.cxx index 71a3ad5564..b93b0b2f16 100644 --- a/src/engine/GameObjects/MapNode.cxx +++ b/src/engine/GameObjects/MapNode.cxx @@ -5,9 +5,11 @@ #include "../map/MapLayers.hxx" #include "GameStates.hxx" #include "Settings.hxx" +#include "Engine.hxx" MapNode::MapNode(Point isoCoordinates, const std::string &terrainID, const std::string &tileID) - : m_isoCoordinates(std::move(isoCoordinates)), m_sprite{std::make_unique(m_isoCoordinates)}, + : m_originalZ(isoCoordinates.z), + m_isoCoordinates(std::move(isoCoordinates)), m_sprite{std::make_unique(m_isoCoordinates)}, m_autotileOrientation(LAYERS_COUNT, TileOrientation::TILE_DEFAULT_ORIENTATION), m_mapNodeData{std::vector(LAYERS_COUNT, MapNodeData{"", nullptr, 0, m_isoCoordinates, true, TileMap::DEFAULT})}, m_autotileBitmask(LAYERS_COUNT) @@ -38,7 +40,7 @@ bool MapNode::changeHeight(const bool higher) return false; } -void MapNode::render() const { m_sprite->render(); } +void MapNode::render(Layer layer) const { m_sprite->render(layer); } void MapNode::setBitmask(unsigned char elevationBitmask, std::vector autotileBitmask) { @@ -52,6 +54,46 @@ void MapNode::setTileID(const std::string &tileID, const Point &origCornerPoint) TileData *tileData = TileManager::instance().getTileData(tileID); if (tileData && !tileID.empty()) { + std::vector targetCoordinates = TileManager::instance().getTargetCoordsOfTileID(origCornerPoint, tileID); + if (targetCoordinates.size() > 1 && m_isoCoordinates == origCornerPoint) + { // multibuilding placed on this node + int minZ = m_isoCoordinates.z; + LOG(LOG_INFO) << "old z " << minZ; + int minY=0; + for (auto coord : targetCoordinates) + { + if(coord.x == origCornerPoint.x) + { + minZ = std::min(minZ, Engine::instance().map->getMapNode(coord).getCoordinates().z); + LOG(LOG_INFO) << "Setting new z " << minZ; + } + } + for (auto coord : targetCoordinates) + { + + if (coord == origCornerPoint) + { + // LOG(LOG_INFO) << "i'm the origin coordinate"; + } + else + { + m_multiTileNodes.push_back(&Engine::instance().map->getMapNode(coord)); + Engine::instance().map->getMapNode(coord).setRenderFlag(Layer::BUILDINGS, false); + // Engine::instance().map->getMapNode(coord).setRenderFlag(Layer::TERRAIN, false); + Engine::instance().map->getMapNode(coord).updateTexture(Layer::BUILDINGS); + // Engine::instance().map->getMapNode(coord).updateTexture(Layer::TERRAIN); + Engine::instance().map->getMapNode(coord).setTileID(tileID, origCornerPoint); + Engine::instance().map->getMapNode(coord).setTileID("terrain_basalt", origCornerPoint); + Engine::instance().map->getMapNode(coord).setZIndex(minZ); + + // LOG(LOG_INFO) << "i'm a multinode"; + } + } + m_isoCoordinates.z = minZ; + LOG(LOG_INFO) << "new z " << minZ; + + // m_isoCoordinates.z = m_isoCoordinates.z - Settings::instance().mapSize; + } const Layer layer = TileManager::instance().getTileLayer(tileID); switch (layer) { @@ -442,6 +484,7 @@ void MapNode::demolishLayer(const Layer &layer) TileOrientation::TILE_DEFAULT_ORIENTATION; // We need to reset TileOrientation, in case it's set (demolishing autotiles) m_mapNodeData[layer].origCornerPoint = this->getCoordinates(); m_mapNodeData[Layer::ZONE].shouldRender = true; + //LOG(LOG_INFO) << "reset render to true"; m_sprite->clearSprite(layer); } @@ -474,6 +517,11 @@ void MapNode::demolishNode(const Layer &demolishLayer) this->demolishLayer(layer); if (layer == Layer::BUILDINGS) { + for (auto *node : m_multiTileNodes) + { + node->demolishNode(layer); + node->setRenderFlag(layer, true); + } this->setNodeTransparency(0, Layer::BLUEPRINT); } updateTexture(demolishLayer); diff --git a/src/engine/GameObjects/MapNode.hxx b/src/engine/GameObjects/MapNode.hxx index faff748364..544278b3f5 100644 --- a/src/engine/GameObjects/MapNode.hxx +++ b/src/engine/GameObjects/MapNode.hxx @@ -75,10 +75,12 @@ public: */ bool changeHeight(const bool higher); - /** @brief Render MapNode + /** @brief Render the sprite object of a layer of MapNode * Renders the sprite object(s) of the node + * @param layer the layer that should be rendered + * @see Sprite#render */ - void render() const; + void render(Layer layer) const; void setBitmask(unsigned char elevationBitmask, std::vector tileTypeBitmask); @@ -165,7 +167,11 @@ public: * Update the Z-Index of this mapNode * @param the new Z-Index */ - void setZIndex(int zIndex) { m_isoCoordinates.z = zIndex; }; + void setZIndex(int zIndex) + { + m_isoCoordinates.z = zIndex; + m_originalZ = zIndex; + }; /** * @brief Maximum height of the node. @@ -174,12 +180,14 @@ public: private: Point m_isoCoordinates; + int m_originalZ = -1; std::unique_ptr m_sprite; std::string m_previousTileID = "terrain"; std::vector m_autotileOrientation; size_t m_elevationOrientation = TileSlopes::DEFAULT_ORIENTATION; int m_clippingWidth = 0; std::vector m_mapNodeData; + std::vector m_multiTileNodes; // keep pointers to other nodes if this is a multile building std::vector m_autotileBitmask; unsigned char m_elevationBitmask = 0; }; diff --git a/src/engine/Map.cxx b/src/engine/Map.cxx index 9a83e0da6d..295c8efc77 100644 --- a/src/engine/Map.cxx +++ b/src/engine/Map.cxx @@ -77,6 +77,7 @@ void Map::getNodeInformation(const Point &isoCoordinates) const LOG(LOG_INFO) << "[Layer: TERRAIN] ID: " << mapNode.getMapNodeDataForLayer(Layer::TERRAIN).tileID; LOG(LOG_INFO) << "[Layer: WATER] ID: " << mapNode.getMapNodeDataForLayer(Layer::WATER).tileID; LOG(LOG_INFO) << "[Layer: BUILDINGS] ID: " << mapNode.getMapNodeDataForLayer(Layer::BUILDINGS).tileID; + LOG(LOG_INFO) << "Z-Index: " << mapNode.getCoordinates().z; LOG(LOG_INFO) << "Category: " << tileData->category; LOG(LOG_INFO) << "FileName: " << tileData->tiles.fileName; LOG(LOG_INFO) << "PickRandomTile: " << tileData->tiles.pickRandomTile; @@ -335,7 +336,7 @@ std::vector Map::calculateAutotileBitmask(const MapNode *const pMapNode } // only auto-tile categories that can be tiled. - const std::string& nodeTileId = pMapNode->getMapNodeDataForLayer(currentLayer).tileID; + const std::string &nodeTileId = pMapNode->getMapNodeDataForLayer(currentLayer).tileID; if (TileManager::instance().isTileIDAutoTile(nodeTileId)) { for (const auto &neighbour : neighborNodes) @@ -356,16 +357,32 @@ std::vector Map::calculateAutotileBitmask(const MapNode *const pMapNode void Map::renderMap() const { + #ifdef MICROPROFILE_ENABLED MICROPROFILE_SCOPEI("Map", "Render Map", MP_YELLOW); #endif - for (int i = 0; i < m_visibleNodesCount; ++i) + //for (int i = m_visibleNodesCount-1; i > 0; --i) + // //for (int i = 0; i < m_visibleNodesCount; ++i) + //{ + // //LOG(LOG_INFO) << "Rendering " << pMapNodesVisible[i].get << "," << y; + // pMapNodesVisible[i]->render(); + //} + + // for (auto node : mapNodesInDrawingOrder) + // { + // node->render(); + // } + for (auto currentLayer : allLayersOrdered) { - pMapNodesVisible[i]->render(); + for (auto node : mapNodesInDrawingOrder) + { + node->render(currentLayer); + } } } + void Map::refresh() { #ifdef MICROPROFILE_ENABLED @@ -373,13 +390,21 @@ void Map::refresh() #endif calculateVisibleMap(); + sortMapByZIndex(); - for (int i = 0; i < m_visibleNodesCount; ++i) + for (auto node : mapNodesInDrawingOrder) { - pMapNodesVisible[i]->refresh(); + node->getSprite()->refresh(); } } +void Map::sortMapByZIndex() +{ + LOG(LOG_INFO) << "sorting " << mapNodesInDrawingOrder.size() << " nodes"; + std::sort(mapNodesInDrawingOrder.begin(), mapNodesInDrawingOrder.end(), + [](MapNode *lhs, MapNode *rhs) { return lhs->getCoordinates().z < rhs->getCoordinates().z; }); +} + //TODO: move it out from the map SDL_Color Map::getColorOfPixelInSurface(SDL_Surface *surface, int x, int y) const { @@ -432,7 +457,8 @@ Point Map::findNodeInMap(const SDL_Point &screenCoordinates, const Layer &layer) const int yMiddlePoint = isoY - diff; // Move y up and down 2 neighbors. - for (int y = std::max(yMiddlePoint - neighborReach, 0); (y <= yMiddlePoint + neighborReach) && (y < mapSize); ++y) + for (int y = std::max(yMiddlePoint + neighborReach, 0); (y >= yMiddlePoint - neighborReach) && (y < mapSize); --y) + //for (int y = std::max(yMiddlePoint - neighborReach, 0); (y <= yMiddlePoint + neighborReach) && (y < mapSize); ++y) { //get all coordinates for node at x,y Point coordinate = getMapNode(Point(x, y)).getCoordinates(); @@ -706,18 +732,19 @@ void Map::calculateVisibleMap(void) const int bottom = bottomRight.y - bottomRight.x - 1 - MapNode::maxHeight; m_visibleNodesCount = 0; - +mapNodesInDrawingOrder.clear(); // ZOrder starts from topmost node to the right. (0,127) =1,(1,127) =2, ... for (int y = m_columns - 1; y >= 0; y--) { - for (int x = 0; x < m_rows; x++) + //for (int y = 0; y <= m_columns - 1; y++) + //for (int x = 0; x < m_rows; x++) + for (int x = m_rows - 1; x > 0; x--) { const int xVal = x + y; const int yVal = y - x; - if ((xVal >= left) && (xVal <= right) && (yVal <= top) && (yVal >= bottom)) { - pMapNodesVisible[m_visibleNodesCount++] = mapNodes[nodeIdx(x, y)].getSprite(); + mapNodesInDrawingOrder.push_back(&mapNodes[nodeIdx(x, y)]); } } } @@ -758,9 +785,18 @@ void Map::setTileID(const std::string &tileID, Point coordinate) demolishNode(targetCoordinates, 0, Layer::BUILDINGS); } - for (auto coord : targetCoordinates) - { // now we can place our building + MapNode ¤tNode = getMapNode(coordinate); + currentNode.setTileID(tileID, coordinate); + + // for (auto coord : targetCoordinates) + // { + // MapNode ¤tMapNode = mapNodes[nodeIdx(coord.x, coord.y)]; + // nodesToBeUpdated.push_back(¤tMapNode); + // } + for (auto coord : targetCoordinates) + { // now we can place our building + break; // don't doanything MapNode ¤tMapNode = mapNodes[nodeIdx(coord.x, coord.y)]; if (coord != coordinate && targetCoordinates.size() > 1) @@ -774,6 +810,7 @@ void Map::setTileID(const std::string &tileID, Point coordinate) if (!targetCoordinates.size() == 1) { // if it's not a >1x1 building, place tileID on the current coordinate (e.g. ground decoration beneath a > 1x1 building) + LOG(LOG_INFO) << "yes"; currentMapNode.setTileID(tileID, coord); } else @@ -782,6 +819,7 @@ void Map::setTileID(const std::string &tileID, Point coordinate) currentMapNode.setTileID(tileID, coordinate); } } + // currentMapNode.setZIndex( currentMapNode.getCoordinates().z - Settings::instance().mapSize*3 - 3); // place ground deco if we have one if (!randomGroundDecorationTileID.empty()) diff --git a/src/engine/Map.hxx b/src/engine/Map.hxx index 05188518f8..18fea6f555 100644 --- a/src/engine/Map.hxx +++ b/src/engine/Map.hxx @@ -227,7 +227,7 @@ private: int m_rows; std::default_random_engine randomEngine; TerrainGenerator m_terrainGen; - + void sortMapByZIndex(); static const size_t m_saveGameVersion; // Signals diff --git a/src/engine/Sprite.cxx b/src/engine/Sprite.cxx index c759f575af..a397e90016 100644 --- a/src/engine/Sprite.cxx +++ b/src/engine/Sprite.cxx @@ -20,47 +20,46 @@ Sprite::Sprite(Point _isoCoordinates) : isoCoordinates(_isoCoordinates) m_SpriteData.resize(LAYERS_COUNT); // resize the spritedata vector to the amount of layers we have. } -void Sprite::render() const +void Sprite::render(Layer layer) const { #ifdef MICROPROFILE_ENABLED MICROPROFILE_SCOPEI("Map", "Sprite render", MP_RED); #endif - for (auto currentLayer : allLayersOrdered) + + if (MapLayers::isLayerActive(layer) && m_SpriteData[layer].texture) { - if (MapLayers::isLayerActive(currentLayer) && m_SpriteData[currentLayer].texture) + if (highlightSprite) { - if (highlightSprite) - { - SDL_SetTextureColorMod(m_SpriteData[currentLayer].texture, highlightColor.r, highlightColor.g, highlightColor.b); - } - - if (GameStates::instance().layerEditMode == LayerEditMode::BLUEPRINT && currentLayer != Layer::BLUEPRINT && currentLayer != Layer::UNDERGROUND) - { - SDL_SetTextureAlphaMod(m_SpriteData[currentLayer].texture, 80); - } - else - { - SDL_SetTextureAlphaMod(m_SpriteData[currentLayer].texture, m_SpriteData[currentLayer].alpha); - } + SDL_SetTextureColorMod(m_SpriteData[layer].texture, highlightColor.r, highlightColor.g, highlightColor.b); + } - if (m_SpriteData[currentLayer].clipRect.w != 0) - { - SDL_RenderCopy(WindowManager::instance().getRenderer(), m_SpriteData[currentLayer].texture, - &m_SpriteData[currentLayer].clipRect, &m_SpriteData[currentLayer].destRect); - } - else - { - SDL_RenderCopy(WindowManager::instance().getRenderer(), m_SpriteData[currentLayer].texture, nullptr, - &m_SpriteData[currentLayer].destRect); - } + if (GameStates::instance().layerEditMode == LayerEditMode::BLUEPRINT && layer != Layer::BLUEPRINT && + layer != Layer::UNDERGROUND) + { + SDL_SetTextureAlphaMod(m_SpriteData[layer].texture, 80); + } + else + { + SDL_SetTextureAlphaMod(m_SpriteData[layer].texture, m_SpriteData[layer].alpha); + } - if (highlightSprite) - { - SDL_SetTextureColorMod(m_SpriteData[currentLayer].texture, 255, 255, 255); - } + if (m_SpriteData[layer].clipRect.w != 0) + { + SDL_RenderCopy(WindowManager::instance().getRenderer(), m_SpriteData[layer].texture, &m_SpriteData[layer].clipRect, + &m_SpriteData[layer].destRect); + } + else + { + SDL_RenderCopy(WindowManager::instance().getRenderer(), m_SpriteData[layer].texture, nullptr, + &m_SpriteData[layer].destRect); + } - SDL_SetTextureAlphaMod(m_SpriteData[currentLayer].texture, 255); + if (highlightSprite) + { + SDL_SetTextureColorMod(m_SpriteData[layer].texture, 255, 255, 255); } + + SDL_SetTextureAlphaMod(m_SpriteData[layer].texture, 255); } } diff --git a/src/engine/Sprite.hxx b/src/engine/Sprite.hxx index db21463198..7af106f6bb 100644 --- a/src/engine/Sprite.hxx +++ b/src/engine/Sprite.hxx @@ -35,7 +35,7 @@ public: explicit Sprite(Point isoCoordinates); virtual ~Sprite() = default; - void render() const; + void render(Layer layer) const; void refresh(const Layer &layer = Layer::NONE); void setTexture(SDL_Texture *m_texture, Layer layer = Layer::TERRAIN); diff --git a/src/engine/map/TerrainGenerator.cxx b/src/engine/map/TerrainGenerator.cxx index 65c838eef2..652837bb56 100644 --- a/src/engine/map/TerrainGenerator.cxx +++ b/src/engine/map/TerrainGenerator.cxx @@ -11,7 +11,7 @@ #ifdef NOISE_IN_SUBDIR #include #else -#include +#include #endif using json = nlohmann::json; @@ -150,15 +150,22 @@ void TerrainGenerator::generateTerrain(std::vector &mapNodes, std::vect int z = 0; // set the z-Index for the mapNodes. It is not used, but it's better to have the correct z-index set - for (int y = mapSize - 1; y >= 0; y--) - { + //for (int y = mapSize - 1; y >= 0; y--) + //for (int y = mapSize - 1; y >= 0; y--) + // for (int x = mapSize - 1; x >= 0; x--) + // for (int y = 0; y < mapSize; y++) + // for (int x = mapSize - 1; x >= 0; x--) + // for (int y = mapSize - 1; y >= 0; y--) + + for (int x = 0; x < mapSize; x++) + for (int y = mapSize - 1; y >= 0; y--) + //for (i for (int x = 0; x < mapSize; x++)nt x = 0; x < mapSize; x++) { z++; mapNodes[x * mapSize + y].setZIndex(z); mapNodesInDrawingOrder.push_back(&mapNodes[x * mapSize + y]); } - } } void TerrainGenerator::loadTerrainDataFromJSON()