学习cocos2dx就要了解cocos2dx 多边形碰撞检测,那么cocos2dx 多边形碰撞检测是怎样实现的呢?今天我们就来学习。
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.yellowbird:boundingBox();
local yellowPoint = self.birdlayer.yellowbird:getParent():convertToWorldSpace(ccp(self.birdlayer.yellowbird:getPositionX(),self.birdlayer.yellowbird: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.yellowbird);
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.yellowbird);
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);
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
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.yellowbird:boundingBox();
local yellowPoint = self.birdlayer.yellowbird:getParent():convertToWorldSpace(ccp(self.birdlayer.yellowbird:getPositionX(),self.birdlayer.yellowbird: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.yellowbird);
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.yellowbird);
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