2013-10-09 24 views
-1

我有两个精灵:一个字符精灵,另一个是障碍精灵。障碍精灵是另一个精灵,称为bgSprite的小孩,它正在不断移动。我如何检测它们之间的碰撞。 我正在使用CGRECTINTESECTRECT,但它看起来不现实。我听说box2d,但我还没有使用它。下面是一些代码:如何通过cocos2d中的box2d检测碰撞

[[CCSpriteFrameCache sharedSpriteFrameCache]  
addSpriteFramesWithFile:@"BoyRunAnimation.plist"]; 

CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode  
batchNodeWithFile:@"BoyRunAnimation.png"]; 
[self addChild:spriteSheet];   

self._character = [CCSprite spriteWithSpriteFrameName:@"Boy_Run_0003.png"]; 
self._character.position = ccp(80, 150); 
[spriteSheet addChild:self._character]; 
[self boyRunningAnimation]; 

//障碍

for (int i=0; i<5; i++) 
{ 
int xPos=500+500*i; 
if (xPos<2*_roadImage1.contentSize.width) 
{ 
    CCSprite *obstacle=[CCSprite node]; 
    obstacle.textureRect=CGRectMake(0, 0, 50, _roadImage1.contentSize.height); 
    obstacle.color=ccc3(255, 255,255); 

    if (xPos <= _roadImage1.contentSize.width) 
    { 
     obstacle.position=ccp(xPos, _roadImage1.contentSize.height/2); 

     [_roadImage1 addChild:obstacle z:0 tag:1]; 
    } 
    else 
    { 
     obstacle.position=ccp(xPos-_roadImage1.contentSize.width, 60); 

     [_roadImage2 addChild:obstacle z:0 tag:2]; 
    } 
    [obstacleArray addObject:obstacle]; 
}  
} 

在更新方法:

CCRect obstacleBox = [obstacle boundingBox]; 
    CCPoint obstaclePosition = obstacleBox.origin; 
    obstaclePosition = [[obstacle parent] convertToWorldSpace:obstaclePosition]; 
    obstaclePosition = [[self._character parent] convertToNodeSpace:obstaclePosition]; 
    obstacleBox.origin = obstaclePosition; 
    if (CGRectIntersectsRect(self._character.boundingBox, obstacleBox)) 
    { 
    isTouchActive=NO; 
    NSLog(@"collision"); 
    } 

请帮助我。

+0

检查Box2D的手册http://box2d.org/manual.pdf并遵循Box2D的教程:https://www.google.de/search?client=safari&rls = EN&q = cocos2d的+ Box2D的+教程&即= UTF-8&OE = UTF-8&gws_rd = CR EI = A1tVUpqbCa6p7Aam64HIBg#q =的cocos2d-iphone + Box2D的+教程&RLS = EN – LearnCocos2D

回答

0

如果您使用box2d,则在处理世界更新时,Box2d引擎会处理冲突检测。这检测身体上的固定装置之间的碰撞,而不是身体本身。所以如果你的身体是由一组固定物组成的,你可以将身体检测到身体的一小部分,以使爆炸(或其他)的位置看起来很好。

简单的答案是从b2ContactListener派生一个类并告诉你想使用它的b2World。从本手册的例子是这样的:

class MyContactListener : public b2ContactListener 
{ 
public: 
void BeginContact(b2Contact* contact) { /* handle begin event */ } 
void EndContact(b2Contact* contact) { /* handle end event */ } 
void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) { /* handle pre-solve event */ } 
void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) 
{ /* handle post-solve event */ } 
}; 

你在你的派生类的一个实例使用b2World :: SetContactListener(...)注册。

然而,它不是那么简单。我的经验是,对于单次“碰撞”,您可以在世界更新期间多次致电您的班级。

下面是一个更完整的解决方案。在此,世界上的每个“事物”都有一个b2Body,并且用户标记指向根类(称为实体)。它会累积冲突列表并检查每个新事件是否引用一个已经看到的对,并过滤掉重复对象。在世界更新之后,NotifyCollisions被调用来向发生冲突的实体发送消息,并且他们需要做一些事情。

这是更大的代码库的一部分;随时提出任何问题,如果你需要澄清,因为代码不在这里。

class EntityContactListener : public ContactListener 
{ 
private: 
    GameWorld* _gameWorld; 
    EntityContactListener() {} 

    typedef struct 
    { 
     Entity* entA; 
     Entity* entB; 
    } CONTACT_PAIR_T; 

    vector<CONTACT_PAIR_T> _contactPairs; 

public: 
    virtual ~EntityContactListener() {} 

    EntityContactListener(GameWorld* gameWorld) : 
     _gameWorld(gameWorld) 
    { 
     _contactPairs.reserve(128); 
    } 

    void NotifyCollisions() 
    { 
     Message* msg; 
     MessageManager& mm = GameManager::Instance().GetMessageMgr(); 

     for(uint32 idx = 0; idx < _contactPairs.size(); idx++) 
     { 
     Entity* entA = _contactPairs[idx].entA; 
     Entity* entB = _contactPairs[idx].entB; 

     //DebugLogCPP("Contact Notification %s<->%s",entA->ToString().c_str(),entB->ToString().c_str()); 

     msg = mm.CreateMessage(); 
     msg->Init(entA->GetID(), entB->GetID(), Message::MESSAGE_COLLISION); 
     mm.EnqueueMessge(msg, 0); 

     msg = mm.CreateMessage(); 
     msg->Init(entB->GetID(), entA->GetID(), Message::MESSAGE_COLLISION); 
     mm.EnqueueMessge(msg, 0);   
     } 
     _contactPairs.clear(); 
    } 

    void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) 
    { 

    } 

    // BEWARE: You may get multiple calls for the same event. 
    void BeginContact(b2Contact* contact) 
    { 
     Entity* entA = (Entity*)contact->GetFixtureA()->GetBody()->GetUserData(); 
     Entity* entB = (Entity*)contact->GetFixtureB()->GetBody()->GetUserData(); 
     //DebugLogCPP("Begin Contact %s->%s",entA->ToString().c_str(),entB->ToString().c_str()); 
     if(entA->GetGroupID() == entB->GetGroupID()) 
     { // Can't collide if they are in the same group. 
     return; 
     } 

     assert(entA != NULL); 
     assert(entB != NULL); 

     for(uint32 idx = 0; idx < _contactPairs.size(); idx++) 
     { 
     if(_contactPairs[idx].entA == entA && _contactPairs[idx].entB == entB) 
      return; 
     // Not sure if this is needed... 
     if(_contactPairs[idx].entA == entB && _contactPairs[idx].entA == entB) 
      return; 
     } 
     CONTACT_PAIR_T pair; 
     pair.entA = entA; 
     pair.entB = entB; 
     _contactPairs.push_back(pair); 
    } 

    // BEWARE: You may get multiple calls for the same event. 
    void EndContact(b2Contact* contact) 
    { 
     /* 
     Entity* entA = (Entity*)contact->GetFixtureA()->GetBody()->GetUserData(); 
     Entity* entB = (Entity*)contact->GetFixtureB()->GetBody()->GetUserData(); 
     DebugLogCPP("End Contact %s->%s",entA->ToString().c_str(),entB->ToString().c_str()); 
     */ 
    } 
}; 

对您有帮助吗?