首先上效果图

这个怎么实现的呢,其实就是通过 TouchEvent 事件实现;
ui::Widget::TouchEventType::BEGAN
ui::Widget::TouchEventType::MOVED
ui::Widget::TouchEventType::CANCELED
ui::Widget::TouchEventType::ENDED
协调这4个类型处理,主要逻辑在TouchEventType::MOVED中;通过getTouchBeganPosition获取到起始点,通过getTouchMovePosition获取到当前移动到的位置,统一使用 当前位置的 Y轴,X轴在两点之间每隔10.0f生成一个检测点,检测该点是否存在扑克牌。判断函数代码主要如下:

bool UIHelper::IsSpriteInTouch(cocos2d::Vec2 kWorldPos, cocos2d::Node *pSrite)
{
    kWorldPos = pSrite->convertToNodeSpace(kWorldPos);      //转换成节点坐标
    cocos2d::Size elementSize = pSrite->getContentSize();
    cocos2d::Rect elementRect;
    cocos2d::Vec2 kAnchor = pSrite->getAnchorPoint();
    elementRect = cocos2d::Rect(
            0,0,
            elementSize.width,
            elementSize.height
    );
    return elementRect.containsPoint(kWorldPos);
}

pSrite 为扑克牌的指针,首先将触摸点的坐标,转换成相对于扑克节点的坐标,通过扑克牌的区域构建检测区域,通过containsPoint函数判断检测点是否在扑克牌的区域内。
这里需要注意的是斗地主 除了最后一张扑克以外有很大一部分被遮挡,所有需要根据遮挡部位调整检测的区域。

bool UIHelper::IsSpriteInTouch(cocos2d::Vec2 kWorldPos, cocos2d::Node *pSrite,cocos2d::Size checkSize)
{
    kWorldPos = pSrite->convertToNodeSpace(kWorldPos);      //转换成节点坐标
    cocos2d::Rect elementRect;
    elementRect = cocos2d::Rect(
            0,0,
            checkSize.width,
            checkSize.height
    );
    return elementRect.containsPoint(kWorldPos);
}

checkSize 为指定的检测范围。具体代码是下面这个样子:

case ui::Widget::TouchEventType::MOVED: {
                    Vec2 a = pCard->getTouchBeganPosition();
                    Vec2 b = pCard->getTouchMovePosition();
                    if (abs(b.x - a.x) > 30) {      //出牌判定
                        m_bMove = true;
                    }
                    //取消状态
                    ui::Layout *pHandCardNode = dynamic_cast<ui::Layout *>(UIHelper::seekNodeByName(m_pParseNode, "HandCard_0"));
                    const auto &arrayRootChildren = pHandCardNode->getChildren();
                    for (auto &subWidget : arrayRootChildren) {
                        subWidget->setName("");
                        UIHelper::seekNodeByName(subWidget, "ColorLayout")->setVisible(false);
                    }

                    float lx = a.x >= b.x ? a.x : b.x;
                    float sx = a.x >= b.x ? b.x : a.x;
                    float by = b.y;
                    while (lx - sx > 10.0f) {    //距离10检测一次
                        lx -= 10.0f;
                        ui::Layout *pTempHandCardNode = dynamic_cast<ui::Layout *>(UIHelper::seekNodeByName(m_pParseNode, "HandCard_0"));
                        const auto &arrayTempRootChildren = pTempHandCardNode->getChildren();
                        ssize_t lsize = arrayTempRootChildren.size();
                        for (int i = 0; i < lsize; i++) {
                            ui::Layout *child = dynamic_cast<ui::Layout *>(arrayTempRootChildren.at(i));
                            Size _cardSize = child->getContentSize();
                            if (i == lsize - 1) {     //最后一张
                                if (UIHelper::IsSpriteInTouch(Vec2(lx, by), child)) {
                                    child->setName("_InTouch_Card_");
                                    UIHelper::seekNodeByName(child, "ColorLayout")->setVisible(true);
                                    break; //成功检测后退出
                                }
                            } else {
                                if (UIHelper::IsSpriteInTouch(Vec2(lx, by), child, Size(m_fBigCardW, _cardSize.height))) {
                                    child->setName("_InTouch_Card_");
                                    UIHelper::seekNodeByName(child, "ColorLayout")->setVisible(true);
                                    break;  //成功检测后退出
                                }
                            }
                        }
                    }
                    break;
                }

通过->setName(“_InTouch_Card_”);给扑克打标记,方便触摸结束时候处理;ColorLayout是一层颜色遮罩层,用来给选中的扑克添加底色;
后续的处理代码大致如下:筛选出最终的扑克牌列表,更改Y轴坐标。

case ui::Widget::TouchEventType::CANCELED:
                case ui::Widget::TouchEventType::ENDED: {
                    if (m_bMove) {
                        ui::Layout *pHandCardNode = dynamic_cast<ui::Layout *>(UIHelper::seekNodeByName(m_pParseNode, "HandCard_0"));
                        const auto &arrayRootChildren = pHandCardNode->getChildren();
                        BYTE cbRemoveCard[MAX_COUNT];   //移除列表
                        ZeroMemory(cbRemoveCard, sizeof(cbRemoveCard));
                        BYTE cbRemoveCardCount = 0;     //移除总数
                        BYTE cbAddCard[MAX_COUNT];      //添加列表
                        ZeroMemory(cbAddCard, sizeof(cbAddCard));
                        BYTE cbAddCardCount = 0;        //添加总数
                        for (auto &subWidget : arrayRootChildren) {
                            Node *child = dynamic_cast<Node *>(subWidget);
                            if (child->getName() == "_InTouch_Card_") {   //触摸的牌
                                bool isExist = false;
                                BYTE cbTag = (BYTE) child->getTag();
                                for (int i = 0; i < m_cbOutCardCount; i++) { isExist = (m_cbOutCardData[i] == cbTag); if (isExist) break; //找到了就退出 } if (isExist) { cbRemoveCard[cbRemoveCardCount++] = cbTag; } else { cbAddCard[cbAddCardCount++] = cbTag; } child->setName("");
                            }
                        }
                        if (cbRemoveCardCount > 0) {
                            m_pGameClient->m_pGameLogic->RemoveCardList(cbRemoveCard, cbRemoveCardCount, m_cbOutCardData, m_cbOutCardCount);
                            m_cbOutCardCount -= cbRemoveCardCount;  //减少数量
                        }
                        CopyMemory(m_cbOutCardData + m_cbOutCardCount, cbAddCard, cbAddCardCount);
                        m_cbOutCardCount += cbAddCardCount;
                        //牌处理
                        CCLOG("选中牌的数量:%d,新增牌的数量:%d,移除牌的数量", m_cbOutCardCount, cbAddCardCount, cbRemoveCardCount);
                        ShowSearchCard(m_cbOutCardData, m_cbOutCardCount);
                        return;
                    } 

 

打赏
Cocostudio 斗地主滑动选牌实现
Tagged on:

发表评论