Merge pull request #5312 from dumganhar/merge5268

closed #3716:PhysicsContact should be inherited from EventCustom, it will simplify the logic of emitting collision events
This commit is contained in:
James Chen 2014-02-10 14:37:43 +08:00
commit e90e0b0c23
7 changed files with 54 additions and 60 deletions

View File

@ -37,7 +37,7 @@ NS_CC_BEGIN
const char* PHYSICSCONTACT_EVENT_NAME = "PhysicsContactEvent"; const char* PHYSICSCONTACT_EVENT_NAME = "PhysicsContactEvent";
PhysicsContact::PhysicsContact() PhysicsContact::PhysicsContact()
: Event(Event::Type::CUSTOM) : EventCustom(PHYSICSCONTACT_EVENT_NAME)
, _world(nullptr) , _world(nullptr)
, _shapeA(nullptr) , _shapeA(nullptr)
, _shapeB(nullptr) , _shapeB(nullptr)
@ -200,32 +200,37 @@ bool EventListenerPhysicsContact::init()
void EventListenerPhysicsContact::onEvent(EventCustom* event) void EventListenerPhysicsContact::onEvent(EventCustom* event)
{ {
PhysicsContact& contact = *(PhysicsContact*)(event->getUserData()); PhysicsContact* contact = dynamic_cast<PhysicsContact*>(event);
switch (contact.getEventCode()) if (contact == nullptr)
{
return;
}
switch (contact->getEventCode())
{ {
case PhysicsContact::EventCode::BEGIN: case PhysicsContact::EventCode::BEGIN:
{ {
bool ret = true; bool ret = true;
if (onContactBegin != nullptr if (onContactBegin != nullptr
&& hitTest(contact.getShapeA(), contact.getShapeB())) && hitTest(contact->getShapeA(), contact->getShapeB()))
{ {
contact._begin = true; contact->_begin = true;
contact.generateContactData(); contact->generateContactData();
// the mask has high priority than _listener->onContactBegin. // the mask has high priority than _listener->onContactBegin.
// so if the mask test is false, the two bodies won't have collision. // so if the mask test is false, the two bodies won't have collision.
if (ret) if (ret)
{ {
ret = onContactBegin(event, contact); ret = onContactBegin(*contact);
}else }else
{ {
onContactBegin(event, contact); onContactBegin(*contact);
} }
} }
contact.setResult(ret); contact->setResult(ret);
break; break;
} }
case PhysicsContact::EventCode::PRESOLVE: case PhysicsContact::EventCode::PRESOLVE:
@ -233,34 +238,34 @@ void EventListenerPhysicsContact::onEvent(EventCustom* event)
bool ret = true; bool ret = true;
if (onContactPreSolve != nullptr if (onContactPreSolve != nullptr
&& hitTest(contact.getShapeA(), contact.getShapeB())) && hitTest(contact->getShapeA(), contact->getShapeB()))
{ {
PhysicsContactPreSolve solve(contact._begin ? nullptr : contact._contactData, contact._contactInfo); PhysicsContactPreSolve solve(contact->_begin ? nullptr : contact->_contactData, contact->_contactInfo);
contact._begin = false; contact->_begin = false;
contact.generateContactData(); contact->generateContactData();
ret = onContactPreSolve(event, contact, solve); ret = onContactPreSolve(*contact, solve);
} }
contact.setResult(ret); contact->setResult(ret);
break; break;
} }
case PhysicsContact::EventCode::POSTSOLVE: case PhysicsContact::EventCode::POSTSOLVE:
{ {
if (onContactPostSolve != nullptr if (onContactPostSolve != nullptr
&& hitTest(contact.getShapeA(), contact.getShapeB())) && hitTest(contact->getShapeA(), contact->getShapeB()))
{ {
PhysicsContactPostSolve solve(contact._contactInfo); PhysicsContactPostSolve solve(contact->_contactInfo);
onContactPostSolve(event, contact, solve); onContactPostSolve(*contact, solve);
} }
break; break;
} }
case PhysicsContact::EventCode::SEPERATE: case PhysicsContact::EventCode::SEPERATE:
{ {
if (onContactSeperate != nullptr if (onContactSeperate != nullptr
&& hitTest(contact.getShapeA(), contact.getShapeB())) && hitTest(contact->getShapeA(), contact->getShapeB()))
{ {
onContactSeperate(event, contact); onContactSeperate(*contact);
} }
break; break;
} }

View File

@ -32,6 +32,7 @@
#include "CCGeometry.h" #include "CCGeometry.h"
#include "CCEventListenerCustom.h" #include "CCEventListenerCustom.h"
#include "CCEvent.h" #include "CCEvent.h"
#include "CCEventCustom.h"
NS_CC_BEGIN NS_CC_BEGIN
@ -58,7 +59,7 @@ typedef struct PhysicsContactData
/** /**
* @brief Contact infomation. it will created automatically when two shape contact with each other. and it will destoried automatically when two shape separated. * @brief Contact infomation. it will created automatically when two shape contact with each other. and it will destoried automatically when two shape separated.
*/ */
class PhysicsContact : public Event class PhysicsContact : public EventCustom
{ {
public: public:
@ -201,20 +202,20 @@ public:
/* /*
* @brief it will called at two shapes start to contact, and only call it once. * @brief it will called at two shapes start to contact, and only call it once.
*/ */
std::function<bool(EventCustom* event, const PhysicsContact& contact)> onContactBegin; std::function<bool(PhysicsContact& contact)> onContactBegin;
/* /*
* @brief Two shapes are touching during this step. Return false from the callback to make world ignore the collision this step or true to process it normally. Additionally, you may override collision values, elasticity, or surface velocity values. * @brief Two shapes are touching during this step. Return false from the callback to make world ignore the collision this step or true to process it normally. Additionally, you may override collision values, elasticity, or surface velocity values.
*/ */
std::function<bool(EventCustom* event, const PhysicsContact& contact, const PhysicsContactPreSolve& solve)> onContactPreSolve; std::function<bool(PhysicsContact& contact, PhysicsContactPreSolve& solve)> onContactPreSolve;
/* /*
* @brief Two shapes are touching and their collision response has been processed. You can retrieve the collision impulse or kinetic energy at this time if you want to use it to calculate sound volumes or damage amounts. See cpArbiter for more info * @brief Two shapes are touching and their collision response has been processed. You can retrieve the collision impulse or kinetic energy at this time if you want to use it to calculate sound volumes or damage amounts. See cpArbiter for more info
*/ */
std::function<void(EventCustom* event, const PhysicsContact& contact, const PhysicsContactPostSolve& solve)> onContactPostSolve; std::function<void(PhysicsContact& contact, const PhysicsContactPostSolve& solve)> onContactPostSolve;
/* /*
* @brief it will called at two shapes separated, and only call it once. * @brief it will called at two shapes separated, and only call it once.
* onContactBegin and onContactSeperate will called in pairs. * onContactBegin and onContactSeperate will called in pairs.
*/ */
std::function<void(EventCustom* event, const PhysicsContact& contact)> onContactSeperate; std::function<void(PhysicsContact& contact)> onContactSeperate;
protected: protected:
bool init(); bool init();

View File

@ -283,9 +283,7 @@ int PhysicsWorld::collisionBeginCallback(PhysicsContact& contact)
contact.setEventCode(PhysicsContact::EventCode::BEGIN); contact.setEventCode(PhysicsContact::EventCode::BEGIN);
contact.setWorld(this); contact.setWorld(this);
EventCustom event(PHYSICSCONTACT_EVENT_NAME); _scene->getEventDispatcher()->dispatchEvent(&contact);
event.setUserData(&contact);
_scene->getEventDispatcher()->dispatchEvent(&event);
return ret ? contact.resetResult() : false; return ret ? contact.resetResult() : false;
} }
@ -300,9 +298,7 @@ int PhysicsWorld::collisionPreSolveCallback(PhysicsContact& contact)
contact.setEventCode(PhysicsContact::EventCode::PRESOLVE); contact.setEventCode(PhysicsContact::EventCode::PRESOLVE);
contact.setWorld(this); contact.setWorld(this);
EventCustom event(PHYSICSCONTACT_EVENT_NAME); _scene->getEventDispatcher()->dispatchEvent(&contact);
event.setUserData(&contact);
_scene->getEventDispatcher()->dispatchEvent(&event);
return contact.resetResult(); return contact.resetResult();
} }
@ -316,9 +312,7 @@ void PhysicsWorld::collisionPostSolveCallback(PhysicsContact& contact)
contact.setEventCode(PhysicsContact::EventCode::POSTSOLVE); contact.setEventCode(PhysicsContact::EventCode::POSTSOLVE);
contact.setWorld(this); contact.setWorld(this);
EventCustom event(PHYSICSCONTACT_EVENT_NAME); _scene->getEventDispatcher()->dispatchEvent(&contact);
event.setUserData(&contact);
_scene->getEventDispatcher()->dispatchEvent(&event);
} }
void PhysicsWorld::collisionSeparateCallback(PhysicsContact& contact) void PhysicsWorld::collisionSeparateCallback(PhysicsContact& contact)
@ -330,9 +324,7 @@ void PhysicsWorld::collisionSeparateCallback(PhysicsContact& contact)
contact.setEventCode(PhysicsContact::EventCode::SEPERATE); contact.setEventCode(PhysicsContact::EventCode::SEPERATE);
contact.setWorld(this); contact.setWorld(this);
EventCustom event(PHYSICSCONTACT_EVENT_NAME); _scene->getEventDispatcher()->dispatchEvent(&contact);
event.setUserData(&contact);
_scene->getEventDispatcher()->dispatchEvent(&event);
} }
void PhysicsWorld::rayCast(PhysicsRayCastCallbackFunc func, const Point& point1, const Point& point2, void* data) void PhysicsWorld::rayCast(PhysicsRayCastCallbackFunc func, const Point& point1, const Point& point2, void* data)

