2013-10-09 23 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()); 
     */ 
    } 
}; 

對您有幫助嗎?