mirror of https://github.com/axmolengine/axmol.git
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:
commit
e90e0b0c23
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
|
|
Loading…
Reference in New Issue