View File

@ -1175,11 +1175,10 @@ static int tolua_cocos2dx_EventListenerPhysicsContact_registerScriptHandler(lua_
{ {
ScriptHandlerMgr::getInstance()->addObjectHandler((void*)self, handler, type); ScriptHandlerMgr::getInstance()->addObjectHandler((void*)self, handler, type);
self->onContactBegin = [handler](EventCustom* event, const PhysicsContact& contact) -> bool{ self->onContactBegin = [handler](PhysicsContact& contact) -> bool{
LuaStack* stack = LuaEngine::getInstance()->getLuaStack(); LuaStack* stack = LuaEngine::getInstance()->getLuaStack();
stack->pushObject(event, "cc.EventCustom"); stack->pushObject(&contact, "cc.PhysicsContact");
stack->pushObject(const_cast<PhysicsContact*>(&contact), "cc.PhysicsContact"); bool ret = stack->executeFunctionByHandler(handler, 1);
bool ret = stack->executeFunctionByHandler(handler, 2);
stack->clean(); stack->clean();
return ret; return ret;
@ -1190,12 +1189,11 @@ static int tolua_cocos2dx_EventListenerPhysicsContact_registerScriptHandler(lua_
{ {
ScriptHandlerMgr::getInstance()->addObjectHandler((void*)self, handler, type); ScriptHandlerMgr::getInstance()->addObjectHandler((void*)self, handler, type);
self->onContactPreSolve = [handler](EventCustom* event, const PhysicsContact& contact, const PhysicsContactPreSolve& solve) -> bool{ self->onContactPreSolve = [handler](PhysicsContact& contact, PhysicsContactPreSolve& solve) -> bool{
LuaStack* stack = LuaEngine::getInstance()->getLuaStack(); LuaStack* stack = LuaEngine::getInstance()->getLuaStack();
stack->pushObject(event, "cc.EventCustom"); stack->pushObject(&contact, "cc.PhysicsContact");
stack->pushObject(const_cast<PhysicsContact*>(&contact), "cc.PhysicsContact"); tolua_pushusertype(stack->getLuaState(), &solve, "cc.PhysicsContactPreSolve");
tolua_pushusertype(stack->getLuaState(), const_cast<PhysicsContactPreSolve*>(&solve), "cc.PhysicsContactPreSolve"); bool ret = stack->executeFunctionByHandler(handler, 2);
bool ret = stack->executeFunctionByHandler(handler, 3);
stack->clean(); stack->clean();
return ret; return ret;
@ -1206,12 +1204,11 @@ static int tolua_cocos2dx_EventListenerPhysicsContact_registerScriptHandler(lua_
{ {
ScriptHandlerMgr::getInstance()->addObjectHandler((void*)self, handler, type); ScriptHandlerMgr::getInstance()->addObjectHandler((void*)self, handler, type);
self->onContactPostSolve = [handler](EventCustom* event, const PhysicsContact& contact, const PhysicsContactPostSolve& solve){ self->onContactPostSolve = [handler](PhysicsContact& contact, const PhysicsContactPostSolve& solve){
LuaStack* stack = LuaEngine::getInstance()->getLuaStack(); LuaStack* stack = LuaEngine::getInstance()->getLuaStack();
stack->pushObject(event, "cc.EventCustom"); stack->pushObject(&contact, "cc.PhysicsContact");
stack->pushObject(const_cast<PhysicsContact*>(&contact), "cc.PhysicsContact");
tolua_pushusertype(stack->getLuaState(), const_cast<PhysicsContactPostSolve*>(&solve), "cc.PhysicsContactPostSolve"); tolua_pushusertype(stack->getLuaState(), const_cast<PhysicsContactPostSolve*>(&solve), "cc.PhysicsContactPostSolve");
stack->executeFunctionByHandler(handler, 3); stack->executeFunctionByHandler(handler, 2);
stack->clean(); stack->clean();
}; };
} }
@ -1220,11 +1217,10 @@ static int tolua_cocos2dx_EventListenerPhysicsContact_registerScriptHandler(lua_
{ {
ScriptHandlerMgr::getInstance()->addObjectHandler((void*)self, handler, type); ScriptHandlerMgr::getInstance()->addObjectHandler((void*)self, handler, type);
self->onContactSeperate = [handler](EventCustom* event, const PhysicsContact& contact){ self->onContactSeperate = [handler](PhysicsContact& contact){
LuaStack* stack = LuaEngine::getInstance()->getLuaStack(); LuaStack* stack = LuaEngine::getInstance()->getLuaStack();
stack->pushObject(event, "cc.EventCustom"); stack->pushObject(&contact, "cc.PhysicsContact");
stack->pushObject(const_cast<PhysicsContact*>(&contact), "cc.PhysicsContact"); stack->executeFunctionByHandler(handler, 1);
stack->executeFunctionByHandler(handler, 2);
stack->clean(); stack->clean();
}; };
} }

View File

@ -1101,11 +1101,11 @@ void PhysicsDemoOneWayPlatform::onEnter()
this->addChild(ball); this->addChild(ball);
auto contactListener = EventListenerPhysicsContactWithBodies::create(platform->getPhysicsBody(), ball->getPhysicsBody()); auto contactListener = EventListenerPhysicsContactWithBodies::create(platform->getPhysicsBody(), ball->getPhysicsBody());
contactListener->onContactBegin = CC_CALLBACK_2(PhysicsDemoOneWayPlatform::onContactBegin, this); contactListener->onContactBegin = CC_CALLBACK_1(PhysicsDemoOneWayPlatform::onContactBegin, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);
} }
bool PhysicsDemoOneWayPlatform::onContactBegin(EventCustom* event, const PhysicsContact& contact) bool PhysicsDemoOneWayPlatform::onContactBegin(PhysicsContact& contact)
{ {
return contact.getContactData()->normal.y < 0; return contact.getContactData()->normal.y < 0;
} }

View File

@ -163,7 +163,7 @@ public:
void onEnter() override; void onEnter() override;
virtual std::string title() const override; virtual std::string title() const override;
bool onContactBegin(EventCustom* event, const PhysicsContact& contact); bool onContactBegin(PhysicsContact& contact);
}; };
class PhysicsDemoSlice : public PhysicsDemo class PhysicsDemoSlice : public PhysicsDemo

View File

@ -702,7 +702,7 @@ local function PhysicsDemoOneWayPlatform()
ball:getPhysicsBody():setMass(1.0); ball:getPhysicsBody():setMass(1.0);
layer:addChild(ball); layer:addChild(ball);
local function onContactBegin(event, contact) local function onContactBegin(contact)
return contact:getContactData().normal.y < 0; return contact:getContactData().normal.y < 0;
end end
local contactListener = cc.EventListenerPhysicsContactWithBodies:create(platform:getPhysicsBody(), ball:getPhysicsBody()); local contactListener = cc.EventListenerPhysicsContactWithBodies:create(platform:getPhysicsBody(), ball:getPhysicsBody());