2013-08-11 6 views
3

Я новичок в мире Cocos2D и даже больше в Box2D. Я разрабатываю игру iOS с этими двумя двигателями, и я хочу, чтобы парень (герой) собирал монеты на прокручиваемой карте.Столкновение без физики (Cocos2D + Box2D iOS)

Ну, проблема в том, что «Слушатель контактов». Я не могу понять, что он на самом деле делает, и как я могу использовать его, чтобы сделать разницу между моими монетами и другими телами (все статические тела) вокруг карты. Я установил все монеты .isSensor = true, чтобы отключить коллизии. Я использую MyContactListener из учебника raywenderlich.com.

Итак, главный вопрос: как узнать, какой тип тела находится в столкновении с телом героя через контакт-слушатель?

(я читал много учебников и вопросов здесь, и я не могу знать, с чего начать)

Спасибо!

Edit:

Si, я, наконец, получил его на работу с sprite.tag, но я не могу уничтожить тела и текстуры. Иногда при использовании [textureB removeFromParentAndCleanup:YES]; я получаю EXC_BAD_ACCESS. И, как я понял, я не могу уничтожить тело, так как фактически использую его.

Но при попытке использовать body->SetUserData(self); в моем Hero класса

@interface Hero : CCNode { 
CCSprite * texture; 
CGPoint position; 
b2Body* body; 
TypeCase type; 
} 

Я получаю EXC_BAD_ACCESS в моем методе обновления:

for(b2Body *b = world_->GetBodyList(); b; b=b->GetNext()) { 
    if (b->GetUserData() != NULL) { 
     if ([b->GetUserData() isKindOfClass:[Hero class]]) 
     { 
      Hero* hero = (Hero*)b->GetUserData(); 
      CCSprite *heroSprite = hero.texture; 
      heroSprite.position = ccp(b->GetPosition().x * PTM_RATIO, 
           b->GetPosition().y * PTM_RATIO); 
     } 
     else if ([b->GetUserData() isKindOfClass:[Tile class]]) 
     { 
      Tile* tile = (Tile*)b->GetUserData(); 
      CCSprite *tileSprite = tile.texture; 
      tileSprite.position = ccp(b->GetPosition().x * PTM_RATIO, 
           b->GetPosition().y * PTM_RATIO); 
     }  
    } 
} 

Я получаю EXC_BAD_ACCESS при вызове isKindOfClass.

Hero USERDATA

b2BodyDef heroBodyDef; 
heroBodyDef.fixedRotation = true; 
heroBodyDef.type = b2_dynamicBody; 
heroBodyDef.position.Set(position.x/PTM_RATIO, position.y/PTM_RATIO); 
body = world_->CreateBody(&heroBodyDef); 
body->SetUserData(self); 

Плитка USERDATA

b2BodyDef blockBodyDef; 
blockBodyDef.type = b2_staticBody; 
blockBodyDef.position.Set(position.x/PTM_RATIO, position.y/PTM_RATIO); 
blockBodyDef.userData = self; 
b2Body *body = world ->CreateBody(&blockBodyDef); 
+0

Почему isKindOfClass не работает для вас? и в какой строке вы получаете исключение? – giorashc

+0

Я отредактировал метод обновления: я получаю исключение, когда вызывается isKindOfClass. – thegameg

+0

Кажется, что данные были выпущены где-то перед тем, как вы его получили. Можете ли вы опубликовать код, в котором вы размещаете данные пользователя тела? используете ли вы ARC в своем проекте? – giorashc

ответ

3

Не использовать физику объектов для монет .. это будет влиять на кадр :) создать CCSprite для монет и обнаружения столкновения с монетическим спрайтом и телом -> UserData; Добавить свои монеты в CCArray и написать что-то вроде этого в вашем методе обновления:

CCSprite *sprite = (CCSprite*)yourObject.body->GetUserData(); 
Coins *coinObject; 
CCARRAY_FOREACH(coinsArray, coinObject) 
    { 
    if (CGRectIntersectsRect([sprite boundingBox], [coinObject boundingBox])) 
     { 
     // collision detected; 
     } 
    } 

, если вы хотите использовать физику тела для монет, вам нужно создать ЬурейеЕ для государств yourObject, и в вашем контактном слушателю void ContactListener::EndContact(b2Contact* contact) метод измените yourObject currentState. currentState - свойство yourObject. ли что-то подобное в void ContactListener::EndContact(b2Contact* contact)

yourObject.currentState = isCollideOnCoin; 

и после этого в вашем обновлении добавьте следующую строку:

if (yourObject.currentState == isCollideOnCoin) 
{ 
// collision detected; 
} 
+0

В первом методе, при каждом обновлении, я действительно проверяю, мой герой трогает каждую монету массива, верно? Это то, что делает ContactListener, но с телами вместо спрайтов? – thegameg

+1

Да, первый метод работает именно так, и я всегда использую его. ContactListener использует обратные вызовы, для получения дополнительной информации вы можете проверить этот учебник http://www.iforce2d.net/b2dtut/collision-callbacks – K1laba

2

Вы можете создать собственный класс (скажем BodyType), который указывает тип органы (в вашем случае игроку/монета)

, то вы можете использовать свойство пользовательских данных на ваших созданных тел:

playerBody->SetUserData(new BodyType(1)); 
coinBody->SetUserData(new BodyType(2)); 

В прослушивателе контактов есть метод с именем beginContact, который имеет аргумент типа b2Contact* с именем contact.

Используйте этот аргумент, чтобы получить два тела:

b2Body* bodyA = contact->GetFixtureA()->GetBody(); 
b2Body* bodyB = contact->GetFixtureB()->GetBody(); 

, то вы можете знать, если ваш игрок ударил монету, проверяя:

if ((bodyA->GetUserData().getType() == 1 && bodyB->GetUserData().getType() == 2) || 
    (bodyA->GetUserData().getType() == 2 && bodyB->GetUserData().getType() == 1)) { 
    // Mark collision or save coin body in a member of your contact listener for removing it later 
} 
  • Конечно убедитесь, что данные пользователя не null, поскольку все тела будут переданы слушателю контакта, и не все могут иметь набор пользовательских данных.

EDIT

Что касается BAD_ACCESS сделать следующее:

if (b->GetUserData() != NULL) { 
    id myUserData = (id)b->GetUserData(); 

    if ([myUserData isKindOfClass:[Hero class]]) 
    { 
     Hero *hero = (Hero *)myUserData; 
     // Do your stuff 
    } 
} 
+0

Я начинаю понимать это, но у меня есть одна проблема. Пользовательские данные для моих тел - их текстура. Есть ли способ включить этот тип? – thegameg

+0

Ну, вы можете создать класс-оболочку как для текстуры, так и для тела ... Поскольку userData является указателем на пустоту, у вас есть бесконечные возможности :) – giorashc

+0

У меня есть класс героя, и я устанавливаю 'body-> SetUserData (self); 'но похоже, что он ошибается, потому что все поля ошибочны. – thegameg