Cocos2d iphone 在没有连续碰撞的情况下检测两个box2d实体的初始碰撞
我有一些简单的box2d Body设置,带有联系人侦听器,如下所示:Cocos2d iphone 在没有连续碰撞的情况下检测两个box2d实体的初始碰撞,cocos2d-iphone,box2d,physics,Cocos2d Iphone,Box2d,Physics,我有一些简单的box2d Body设置,带有联系人侦听器,如下所示: #import "MyContactListener.h" MyContactListener::MyContactListener() : _contacts() { } MyContactListener::~MyContactListener() { } void MyContactListener::BeginContact(b2Contact* contact) { // We need to copy out
#import "MyContactListener.h"
MyContactListener::MyContactListener() : _contacts() {
}
MyContactListener::~MyContactListener() {
}
void MyContactListener::BeginContact(b2Contact* contact) {
// We need to copy out the data because the b2Contact passed in
// is reused.
MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() };
_contacts.push_back(myContact);
b2Body *A = contact->GetFixtureA()->GetBody();
b2Body *B = contact->GetFixtureA()->GetBody();
NSLog(@"Collision detected!");
PLAYSOUND(COLLISION);
}
void MyContactListener::EndContact(b2Contact* contact) {
MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() };
std::vector<MyContact>::iterator pos;
pos = std::find(_contacts.begin(), _contacts.end(), myContact);
if (pos != _contacts.end()) {
_contacts.erase(pos);
}
}
void MyContactListener::PreSolve(b2Contact* contact, const b2Manifold* oldManifold) {
}
void MyContactListener::PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) {
}
#导入“MyContactListener.h”
MyContactListener::MyContactListener():_contacts(){
}
MyContactListener::~MyContactListener(){
}
void MyContactListener::BeginContact(b2Contact*contact){
//我们需要复制数据,因为B2B联系人传入了
//重复使用。
MyContact MyContact={contact->GetFixtureA(),contact->GetFixtureB()};
_触点。推回(myContact);
b2Body*A=联系人->GetFixtureA()->GetBody();
b2Body*B=联系人->GetFixtureA()->GetBody();
NSLog(@“检测到冲突!”);
播放声音(碰撞);
}
void MyContactListener::EndContact(b2Contact*contact){
MyContact MyContact={contact->GetFixtureA(),contact->GetFixtureB()};
std::vector::iterator pos;
pos=std::find(_contacts.begin(),_contacts.end(),myContact);
如果(位置=_contacts.end()){
_触点。擦除(pos);
}
}
void MyContactListener::PreSolve(b2Contact*contact,const b2Manifold*oldManifold){
}
void MyContactListener::PostSolve(b2Contact*触点,常量b2ContactImpulse*脉冲){
}
当两个物体碰撞时,我需要播放一个声音。但是,此实现检测连续碰撞,以便在身体接触时播放声音。我对Box 2D和C++的知识已经非常有限,有没有简单的方法来检测新的碰撞而不检测连续的碰撞? < P>首先设置这样的定时器…< /P>
[self schedule:@selector(check collision:)];
在这个方法中
- (void)tick:(ccTime) dt
{
for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext())
{
//--------------My contact Listener Start-------------------------
std::vector<MyContact>::iterator pos;
for(pos = _contactListener->_contacts.begin(); pos != _contactListener->_contacts.end(); ++pos)
{
MyContact contact = *pos;
// Here get your sprite and make their fixture and check...
if ((contact.fixtureA == tempballFixture && contact.fixtureB == _mainballFixture) ||
(contact.fixtureA == _mainballFixture && contact.fixtureB == tempballFixture))
{
if(mainDelegate.music_playing == TRUE)
{
[[SimpleAudioEngine sharedEngine] playEffect:@"Rock impact.mp3"];
}
//-------------collision count for update score value--------
}
}
-(无效)勾选:(ccTime)dt
{
对于(b2Body*b=_world->GetBodyList();b;b=b->GetNext())
{
//--------------我的联系人侦听器启动-------------------------
std::vector::iterator pos;
对于(pos=_contactListener->_contacts.begin();pos!=_contactListener->_contacts.end();++pos)
{
MyContact contact=*位置;
//来拿你的雪碧,做他们的固定装置,然后检查。。。
if((contact.fixtureA==tempball fixture&&contact.fixtureB===\u MainbalFixture)||
(contact.fixtureA==\u mainballFixture&&contact.fixtureB==tempballFixture))
{
if(mainDelegate.music_playing==TRUE)
{
[[SimpleAudioEngine sharedEngine]播放效果:@“Rock impact.mp3”];
}
//-------------更新分数值的冲突计数--------
}
}
您的基本想法是正确的,但它需要一些改进
在您的BeginContact(…)通话中,您有:
PLAYSOUND(COLLISION);
不要在这里播放声音,你应该做的是让其他系统排队播放这对特定的声音。将你身体的userdata标记设置为指向类的指针(或其他一些ID以跟踪实体)。如下所示:
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());
*/
}
};
类EntityContactListener:公共ContactListener
{
私人:
游戏世界*\u游戏世界;
EntityContactListener(){}
类型定义结构
{
实体*entA;
实体*entB;
}接触线对;
矢量接触对;
公众:
虚拟~EntityContactListener(){}
EntityContactListener(游戏世界*游戏世界):
_游戏世界(gameWorld)
{
_触点对。保留(128);
}
void
{
讯息*msg;
MessageManager&mm=GameManager::Instance().GetMessageMgr();
对于(uint32 idx=0;idx<_contactPairs.size();idx++)
{
实体*entA=_contactPairs[idx].entA;
实体*entB=_contactPairs[idx].entB;
//DebugLogCPP(“联系通知%s%s”,entA->ToString().c_str(),entB->ToString().c_str());
msg=mm.CreateMessage();
msg->Init(entA->GetID(),entB->GetID(),Message::Message\u冲突);
mm.排队消息(msg,0);
msg=mm.CreateMessage();
msg->Init(entB->GetID(),entA->GetID(),Message::Message\u冲突);
mm.排队消息(msg,0);
}
_contactPairs.clear();
}
无效预溶解(b2Contact*contact,常数b2Manifold*oldManifold)
{
}
//注意:同一事件可能会有多个呼叫。
无效BeginContact(b2Contact*contact)
{
实体*entA=(实体*)联系人->GetFixtureA()->GetBody()->GetUserData();
实体*entB=(实体*)联系人->GetFixtureB()->GetBody()->GetUserData();
//DebugLogCPP(“开始联系人%s->%s”,entA->ToString().c_str(),entB->ToString().c_str());
如果(entA->GetGroupID()==entB->GetGroupID())
{//如果它们在同一组中,则无法碰撞。
返回;
}
断言(entA!=NULL);
断言(entB!=NULL);
对于(uint32 idx=0;idx<_contactPairs.size();idx++)
{
if(_contactPairs[idx].entA==entA&&u contactPairs[idx].entB==entB)
返回;
//不确定是否需要这个。。。
if(_contactPairs[idx].entA==entB&&u contactPairs[idx].entA==entB)
返回;
}
接触线对;
pair.entA=entA;
pair.entB=entB;
_触点对。推回(对);
}
//注意:同一事件可能会有多个呼叫。
无效结束触点(b2Contact*触点)
{
/*
实体*entA=(实体*)联系人->GetFixtureA()->GetBody()->GetUserData();
实体*entB=(实体*)联系人->GetFixtureB()->GetBody()->GetUserData();
DebugLogCPP(“结束联系人%s->%s”,entA->ToString().c_str(),entB->ToString().c_str());
*/
}
};
最后一部分是,即使发生碰撞,也不要在短时间内再次播放声音。您可以通过创建秒表或从实体更新周期的固定时间开始倒计时来完成此操作
这有帮助吗?我建议您仔细检查,这样您就可以在“两个物体发生碰撞时”检测到单个碰撞“=开始接触。这不是一个co