Cocos2dx 多边形碰撞检测

时间:2023-02-08 16:23:42

ContactListen = ObjClass("ContactListen")


-- 创建layer

function ContactListen:createLayer(layer)

    local contactListen = self:new();

    contactListen.maxnum = 0

    return contactListen;

end



-- 创建时候调用的方法 相当于init

function ContactListen:ctor()


   

end


-- 初始化

function ContactListen:init(birdlayer,rankLayer,gameScene)

    self.gameScene = gameScene;

    self.birdlayer = birdlayer;

    self.rankLayer = rankLayer;


end


-- 监听

function ContactListen:listenContact()

    -- 开始监听

    local function contactSp()

        -- 判断碰撞

        table.foreach(self.rankLayer.spriteArray, function(i, v) 

             v = tolua.cast(v,"CCSprite")

             local barBoundingbox = CCRectMake(0,0,0,0);

             local barTempArray = {}

             self:getPositions(v,barTempArray,barBoundingbox)


             if barBoundingbox.origin.y < 350 then


                --local yellowRect = self.birdlayer.*:boundingBox();

                local yellowPoint = self.birdlayer.*:getParent():convertToWorldSpace(ccp(self.birdlayer.*:getPositionX(),self.birdlayer.*:getPositionY()));                

                

                --local redRect = self.birdlayer.RedBird:boundingBox();

                local redWordPoint = self.birdlayer.RedBird:getParent():convertToWorldSpace(ccp(self.birdlayer.RedBird:getPositionX(),self.birdlayer.RedBird:getPositionY()));



                -- 判断该sp是不是选中中得

                if v:getRotation() ==0 then


                    if barBoundingbox:containsPoint(yellowPoint) then


                        --_director:pause()

                        -- 碰撞了黄色鸟

                        _director:getScheduler():unscheduleScriptEntry(self.schId);

                        self:boump(yellowPoint,v,barTemp,self.birdlayer.*);

                        return;

                    elseif barBoundingbox:containsPoint(redWordPoint) then

                        -- 碰撞了红色的鸟

                   

                        --_director:pause()

                        _director:getScheduler():unscheduleScriptEntry(self.schId);

                        self:boump(redWordPoint,v,barTemp,self.birdlayer.RedBird);

                        return;

                    end


                else

                   

                     -- 判断碰撞检测

                    if self:checkBox(yellowPoint,barTempArray) then

                       

                        --_director:pause()

                        -- 碰撞了黄色鸟

                        _director:getScheduler():unscheduleScriptEntry(self.schId);

                        self:boump(yellowPoint,v,barTemp,self.birdlayer.*);

                       

                        return;

                    elseif self:checkBox(redWordPoint,barTempArray) then

                        -- 碰撞了红色的鸟

                      

                        --_director:pause()

                        _director:getScheduler():unscheduleScriptEntry(self.schId);

                        self:boump(redWordPoint,v,barTemp,self.birdlayer.RedBird);

                        

                        return;

                    end

                end

                barTempArray = nil

             end

        end) ;

    end

    

    -- 开启定时器

    self.schId = _director:getScheduler():scheduleScriptFunc(contactSp,1/30.0, false);

end


-- 获取4个点

