Cocos2d-x 3 - отключить столкновение между двумя телами и определить, когда они разделяются друг с другом

Я разрабатываю игру cocos2d-x (версия 3.8). Моя игра использует физику бурундука и имеет статическое тело, которое работает как прерыватель. Этот прерыватель включается, когда над ним находится другое тело. Прерыватель отключается, когда тела расходятся.

Я хочу:

  • Движущееся тело не сталкивается с прерывателем. Он должен пересечь прерыватель без отскока
  • Я хочу обнаружить, когда движущееся тело отделяет прерыватель

Мой первый подход заключался в реализации метода onContactBegin. Я возвращаю false, когда эти два тела соприкасаются. Таким образом, тело пересекает прерыватель и не отскакивает.

Проблема в том, что метод onContactSeparate не вызывается, так как контакта не произошло.

Если я возвращаю true в методе onContactBegin, вызывается onContactSeparate, и я могу это обнаружить. Проблема в том, что тело не пересекает прерыватель, оно отскакивает.

[EDIT] Подробнее

Это сценарий, в котором два спрайта разделены. Мяч может двигаться, а прерыватель является статическим телом. Мяч мог оказаться над прерывателем.

Прерыватель отключен

Это сценарий, в котором два спрайта соприкасаются, а объект1 (мяч) находится над прерывателем. Я хочу определить, где два спрайта разделяют друг друга.

Прерыватель включен

Любая помощь будет оценена по достоинству!


person Daniel Albert    schedule 29.09.2015    source источник


Ответы (1)


Мне кажется, что вы используете Box2D в кокосах, поэтому я отвечу на это как на свое основное предположение.

Это то, что я бы сделал.

  1. Моим прерывателем будет b2Body* без определенных измерений BodyDef или просто определение измерения 0x0.
  2. Я бы установил пользовательские данные для bodyDef в виде прямоугольника, описывающего мою область прерывания. Таким образом, вы всегда можете представить свою область прерывания, но ни с чем не столкнетесь.
  3. (Необязательно) Если вы хотите, чтобы область прерывания перемещалась на основе фиктивного тела, которое вы ей назначили, вы можете обновить его сразу после пошаговой функции, используя что-то вроде ниже.

    world->Step(delta, 10, 10);   
    for (auto physicsBody = _world->GetBodyList(); physicsBody; physicsBody = physicsBody->GetNext())
    { 
     auto userData = static_cast<Node*>(physicsBody->GetUserData());
     if(userData != NULL)
     {
       // Set interruptor area rectangle = physicsBody->GetPosition();
     }
    }
    
  4. Чтобы остальная часть системы знала, когда я покину прерыватель, я бы сохранил указатель функции на функцию, которую я хочу вызвать, когда это произойдет. " после этого, первый шаг обновления, который вы получаете, когда он больше не находится в области, я запускаю обратный вызов и сбрасываю флаги, которые я использовал, чтобы добраться до этой точки.

Надеюсь, это поможет. Вы не даете много контекста для того, что вы хотите сделать, изображение было бы полезно. Особенно, когда речь идет о поиске помощи с кодом, который также имеет визуальное представление.

[РЕДАКТИРОВАТЬ] Основываясь на желаемом поведении, я сделал это так. Первое, что нужно знать, это то, что вам не нужны коллизии физики для желаемого поведения. Вы можете сделать это, используя тесты пересечения ограничивающей рамки и использовать флаги и обратные вызовы, чтобы выяснить все остальное.

У меня есть объект, который знает и о шаре, и о моих узлах-прерывателях. В цикле обновления этого объекта я проверяю, пересекаются ли они. Я устанавливаю флаг, указывающий «Я в прерывателе», в следующем кадре, что я не в прерывателе, и мой флаг все еще верен, я вызываю функцию, которую я назначил с моей «логикой выхода» в его, а затем установите флаг обратно в false.

person Filled Stacks    schedule 30.09.2015
comment
Спасибо, но я использую физику бурундука. Я добавил дополнительную информацию и несколько изображений, показывающих, как это должно работать. - person Daniel Albert; 30.09.2015
comment
@DanielAlbert Из редактирования вы пишете, что хотите определить, где два спрайта разделяют друг друга? Означает ли это, что вы хотите знать, когда спрайты перестают сталкиваться и удаляются друг от друга? или вы хотите знать точки пересечения спрайтов при столкновении? - person Filled Stacks; 01.10.2015
comment
да, мне нужен только обратный вызов, чтобы определить момент, когда два спрайта разделяют друг друга. Что-то вроде обратного вызова onContactSeparate, когда происходит столкновение. Мне не нужны точки пересечения. - person Daniel Albert; 01.10.2015
comment
@DanielAlbert хорошо. В cocos2d-x вы получаете что-то, называемое EventListenerPhysicsContact, вы можете создать его, используя статическую функцию создания. на этом слушателе у вас есть 4 открытые функции для разрешения контактов. onContactBegin, onContactPreSolve и onContactSeperate. назначьте обратный вызов onContactSeperate и поместите туда свою логику для разделения. Убедитесь, что ваш onContactBegin возвращает false, чтобы вы могли игнорировать реакцию столкновения (если хотите) - person Filled Stacks; 02.10.2015
comment
но если я возвращаю false в onContactBegin, обратный вызов onContactSeparate не вызывается. Он вызывается только в том случае, если onContactBegin возвращает значение true. Если я возвращаю true в методе onContactBegin, два тела сталкиваются, и мяч не пересекает прерыватель. - person Daniel Albert; 02.10.2015
comment
@DanielAlbert, пожалуйста, смотрите отредактированный ответ выше. Я реализовал поведение, которое вы хотите, и я объясню, как я это сделал в своем редактировании. - person Filled Stacks; 02.10.2015