void FloorMapLayer::confirm_open(OKCancelDialog::RETURN_TYPE type, const npc_t& npc) { if (type == OKCancelDialog::CANCEL) { stop_and_clear(); } else { _warrior->stand_auto(); auto npc_layer = _tiled_map->getLayer("npc"); auto door = npc_layer->getTileAt(Vec2(npc.x, 11 - npc.y)); npc_layer->setupTileSprite(door, Vec2(npc.x, 11 - npc.y), npc.gid); door->runAction(CCSequence::create(FadeOut::create(0.5f), RemoveSelf::create(), CCCallFunc::create(std::bind(&FloorMapLayer::confirm_open_impl, this, npc)), nullptr)); // 如果是竖门需要将其上方的附加节点一并去除 auto uplink = get_tile_prop(npc.gid, "uplink").asInt(); if (1 == uplink) { auto npc_iter = find(_npcs.begin(), _npcs.end(), npc_t(npc.x, npc.y + 1, 0)); if (npc_iter != _npcs.end()) { const auto& npc_up = *npc_iter; auto door_up = npc_layer->getTileAt(Vec2(npc_up.x, 11 - npc_up.y)); npc_layer->setupTileSprite(door_up, Vec2(npc_up.x, 11 - npc_up.y), npc_up.gid); door_up->runAction(CCSequence::create(FadeOut::create(0.5f), RemoveSelf::create(), nullptr)); } } } }
void FloorMapLayer::confirm_open(OKCancelDialog::RETURN_TYPE type, const Floor::npc_t& npc) { if (type == OKCancelDialog::CANCEL) { stop_and_clear(); } else { _warrior->stand_auto(); _warrior->set_lock(true); // 设置等待开门的过程中不可重新寻路,以免出现计算混乱 auto npc_layer = _tiled_map->getLayer("npc"); auto door = npc_layer->getTileAt(Vec2(npc.pos.x, 11 - npc.pos.y)); npc_layer->setupTileSprite(door, Vec2(npc.pos.x, 11 - npc.pos.y), npc.gid); const float OPEN_DURATION = 0.5f; door->runAction(CCSequence::create(FadeOut::create(OPEN_DURATION), RemoveSelf::create(), CCCallFunc::create(std::bind(&FloorMapLayer::confirm_open_impl, this, npc)), nullptr)); // 如果是竖门需要将其上方的附加节点一并去除 auto uplink = get_tile_prop(npc.gid, "uplink").asInt(); if (1 == uplink) { auto npc_up = Floor::GetInstance()->get_floor_info(_floor).find_npc_by_pos(Floor::position_t(npc.pos.x, npc.pos.y + 1)); if (nullptr != npc_up) { auto door_up = npc_layer->getTileAt(Vec2(npc_up->pos.x, 11 - npc_up->pos.y)); npc_layer->setupTileSprite(door_up, Vec2(npc_up->pos.x, 11 - npc_up->pos.y), npc_up->gid); door_up->runAction(CCSequence::create(FadeOut::create(OPEN_DURATION), RemoveSelf::create(), nullptr)); } } } }
// used only when parsing the map. useless after the map was parsed // since lot's of assumptions are no longer true Sprite * TMXLayer::appendTileForGID(int gid, const Point& pos) { if (gid != 0 && (static_cast<int>((gid & kFlippedMask)) - _tileSet->_firstGid) >= 0) { Rect rect = _tileSet->rectForGID(gid); rect = CC_RECT_PIXELS_TO_POINTS(rect); intptr_t z = (intptr_t)(pos.x + pos.y * _layerSize.width); Sprite *tile = reusedTileWithRect(rect); setupTileSprite(tile ,pos ,gid); // optimization: // The difference between appendTileForGID and insertTileforGID is that append is faster, since // it appends the tile at the end of the texture atlas ssize_t indexForZ = _atlasIndexArray->num; // don't add it using the "standard" way. insertQuadFromSprite(tile, indexForZ); // append should be after addQuadFromSprite since it modifies the quantity values ccCArrayInsertValueAtIndex(_atlasIndexArray, (void*)z, indexForZ); return tile; } return nullptr; }
void TMXLayer::setTileGID(int gid, const Vec2& tileCoordinate, TMXTileFlags flags) { CCASSERT(tileCoordinate.x < _layerSize.width && tileCoordinate.y < _layerSize.height && tileCoordinate.x >=0 && tileCoordinate.y >=0, "TMXLayer: invalid position"); CCASSERT(_tiles, "TMXLayer: the tiles map has been released"); CCASSERT(gid == 0 || gid >= _tileSet->_firstGid, "TMXLayer: invalid gid" ); TMXTileFlags currentFlags; int currentGID = getTileGIDAt(tileCoordinate, ¤tFlags); if (currentGID == gid && currentFlags == flags) return; int gidAndFlags = gid | flags; // setting gid=0 is equal to remove the tile if (gid == 0) { removeTileAt(tileCoordinate); } // empty tile. create a new one else if (currentGID == 0) { int z = tileCoordinate.x + tileCoordinate.y * _layerSize.width; setFlaggedTileGIDByIndex(z, gidAndFlags); } // modifying an existing tile with a non-empty tile else { int z = tileCoordinate.x + tileCoordinate.y * _layerSize.width; auto it = _spriteContainer.find(z); if (it != _spriteContainer.end()) { Sprite *sprite = it->second.first; Rect rect = _tileSet->getRectForGID(gid); rect = CC_RECT_PIXELS_TO_POINTS(rect); sprite->setTextureRect(rect, false, rect.size); this->reorderChild(sprite, z); if (flags) { setupTileSprite(sprite, sprite->getPosition(), gidAndFlags); } it->second.second = gidAndFlags; } else { setFlaggedTileGIDByIndex(z, gidAndFlags); } } }
void TMXLayer::setTileGID(int gid, const Point& pos, ccTMXTileFlags flags) { CCASSERT(pos.x < _layerSize.width && pos.y < _layerSize.height && pos.x >=0 && pos.y >=0, "TMXLayer: invalid position"); CCASSERT(_tiles && _atlasIndexArray, "TMXLayer: the tiles map has been released"); CCASSERT(gid == 0 || gid >= _tileSet->_firstGid, "TMXLayer: invalid gid" ); ccTMXTileFlags currentFlags; int currentGID = getTileGIDAt(pos, ¤tFlags); if (currentGID != gid || currentFlags != flags) { int gidAndFlags = gid | flags; // setting gid=0 is equal to remove the tile if (gid == 0) { removeTileAt(pos); } // empty tile. create a new one else if (currentGID == 0) { insertTileForGID(gidAndFlags, pos); } // modifying an existing tile with a non-empty tile else { int z = pos.x + pos.y * _layerSize.width; Sprite *sprite = static_cast<Sprite*>(getChildByTag(z)); if (sprite) { Rect rect = _tileSet->rectForGID(gid); rect = CC_RECT_PIXELS_TO_POINTS(rect); sprite->setTextureRect(rect, false, rect.size); if (flags) { setupTileSprite(sprite, sprite->getPosition(), gidAndFlags); } _tiles[z] = gidAndFlags; } else { updateTileForGID(gidAndFlags, pos); } } } }
Sprite * TMXLayer::updateTileForGID(int gid, const Point& pos) { Rect rect = _tileSet->rectForGID(gid); rect = Rect(rect.origin.x / _contentScaleFactor, rect.origin.y / _contentScaleFactor, rect.size.width/ _contentScaleFactor, rect.size.height/ _contentScaleFactor); int z = (int)(pos.x + pos.y * _layerSize.width); Sprite *tile = reusedTileWithRect(rect); setupTileSprite(tile ,pos ,gid); // get atlas index ssize_t indexForZ = atlasIndexForExistantZ(z); tile->setAtlasIndex(indexForZ); tile->setDirty(true); tile->updateTransform(); _tiles[z] = gid; return tile; }
// CCTMXLayer - adding helper methods CCSprite * CCTMXLayer::insertTileForGID(unsigned int gid, const CCPoint& pos) { CCRect rect = m_pTileSet->rectForGID(gid); rect = CC_RECT_PIXELS_TO_POINTS(rect); intptr_t z = (intptr_t)(pos.x + pos.y * m_tLayerSize.width); // if quad optimization is used CCSprite *tile; if(m_pAtlasIndexArray) { tile = reusedTileWithRect(rect); setupTileSprite(tile, pos, gid); // get atlas index unsigned int indexForZ = atlasIndexForNewZ(z); // Optimization: add the quad without adding a child this->insertQuadFromSprite(tile, indexForZ); // insert it into the local atlasindex array ccCArrayInsertValueAtIndex(m_pAtlasIndexArray, (void*)z, indexForZ); // update possible children if (m_pChildren && m_pChildren->count()>0) { CCObject* pObject = NULL; CCARRAY_FOREACH(m_pChildren, pObject) { CCSprite* pChild = (CCSprite*) pObject; if (pChild) { unsigned int ai = pChild->getAtlasIndex(); if ( ai >= indexForZ ) { pChild->setAtlasIndex(ai+1); } } } }
// TMXLayer - adding helper methods Sprite * TMXLayer::insertTileForGID(int gid, const Point& pos) { if (gid != 0 && (static_cast<int>((gid & kFlippedMask)) - _tileSet->_firstGid) >= 0) { Rect rect = _tileSet->rectForGID(gid); rect = CC_RECT_PIXELS_TO_POINTS(rect); intptr_t z = (intptr_t)(pos.x + pos.y * _layerSize.width); Sprite *tile = reusedTileWithRect(rect); setupTileSprite(tile, pos, gid); // get atlas index ssize_t indexForZ = atlasIndexForNewZ(static_cast<int>(z)); // Optimization: add the quad without adding a child this->insertQuadFromSprite(tile, indexForZ); // insert it into the local atlasindex array ccCArrayInsertValueAtIndex(_atlasIndexArray, (void*)z, indexForZ); // update possible children for(const auto &child : _children) { Sprite* sp = static_cast<Sprite*>(child); ssize_t ai = sp->getAtlasIndex(); if ( ai >= indexForZ ) { sp->setAtlasIndex(ai+1); } } _tiles[z] = gid; return tile; } return nullptr; }
// used only when parsing the map. useless after the map was parsed // since lot's of assumptions are no longer true Sprite * TMXLayer::appendTileForGID(uint32_t gid, const Vec2& pos) { if (gid != 0 && (static_cast<int>((gid & kTMXFlippedMask)) - _tileSet->_firstGid) >= 0) { Rect rect = _tileSet->getRectForGID(gid); rect = CC_RECT_PIXELS_TO_POINTS(rect); // Z could be just an integer that gets incremented each time it is called. // but that wouldn't work on layers with empty tiles. // and it is IMPORTANT that Z returns an unique and bigger number than the previous one. // since _atlasIndexArray must be ordered because `bsearch` is used to find the GID for // a given Z. (github issue #16512) intptr_t z = getZForPos(pos); Sprite *tile = reusedTileWithRect(rect); setupTileSprite(tile ,pos ,gid); // optimization: // The difference between appendTileForGID and insertTileforGID is that append is faster, since // it appends the tile at the end of the texture atlas ssize_t indexForZ = _atlasIndexArray->num; // don't add it using the "standard" way. insertQuadFromSprite(tile, indexForZ); // append should be after addQuadFromSprite since it modifies the quantity values ccCArrayInsertValueAtIndex(_atlasIndexArray, (void*)z, indexForZ); // Validation for issue #16512 CCASSERT(_atlasIndexArray->num == 1 || _atlasIndexArray->arr[_atlasIndexArray->num-1] > _atlasIndexArray->arr[_atlasIndexArray->num-2], "Invalid z for _atlasIndexArray"); return tile; } return nullptr; }
void FloorMapLayer::pick_up_item_impl(const npc_t& npc, const cocos2d::Vec2& target_pos, const std::function<void()>& callback) { auto npc_layer = _tiled_map->getLayer("npc"); auto item = npc_layer->getTileAt(Vec2(npc.x, 11 - npc.y)); npc_layer->setupTileSprite(item, Vec2(npc.x, 11 - npc.y), npc.gid); auto start_pos = this->convertToNodeSpace(item->getParent()->convertToWorldSpace(item->getPosition())); item->retain(); item->removeFromParentAndCleanup(false); item->setPosition(start_pos); this->addChild(item); item->release(); // TODO.. cocos2d-x tiled bug. 如果一个Layer只剩下一个tile,getTileAt内部设置gid为0不起作用,目前找不到解决办法 npc_layer->setTileGID(999, Vec2(npc.x, 11 - npc.y)); auto duration = item->getPosition().distance(target_pos) / 1000.0f; item->runAction(Sequence::create( Spawn::createWithTwoActions(MoveTo::create(duration, target_pos), ScaleTo::create(duration, 0.6f)), CallFunc::create([item, callback]() { item->removeFromParentAndCleanup(true); callback(); }), nullptr)); }
// TMXLayer - adding helper methods Sprite * TMXLayer::insertTileForGID(unsigned int gid, const Point& pos) { Rect rect = m_pTileSet->rectForGID(gid); rect = CC_RECT_PIXELS_TO_POINTS(rect); KDintptr z = (KDintptr)(pos.x + pos.y * m_tLayerSize.width); Sprite *tile = reusedTileWithRect(rect); setupTileSprite(tile, pos, gid); // get atlas index unsigned int indexForZ = atlasIndexForNewZ(z); // Optimization: add the quad without adding a child this->insertQuadFromSprite(tile, indexForZ); // insert it into the local atlasindex array ccCArrayInsertValueAtIndex(m_pAtlasIndexArray, (void*)z, indexForZ); // update possible children if (m_pChildren && m_pChildren->count()>0) { Object* pObject = nullptr; CCARRAY_FOREACH(m_pChildren, pObject) { Sprite* child = static_cast<Sprite*>(pObject); if (child) { unsigned int ai = child->getAtlasIndex(); if ( ai >= indexForZ ) { child->setAtlasIndex(ai+1); } } }