function ContactListen:getPositions(barsp,barTempArray,barBoundingbox)

    barsp = tolua.cast(barsp,"CCSprite")

    barBoundingbox = tolua.cast(barBoundingbox,"CCRect")

    local rect = CCRectMake(0,0,barsp:getContentSize().width,barsp:getContentSize().height)

    local top    = rect:getMinY();

    local left   = rect:getMinX();

    local right  = rect:getMaxX();

    local bottom = rect:getMaxY();

    local anAffineTransform = barsp:nodeToParentTransform()


    local topLeft = CCPointApplyAffineTransform(CCPointMake(left, top), anAffineTransform);

    local topRight = CCPointApplyAffineTransform(CCPointMake(right, top), anAffineTransform);

    local bottomLeft = CCPointApplyAffineTransform(CCPointMake(left, bottom), anAffineTransform);

    local bottomRight = CCPointApplyAffineTransform(CCPointMake(right, bottom), anAffineTransform);


    local minX = math.min(math.min(topLeft.x, topRight.x), math.min(bottomLeft.x, bottomRight.x));

    local maxX = math.max(math.max(topLeft.x, topRight.x), math.max(bottomLeft.x, bottomRight.x));

    local minY = math.min(math.min(topLeft.y, topRight.y), math.min(bottomLeft.y, bottomRight.y));

    local maxY = math.max(math.max(topLeft.y, topRight.y), math.max(bottomLeft.y, bottomRight.y));

        

    barBoundingbox.origin = barsp:getParent():convertToWorldSpace(ccp(minX,minY));

    barBoundingbox.size = CCSizeMake((maxX - minX), (maxY - minY))

   if barsp:getRotation() ~=0 then

    table.insert(barTempArray,0,barsp:getParent():convertToWorldSpace(ccp(topLeft.x,topLeft.y)));

    table.insert(barTempArray,1,barsp:getParent():convertToWorldSpace(ccp(topRight.x,topRight.y)));

    table.insert(barTempArray,2,barsp:getParent():convertToWorldSpace(ccp(bottomRight.x,bottomRight.y)));

    table.insert(barTempArray,3,barsp:getParent():convertToWorldSpace(ccp(bottomLeft.x,bottomLeft.y)));

    --table.insert(barTempArray,4,barsp:getParent():convertToWorldSpace(ccp(topLeft.x,topLeft.y)));

    end

    


end



-- 爆炸效果

function ContactListen:boump(point,sp,barTemp,bird)


    --播放音效

    playEffect("bounding.mp3")



    bird = tolua.cast(bird,"CCSprite")

    point = tolua.cast(point,"CCPoint")

    barTemp = tolua.cast(barTemp,"CCRect")

    -- 鸟小时

    bird:setVisible(false)

    -- 先暂停

    self.gameScene:cancelTouch()

    -- 执行帧动画

    local redAry = CCArray:create()

    for i=1,6 do

        local str = string.format("boump%d.png", i);

        redAry:addObject(CCSpriteFrameCache:sharedSpriteFrameCache():spriteFrameByName(str))

    end

    local redAnimation = CCAnimation:createWithSpriteFrames(redAry,0.05);

    local redAnimate = CCAnimate:create(redAnimation);

    local boumpSp = CCSprite:createWithSpriteFrameName("boump1.png")

    boumpSp:setPosition(ccp(point.x,point.y))

    self.gameScene:addChild(boumpSp);

    -- 回调函数

    local function callFunc()

        boumpSp:removeFromParentAndCleanup(true)

       self.gameScene:resumeTouch()

       self.gameScene:gameOver();

    end

    local callFunc = CCCallFunc:create(callFunc);

    boumpSp:runAction(CCSequence:createWithTwoActions(redAnimate, callFunc));

end


-- 判断是否碰撞

function ContactListen:checkBox(p,pointArray)

    p = tolua.cast(p,"CCPoint")

    local nCross = 0;

    local nCount = table.maxn(pointArray);

    local cosin = 0

    for i=0,nCount do

        local p1 = pointArray[i];

        p1 = tolua.cast(p1,"CCPoint")

        local p2 = pointArray[(i+1)%(nCount+1)];

        p2 = tolua.cast(p2,"CCPoint")

        -- 求解 y=p.y p1p2 的交点

        local x1 = (p1.x-p.x)

        local y1 = (p1.y-p.y)

        local x2 = (p2.x-p.x)

        local y2 = (p2.y-p.y)

        local temp = (x1*x2+y1*y2)/ math.sqrt((x1*x1+y1*y1)*(x2*x2+y2*y2))


        cosin =  cosin + math.deg(math.acos(temp))

        

    end

    

    

    if cosin>=355 then


        return true;

    end


    -- 单边交点为偶数,点在多边形之外 ---

    return false;

end



-- 释放

function ContactListen:deleteSelf()

    if self.schId then

        _director:getScheduler():unscheduleScriptEntry(self.schId);

    end

    self.birdlayer = nil;

    self.rankLayer = nil;

    self = nil

end