《ImCat》切小鸟碰撞检测实现

首先恭喜一下自己如期地完成了课题并且顺利地毕业了(此处应有弹幕)( ̄▽ ̄)~■干杯□~( ̄▽ ̄)。
游戏设计中有主角持剑切击小鸟的功能,参考网上切水果的实现。主要思路如下:

  • 记录手指滑动的点位置,把点组成的一个有生命周期的线段并存储
  • 把切击的小鸟对象(圆形)放入飞行池中
  • 对飞行池中的小鸟和存储的线段进行圆和线段的相交判断

主要实现:

void HandleLayer::update(float dt)
{
    vector<SLine>::iterator it = m_lines.begin();
    while (it != m_lines.end()){
        if ((*it).life >= 0){
            (*it).life--;
            it++;
        }
        else{
            it = m_lines.erase(it);
        }
    }
}
bool HandleLayer::onTouchBegan(Touch* tTouch, Event* eEvent)
{
    auto touchPos = tTouch->getLocation();
    touchPos = convertToWorldSpace(touchPos);
    if (canCut){
        m_down = true;
        m_startPoint = touchPos;
    }
    return true;
}
void HandleLayer::onTouchMoved (Touch* tTouch, Event* eEvent)
{
    if (m_down){
        auto touchPos = tTouch->getLocation();
        touchPos = convertToWorldSpace(touchPos);
        m_endPoint = touchPos;
        //刀光效果用MotionStreak实现
        m_motionStreak->setPosition(touchPos);

        SLine line;
        line.startPos = m_startPoint;
        line.endPos = m_endPoint;
        line.life = 10;
        m_lines.push_back(line);
    }
}
void HandleLayer::onTouchEnded(Touch* tTouch, Event* eEvent)
{
    m_down = false;
}
// 碰撞检测
void ScenePlay::checkCollide(){
    for (auto line : m_handleLayer->m_lines){
        auto tmpList = birdLayer->_birdList;
        for (auto bird : tmpList){
            auto xy = bird->getBirdPosition();
            auto xx = xy.x;
            auto yy = xy.y;
            bool isHit = lineHitCircle(line.startPos.x, line.startPos.y, line.endPos.x, line.endPos.y, bird->getBirdRadius(), xx, yy);
            if (!bird->isDie()&&isHit){
                birdLayer->blowUpBird(bird);
            }
        }
    }
}
// 线段和圆相交判断(无颜面对当年的数学老师o(TヘTo))
bool ScenePlay::lineHitCircle(float x0, float y0, float x1, float y1, float r, float x2, float y2)
{
    bool  isHit = false;
    float a = x1 - x0; // Line segment end point horizontal coordinate
    float b = y1 - y0; // Line segment end point vertical coordinate
    float c = x2 - x0; // Circle center horizontal coordinate
    float d = y2 - y0; // Circle center vertical coordinate
    bool circleSideIsRight = false;
    if (d*a - c*b < 0) {
        circleSideIsRight = true;
    }
    bool startInside = false;
    bool endInside = false;
    bool middleInside = false;
    if ((d*a - c*b)*(d*a - c*b) <= r*r*(a*a + b*b)) {
        if (c*c + d*d <= r*r) {
            startInside = true;
        }
        if ((a - c)*(a - c) + (b - d)*(b - d) <= r*r) {
            endInside = true;
        }
        if (!startInside && !endInside && c*a + d*b >= 0 && c*a + d*b <= a*a + b*b) {
            middleInside = true;
        }
    }

    isHit = (startInside || endInside || middleInside);
    return isHit;
}

附一张游戏场景图
Play_Sword