зеркало из https://github.com/microsoft/cocos2d-x.git
issue #2771: enhance Listener use EventListener mechanism
This commit is contained in:
Родитель
dec749a692
Коммит
b2951b70ff
|
@ -102,8 +102,7 @@ bool Scene::initWithPhysics()
|
|||
Director * pDirector;
|
||||
CC_BREAK_IF( ! (pDirector = Director::getInstance()) );
|
||||
this->setContentSize(pDirector->getWinSize());
|
||||
CC_BREAK_IF(! (_physicsWorld = PhysicsWorld::create()));
|
||||
_physicsWorld->setScene(this);
|
||||
CC_BREAK_IF(! (_physicsWorld = PhysicsWorld::create(*this)));
|
||||
|
||||
this->scheduleUpdate();
|
||||
// success
|
||||
|
|
|
@ -207,6 +207,7 @@ typedef int (Object::*SEL_Compare)(Object*);
|
|||
#define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__)
|
||||
#define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)
|
||||
#define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)
|
||||
#define CC_CALLBACK_3(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3 ##__VA_ARGS__)
|
||||
|
||||
// end of base_nodes group
|
||||
/// @}
|
||||
|
|
|
@ -44,7 +44,7 @@ class PhysicsJoint;
|
|||
class PhysicsBodyInfo;
|
||||
|
||||
|
||||
const PhysicsMaterial PHYSICSBODY_MATERIAL_DEFAULT(0.01f, 0.5f, 0.5f);
|
||||
const PhysicsMaterial PHYSICSBODY_MATERIAL_DEFAULT(0.1f, 0.5f, 0.5f);
|
||||
|
||||
/**
|
||||
* A body affect by physics.
|
||||
|
|
|
@ -30,22 +30,30 @@
|
|||
#include "Box2D.h"
|
||||
#endif
|
||||
|
||||
#include "CCPhysicsBody.h"
|
||||
|
||||
#include "chipmunk/CCPhysicsContactInfo_chipmunk.h"
|
||||
#include "box2d/CCPhysicsContactInfo_box2d.h"
|
||||
#include "chipmunk/CCPhysicsHelper_chipmunk.h"
|
||||
#include "box2d/CCPhysicsHelper_box2d.h"
|
||||
|
||||
#include "CCEventCustom.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
PhysicsContact::PhysicsContact()
|
||||
: _shapeA(nullptr)
|
||||
: Event(Event::Type::CUSTOM)
|
||||
, _world(nullptr)
|
||||
, _shapeA(nullptr)
|
||||
, _shapeB(nullptr)
|
||||
, _eventCode(EventCode::NONE)
|
||||
, _info(nullptr)
|
||||
, _notify(true)
|
||||
, _begin(false)
|
||||
, _data(nullptr)
|
||||
, _contactInfo(nullptr)
|
||||
, _contactData(nullptr)
|
||||
, _result(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -172,25 +180,106 @@ Point PhysicsContactPostSolve::getSurfaceVelocity()
|
|||
return PhysicsHelper::cpv2point(((cpArbiter*)_contactInfo)->surface_vr);
|
||||
}
|
||||
|
||||
PhysicsContactListener::PhysicsContactListener()
|
||||
EventListenerPhysicsContact::EventListenerPhysicsContact()
|
||||
: onContactBegin(nullptr)
|
||||
, onContactPreSolve(nullptr)
|
||||
, onContactPostSolve(nullptr)
|
||||
, onContactEnd(nullptr)
|
||||
, onContactSeperate(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool EventListenerPhysicsContact::init()
|
||||
{
|
||||
auto func = [this](EventCustom* event) -> void
|
||||
{
|
||||
return onEvent(event);
|
||||
};
|
||||
|
||||
return EventListenerCustom::init(std::hash<std::string>()(PHYSICSCONTACT_EVENT_NAME), func);
|
||||
}
|
||||
|
||||
void EventListenerPhysicsContact::onEvent(EventCustom* event)
|
||||
{
|
||||
PhysicsContact& contact = *(PhysicsContact*)(event->getUserData());
|
||||
|
||||
switch (contact.getEventCode())
|
||||
{
|
||||
case PhysicsContact::EventCode::BEGIN:
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if (onContactBegin != nullptr
|
||||
&& contact.getNotify()
|
||||
&& test(contact.getShapeA(), contact.getShapeB()))
|
||||
{
|
||||
contact._begin = true;
|
||||
contact.generateContactData();
|
||||
|
||||
// the mask has high priority than _listener->onContactBegin.
|
||||
// so if the mask test is false, the two bodies won't have collision.
|
||||
if (ret)
|
||||
{
|
||||
ret = onContactBegin(event, contact);
|
||||
}else
|
||||
{
|
||||
onContactBegin(event, contact);
|
||||
}
|
||||
}
|
||||
|
||||
contact.setResult(ret);
|
||||
break;
|
||||
}
|
||||
case PhysicsContact::EventCode::PRESOLVE:
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if (onContactPreSolve != nullptr
|
||||
&& test(contact.getShapeA(), contact.getShapeB()))
|
||||
{
|
||||
PhysicsContactPreSolve solve(contact._begin ? nullptr : contact._contactData, contact._contactInfo);
|
||||
contact._begin = false;
|
||||
contact.generateContactData();
|
||||
|
||||
ret = onContactPreSolve(event, contact, solve);
|
||||
}
|
||||
|
||||
contact.setResult(ret);
|
||||
break;
|
||||
}
|
||||
case PhysicsContact::EventCode::POSTSOLVE:
|
||||
{
|
||||
if (onContactPreSolve != nullptr
|
||||
&& test(contact.getShapeA(), contact.getShapeB()))
|
||||
{
|
||||
PhysicsContactPostSolve solve(contact._contactInfo);
|
||||
onContactPostSolve(event, contact, solve);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PhysicsContact::EventCode::SEPERATE:
|
||||
{
|
||||
if (onContactSeperate != nullptr
|
||||
&& test(contact.getShapeA(), contact.getShapeB()))
|
||||
{
|
||||
onContactSeperate(event, contact);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EventListenerPhysicsContact::~EventListenerPhysicsContact()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PhysicsContactListener::~PhysicsContactListener()
|
||||
EventListenerPhysicsContact* EventListenerPhysicsContact::create()
|
||||
{
|
||||
EventListenerPhysicsContact* obj = new EventListenerPhysicsContact();
|
||||
|
||||
}
|
||||
|
||||
PhysicsContactListener* PhysicsContactListener::create()
|
||||
{
|
||||
PhysicsContactListener* obj = new PhysicsContactListener();
|
||||
|
||||
if (obj != nullptr)
|
||||
if (obj != nullptr && obj->init())
|
||||
{
|
||||
obj->autorelease();
|
||||
return obj;
|
||||
|
@ -200,17 +289,17 @@ PhysicsContactListener* PhysicsContactListener::create()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool PhysicsContactListener::test(PhysicsShape* shapeA, PhysicsShape* shapeB)
|
||||
bool EventListenerPhysicsContact::test(PhysicsShape* shapeA, PhysicsShape* shapeB)
|
||||
{
|
||||
CC_UNUSED_PARAM(shapeA);
|
||||
CC_UNUSED_PARAM(shapeB);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PhysicsContactListener::checkAvailable()
|
||||
bool EventListenerPhysicsContact::checkAvailable()
|
||||
{
|
||||
if (onContactBegin == nullptr && onContactPreSolve == nullptr
|
||||
&& onContactPostSolve == nullptr && onContactEnd == nullptr)
|
||||
&& onContactPostSolve == nullptr && onContactSeperate == nullptr)
|
||||
{
|
||||
CCASSERT(false, "Invalid PhysicsContactListener.");
|
||||
return false;
|
||||
|
@ -219,16 +308,16 @@ bool PhysicsContactListener::checkAvailable()
|
|||
return true;
|
||||
}
|
||||
|
||||
EventListener* PhysicsContactListener::clone()
|
||||
EventListenerPhysicsContact* EventListenerPhysicsContact::clone()
|
||||
{
|
||||
PhysicsContactListener* obj = PhysicsContactListener::create();
|
||||
EventListenerPhysicsContact* obj = EventListenerPhysicsContact::create();
|
||||
|
||||
if (obj != nullptr)
|
||||
{
|
||||
obj->onContactBegin = onContactBegin;
|
||||
obj->onContactPreSolve = onContactPreSolve;
|
||||
obj->onContactPostSolve = onContactPostSolve;
|
||||
obj->onContactEnd = onContactEnd;
|
||||
obj->onContactSeperate = onContactSeperate;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
@ -237,14 +326,79 @@ EventListener* PhysicsContactListener::clone()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PhysicsContactWithBodysListener* PhysicsContactWithBodysListener::create(PhysicsShape* shapeA, PhysicsShape* shapeB)
|
||||
EventListenerPhysicsContactWithBodies* EventListenerPhysicsContactWithBodies::create(PhysicsBody* bodyA, PhysicsBody* bodyB)
|
||||
{
|
||||
PhysicsContactWithBodysListener* obj = new PhysicsContactWithBodysListener();
|
||||
EventListenerPhysicsContactWithBodies* obj = new EventListenerPhysicsContactWithBodies();
|
||||
|
||||
if (obj != nullptr && obj->init())
|
||||
{
|
||||
obj->_a = bodyA;
|
||||
obj->_b = bodyB;
|
||||
obj->autorelease();
|
||||
return obj;
|
||||
}
|
||||
|
||||
CC_SAFE_DELETE(obj);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EventListenerPhysicsContactWithBodies::EventListenerPhysicsContactWithBodies()
|
||||
: _a(nullptr)
|
||||
, _b(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
EventListenerPhysicsContactWithBodies::~EventListenerPhysicsContactWithBodies()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool EventListenerPhysicsContactWithBodies::test(PhysicsShape* shapeA, PhysicsShape* shapeB)
|
||||
{
|
||||
if ((shapeA->getBody() == _a && shapeB->getBody() == _b)
|
||||
|| (shapeA->getBody() == _b && shapeB->getBody() == _a))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
EventListenerPhysicsContactWithBodies* EventListenerPhysicsContactWithBodies::clone()
|
||||
{
|
||||
EventListenerPhysicsContactWithBodies* obj = EventListenerPhysicsContactWithBodies::create(_a, _b);
|
||||
|
||||
if (obj != nullptr)
|
||||
{
|
||||
obj->onContactBegin = onContactBegin;
|
||||
obj->onContactPreSolve = onContactPreSolve;
|
||||
obj->onContactPostSolve = onContactPostSolve;
|
||||
obj->onContactSeperate = onContactSeperate;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
CC_SAFE_DELETE(obj);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EventListenerPhysicsContactWithShapes::EventListenerPhysicsContactWithShapes()
|
||||
: _a(nullptr)
|
||||
, _b(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
EventListenerPhysicsContactWithShapes::~EventListenerPhysicsContactWithShapes()
|
||||
{
|
||||
}
|
||||
|
||||
EventListenerPhysicsContactWithShapes* EventListenerPhysicsContactWithShapes::create(PhysicsShape* shapeA, PhysicsShape* shapeB)
|
||||
{
|
||||
EventListenerPhysicsContactWithShapes* obj = new EventListenerPhysicsContactWithShapes();
|
||||
|
||||
if (obj != nullptr && obj->init())
|
||||
{
|
||||
obj->_a = shapeA;
|
||||
obj->_b = shapeB;
|
||||
|
@ -256,17 +410,7 @@ PhysicsContactWithBodysListener* PhysicsContactWithBodysListener::create(Physics
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
PhysicsContactWithBodysListener::PhysicsContactWithBodysListener()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PhysicsContactWithBodysListener::~PhysicsContactWithBodysListener()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool PhysicsContactWithBodysListener::test(PhysicsShape* shapeA, PhysicsShape* shapeB)
|
||||
bool EventListenerPhysicsContactWithShapes::test(PhysicsShape* shapeA, PhysicsShape* shapeB)
|
||||
{
|
||||
if ((shapeA == _a && shapeB == _b)
|
||||
|| (shapeA == _b && shapeB == _a))
|
||||
|
@ -277,16 +421,68 @@ bool PhysicsContactWithBodysListener::test(PhysicsShape* shapeA, PhysicsShape* s
|
|||
return false;
|
||||
}
|
||||
|
||||
EventListener* PhysicsContactWithBodysListener::clone()
|
||||
EventListenerPhysicsContactWithShapes* EventListenerPhysicsContactWithShapes::clone()
|
||||
{
|
||||
PhysicsContactWithBodysListener* obj = PhysicsContactWithBodysListener::create(_a, _b);
|
||||
EventListenerPhysicsContactWithShapes* obj = EventListenerPhysicsContactWithShapes::create(_a, _b);
|
||||
|
||||
if (obj != nullptr)
|
||||
{
|
||||
obj->onContactBegin = onContactBegin;
|
||||
obj->onContactPreSolve = onContactPreSolve;
|
||||
obj->onContactPostSolve = onContactPostSolve;
|
||||
obj->onContactEnd = onContactEnd;
|
||||
obj->onContactSeperate = onContactSeperate;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
CC_SAFE_DELETE(obj);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EventListenerPhysicsContactWithGroup::EventListenerPhysicsContactWithGroup()
|
||||
: _group(CP_NO_GROUP)
|
||||
{
|
||||
}
|
||||
|
||||
EventListenerPhysicsContactWithGroup::~EventListenerPhysicsContactWithGroup()
|
||||
{
|
||||
}
|
||||
|
||||
EventListenerPhysicsContactWithGroup* EventListenerPhysicsContactWithGroup::create(int group)
|
||||
{
|
||||
EventListenerPhysicsContactWithGroup* obj = new EventListenerPhysicsContactWithGroup();
|
||||
|
||||
if (obj != nullptr && obj->init())
|
||||
{
|
||||
obj->_group = group;
|
||||
obj->autorelease();
|
||||
return obj;
|
||||
}
|
||||
|
||||
CC_SAFE_DELETE(obj);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool EventListenerPhysicsContactWithGroup::test(PhysicsShape* shapeA, PhysicsShape* shapeB)
|
||||
{
|
||||
if (shapeA->getGroup() == _group || shapeB->getGroup() == _group)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
EventListenerPhysicsContactWithGroup* EventListenerPhysicsContactWithGroup::clone()
|
||||
{
|
||||
EventListenerPhysicsContactWithGroup* obj = EventListenerPhysicsContactWithGroup::create(_group);
|
||||
|
||||
if (obj != nullptr)
|
||||
{
|
||||
obj->onContactBegin = onContactBegin;
|
||||
obj->onContactPreSolve = onContactPreSolve;
|
||||
obj->onContactPostSolve = onContactPostSolve;
|
||||
obj->onContactSeperate = onContactSeperate;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
|
|
@ -30,11 +30,13 @@
|
|||
|
||||
#include "CCObject.h"
|
||||
#include "CCGeometry.h"
|
||||
#include "CCEventListener.h"
|
||||
#include "CCEventListenerCustom.h"
|
||||
#include "CCEvent.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
class PhysicsShape;
|
||||
class PhysicsBody;
|
||||
class PhysicsWorld;
|
||||
|
||||
class PhysicsContactInfo;
|
||||
|
@ -54,9 +56,19 @@ 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.
|
||||
*/
|
||||
class PhysicsContact
|
||||
class PhysicsContact : Event
|
||||
{
|
||||
public:
|
||||
|
||||
enum class EventCode
|
||||
{
|
||||
NONE,
|
||||
BEGIN,
|
||||
PRESOLVE,
|
||||
POSTSOLVE,
|
||||
SEPERATE
|
||||
};
|
||||
|
||||
/*
|
||||
* @brief get contact shape A.
|
||||
*/
|
||||
|
@ -75,12 +87,19 @@ public:
|
|||
*/
|
||||
inline void setData(void* data) { _data = data; }
|
||||
|
||||
EventCode getEventCode() { return _eventCode; };
|
||||
|
||||
private:
|
||||
static PhysicsContact* create(PhysicsShape* a, PhysicsShape* b);
|
||||
bool init(PhysicsShape* a, PhysicsShape* b);
|
||||
|
||||
void setEventCode(EventCode eventCode) { _eventCode = eventCode; };
|
||||
inline bool getNotify() { return _notify; }
|
||||
inline void setNotify(bool notify) { _notify = notify; }
|
||||
inline PhysicsWorld* getWorld() { return _world; }
|
||||
inline void setWorld(PhysicsWorld* world) { _world = world; }
|
||||
inline void setResult(bool result) { _result = result; }
|
||||
inline bool resetResult() { bool ret = _result; _result = true; return ret; }
|
||||
|
||||
void generateContactData();
|
||||
|
||||
|
@ -89,18 +108,22 @@ private:
|
|||
~PhysicsContact();
|
||||
|
||||
private:
|
||||
PhysicsWorld* _world;
|
||||
PhysicsShape* _shapeA;
|
||||
PhysicsShape* _shapeB;
|
||||
EventCode _eventCode;
|
||||
PhysicsContactInfo* _info;
|
||||
bool _notify;
|
||||
bool _begin;
|
||||
bool _result;
|
||||
|
||||
void* _data;
|
||||
void* _contactInfo;
|
||||
PhysicsContactData* _contactData;
|
||||
|
||||
friend class PhysicsWorld;
|
||||
friend class EventListenerPhysicsContact;
|
||||
friend class PhysicsWorldCallback;
|
||||
friend class PhysicsWorld;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -128,7 +151,7 @@ private:
|
|||
PhysicsContactData* _preContactData;
|
||||
void* _contactInfo;
|
||||
|
||||
friend class PhysicsWorld;
|
||||
friend class EventListenerPhysicsContact;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -149,60 +172,99 @@ private:
|
|||
private:
|
||||
void* _contactInfo;
|
||||
|
||||
friend class PhysicsWorld;
|
||||
friend class EventListenerPhysicsContact;
|
||||
};
|
||||
|
||||
static const char* PHYSICSCONTACT_EVENT_NAME = "PhysicsContactEvent";
|
||||
|
||||
/*
|
||||
* @brief contact listener.
|
||||
*/
|
||||
class PhysicsContactListener : public EventListener
|
||||
class EventListenerPhysicsContact : public EventListenerCustom
|
||||
{
|
||||
public:
|
||||
static PhysicsContactListener* create();
|
||||
static EventListenerPhysicsContact* create();
|
||||
|
||||
virtual bool test(PhysicsShape* shapeA, PhysicsShape* shapeB);
|
||||
virtual bool checkAvailable();
|
||||
virtual EventListener* clone();
|
||||
virtual bool checkAvailable() override;
|
||||
virtual EventListenerPhysicsContact* clone() override;
|
||||
|
||||
public:
|
||||
/*
|
||||
* @brief it will called at two shapes start to contact, and only call it once.
|
||||
*/
|
||||
std::function<bool(PhysicsWorld& world, const PhysicsContact& contact)> onContactBegin;
|
||||
std::function<bool(EventCustom* event, const 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.
|
||||
*/
|
||||
std::function<bool(PhysicsWorld& world, const PhysicsContact& contact, const PhysicsContactPreSolve& solve)> onContactPreSolve;
|
||||
std::function<bool(EventCustom* event, const PhysicsContact& contact, const 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
|
||||
*/
|
||||
std::function<void(PhysicsWorld& world, const PhysicsContact& contact, const PhysicsContactPostSolve& solve)> onContactPostSolve;
|
||||
std::function<void(EventCustom* event, const PhysicsContact& contact, const PhysicsContactPostSolve& solve)> onContactPostSolve;
|
||||
/*
|
||||
* @brief it will called at two shapes separated, and only call it once.
|
||||
* onContactBegin and onContactEnd will called in pairs.
|
||||
* onContactBegin and onContactSeperate will called in pairs.
|
||||
*/
|
||||
std::function<void(PhysicsWorld& world, const PhysicsContact& contact)> onContactEnd;
|
||||
std::function<void(EventCustom* event, const PhysicsContact& contact)> onContactSeperate;
|
||||
|
||||
protected:
|
||||
PhysicsContactListener();
|
||||
virtual ~PhysicsContactListener();
|
||||
bool init();
|
||||
void onEvent(EventCustom* event);
|
||||
|
||||
protected:
|
||||
EventListenerPhysicsContact();
|
||||
virtual ~EventListenerPhysicsContact();
|
||||
};
|
||||
|
||||
class PhysicsContactWithBodysListener : public PhysicsContactListener
|
||||
class EventListenerPhysicsContactWithBodies : public EventListenerPhysicsContact
|
||||
{
|
||||
public:
|
||||
static PhysicsContactWithBodysListener* create(PhysicsShape* shapeA, PhysicsShape* shapeB);
|
||||
static EventListenerPhysicsContactWithBodies* create(PhysicsBody* bodyA, PhysicsBody* bodyB);
|
||||
|
||||
virtual bool test(PhysicsShape* shapeA, PhysicsShape* shapeB);
|
||||
virtual EventListener* clone();
|
||||
virtual EventListenerPhysicsContactWithBodies* clone() override;
|
||||
|
||||
protected:
|
||||
PhysicsBody* _a;
|
||||
PhysicsBody* _b;
|
||||
|
||||
protected:
|
||||
EventListenerPhysicsContactWithBodies();
|
||||
virtual ~EventListenerPhysicsContactWithBodies();
|
||||
};
|
||||
|
||||
class EventListenerPhysicsContactWithShapes : public EventListenerPhysicsContact
|
||||
{
|
||||
public:
|
||||
static EventListenerPhysicsContactWithShapes* create(PhysicsShape* shapeA, PhysicsShape* shapeB);
|
||||
|
||||
virtual bool test(PhysicsShape* shapeA, PhysicsShape* shapeB);
|
||||
virtual EventListenerPhysicsContactWithShapes* clone() override;
|
||||
|
||||
protected:
|
||||
PhysicsShape* _a;
|
||||
PhysicsShape* _b;
|
||||
|
||||
protected:
|
||||
PhysicsContactWithBodysListener();
|
||||
virtual ~PhysicsContactWithBodysListener();
|
||||
EventListenerPhysicsContactWithShapes();
|
||||
virtual ~EventListenerPhysicsContactWithShapes();
|
||||
};
|
||||
|
||||
class EventListenerPhysicsContactWithGroup : public EventListenerPhysicsContact
|
||||
{
|
||||
public:
|
||||
static EventListenerPhysicsContactWithGroup* create(int group);
|
||||
|
||||
virtual bool test(PhysicsShape* shapeA, PhysicsShape* shapeB);
|
||||
virtual EventListenerPhysicsContactWithGroup* clone() override;
|
||||
|
||||
protected:
|
||||
int _group;
|
||||
|
||||
protected:
|
||||
EventListenerPhysicsContactWithGroup();
|
||||
virtual ~EventListenerPhysicsContactWithGroup();
|
||||
};
|
||||
|
||||
NS_CC_END
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
#include "CCArray.h"
|
||||
#include "CCScene.h"
|
||||
#include "CCDirector.h"
|
||||
#include "CCEventDispatcher.h"
|
||||
#include "CCEventCustom.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -175,7 +177,7 @@ void PhysicsWorldCallback::nearestPointQueryFunc(cpShape *shape, cpFloat distanc
|
|||
arr->addObject(it->second->shape);
|
||||
}
|
||||
|
||||
bool PhysicsWorld::init()
|
||||
bool PhysicsWorld::init(Scene& scene)
|
||||
{
|
||||
do
|
||||
{
|
||||
|
@ -184,6 +186,8 @@ bool PhysicsWorld::init()
|
|||
_bodies = Array::create();
|
||||
CC_BREAK_IF(_bodies == nullptr);
|
||||
_bodies->retain();
|
||||
|
||||
_scene = &scene;
|
||||
|
||||
cpSpaceSetGravity(_info->space, PhysicsHelper::point2cpv(_gravity));
|
||||
|
||||
|
@ -458,11 +462,6 @@ void PhysicsWorld::debugDraw()
|
|||
}
|
||||
}
|
||||
|
||||
void PhysicsWorld::setScene(Scene *scene)
|
||||
{
|
||||
_scene = scene;
|
||||
}
|
||||
|
||||
void PhysicsWorld::drawWithJoint(DrawNode* node, PhysicsJoint* joint)
|
||||
{
|
||||
for (auto it = joint->_info->joints.begin(); it != joint->_info->joints.end(); ++it)
|
||||
|
@ -571,6 +570,7 @@ void PhysicsWorld::drawWithShape(DrawNode* node, PhysicsShape* shape)
|
|||
int PhysicsWorld::collisionBeginCallback(PhysicsContact& contact)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
PhysicsShape* shapeA = contact.getShapeA();
|
||||
PhysicsShape* shapeB = contact.getShapeB();
|
||||
PhysicsBody* bodyA = shapeA->getBody();
|
||||
|
@ -597,7 +597,6 @@ int PhysicsWorld::collisionBeginCallback(PhysicsContact& contact)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// bitmask check
|
||||
if ((shapeA->getCategoryBitmask() & shapeB->getContactTestBitmask()) == 0
|
||||
|| (shapeB->getContactTestBitmask() & shapeA->getCategoryBitmask()) == 0)
|
||||
|
@ -617,69 +616,42 @@ int PhysicsWorld::collisionBeginCallback(PhysicsContact& contact)
|
|||
}
|
||||
}
|
||||
|
||||
if (contact.getNotify() && _listener && _listener->onContactBegin)
|
||||
{
|
||||
contact._begin = true;
|
||||
contact.generateContactData();
|
||||
|
||||
// the mask has high priority than _listener->onContactBegin.
|
||||
// so if the mask test is false, the two bodies won't have collision.
|
||||
if (ret)
|
||||
{
|
||||
ret = _listener->onContactBegin(*this, contact);
|
||||
}else
|
||||
{
|
||||
_listener->onContactBegin(*this, contact);
|
||||
}
|
||||
}
|
||||
contact.setEventCode(PhysicsContact::EventCode::BEGIN);
|
||||
contact.setWorld(this);
|
||||
EventCustom event(PHYSICSCONTACT_EVENT_NAME);
|
||||
event.setUserData(&contact);
|
||||
_scene->getEventDispatcher()->dispatchEvent(&event);
|
||||
|
||||
return ret;
|
||||
return ret ? contact.resetResult() : false;
|
||||
}
|
||||
|
||||
int PhysicsWorld::collisionPreSolveCallback(PhysicsContact& contact)
|
||||
{
|
||||
if (!contact.getNotify())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
contact.setEventCode(PhysicsContact::EventCode::PRESOLVE);
|
||||
contact.setWorld(this);
|
||||
EventCustom event(PHYSICSCONTACT_EVENT_NAME);
|
||||
event.setUserData(&contact);
|
||||
_scene->getEventDispatcher()->dispatchEvent(&event);
|
||||
|
||||
if (_listener && _listener->onContactPreSolve)
|
||||
{
|
||||
PhysicsContactPreSolve solve(contact._begin ? nullptr : contact._contactData, contact._contactInfo);
|
||||
contact._begin = false;
|
||||
contact.generateContactData();
|
||||
|
||||
return _listener->onContactPreSolve(*this, contact, solve);
|
||||
}
|
||||
|
||||
return true;
|
||||
return contact.resetResult();
|
||||
}
|
||||
|
||||
void PhysicsWorld::collisionPostSolveCallback(PhysicsContact& contact)
|
||||
{
|
||||
if (!contact.getNotify())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_listener && _listener->onContactPreSolve)
|
||||
{
|
||||
PhysicsContactPostSolve solve(contact._contactInfo);
|
||||
_listener->onContactPostSolve(*this, contact, solve);
|
||||
}
|
||||
contact.setEventCode(PhysicsContact::EventCode::POSTSOLVE);
|
||||
contact.setWorld(this);
|
||||
EventCustom event(PHYSICSCONTACT_EVENT_NAME);
|
||||
event.setUserData(&contact);
|
||||
_scene->getEventDispatcher()->dispatchEvent(&event);
|
||||
}
|
||||
|
||||
void PhysicsWorld::collisionSeparateCallback(PhysicsContact& contact)
|
||||
{
|
||||
if (!contact.getNotify())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_listener && _listener->onContactEnd)
|
||||
{
|
||||
_listener->onContactEnd(*this, contact);
|
||||
}
|
||||
contact.setEventCode(PhysicsContact::EventCode::SEPERATE);
|
||||
contact.setWorld(this);
|
||||
EventCustom event(PHYSICSCONTACT_EVENT_NAME);
|
||||
event.setUserData(&contact);
|
||||
_scene->getEventDispatcher()->dispatchEvent(&event);
|
||||
}
|
||||
|
||||
void PhysicsWorld::setGravity(Point gravity)
|
||||
|
@ -786,10 +758,10 @@ PhysicsBody* PhysicsWorld::getBodyByTag(int tag)
|
|||
|
||||
#endif
|
||||
|
||||
PhysicsWorld* PhysicsWorld::create()
|
||||
PhysicsWorld* PhysicsWorld::create(Scene& scene)
|
||||
{
|
||||
PhysicsWorld * world = new PhysicsWorld();
|
||||
if(world && world->init())
|
||||
if(world && world->init(scene))
|
||||
{
|
||||
return world;
|
||||
}
|
||||
|
@ -802,7 +774,6 @@ PhysicsWorld::PhysicsWorld()
|
|||
: _gravity(Point(0.0f, -98.0f))
|
||||
, _speed(1.0f)
|
||||
, _info(nullptr)
|
||||
, _listener(nullptr)
|
||||
, _bodies(nullptr)
|
||||
, _scene(nullptr)
|
||||
, _debugDraw(false)
|
||||
|
|
|
@ -40,7 +40,6 @@ class PhysicsJoint;
|
|||
class PhysicsWorldInfo;
|
||||
class PhysicsShape;
|
||||
class PhysicsContact;
|
||||
class PhysicsContactListener;
|
||||
class Array;
|
||||
|
||||
class Sprite;
|
||||
|
@ -101,10 +100,11 @@ public:
|
|||
PhysicsBody* getBodyByTag(int tag);
|
||||
|
||||
/** Register a listener to receive contact callbacks*/
|
||||
inline void registerContactListener(PhysicsContactListener* delegate) { _listener = delegate; }
|
||||
//inline void registerContactListener(EventListenerPhysicsContact* delegate) { _listener = delegate; }
|
||||
/** Unregister a listener. */
|
||||
inline void unregisterContactListener() { _listener = nullptr; }
|
||||
//inline void unregisterContactListener() { _listener = nullptr; }
|
||||
|
||||
inline Scene& getScene() { return *_scene; }
|
||||
/** get the gravity value */
|
||||
inline Point getGravity() { return _gravity; }
|
||||
/** set the gravity value */
|
||||
|
@ -120,10 +120,8 @@ public:
|
|||
virtual void removeAllBodies();
|
||||
|
||||
protected:
|
||||
static PhysicsWorld* create();
|
||||
bool init();
|
||||
|
||||
void setScene(Scene* scene);
|
||||
static PhysicsWorld* create(Scene& scene);
|
||||
bool init(Scene& scene);
|
||||
|
||||
virtual PhysicsBody* addBody(PhysicsBody* body);
|
||||
virtual PhysicsShape* addShape(PhysicsShape* shape);
|
||||
|
@ -144,8 +142,7 @@ protected:
|
|||
Point _gravity;
|
||||
float _speed;
|
||||
PhysicsWorldInfo* _info;
|
||||
PhysicsContactListener* _listener;
|
||||
|
||||
//EventListenerPhysicsContact* _listener;
|
||||
|
||||
Array* _bodies;
|
||||
std::list<PhysicsJoint*> _joints;
|
||||
|
|
|
@ -898,7 +898,7 @@ void PhysicsDemoPump::onEnter()
|
|||
// balls
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
auto ball = makeBall(VisibleRect::leftTop() + Point(75 + CCRANDOM_0_1() * 90, 0), 22, PhysicsMaterial(0.5f, 0.0f, 0.1f));
|
||||
auto ball = makeBall(VisibleRect::leftTop() + Point(75 + CCRANDOM_0_1() * 90, 0), 22, PhysicsMaterial(0.05f, 0.0f, 0.1f));
|
||||
ball->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
|
||||
addChild(ball);
|
||||
}
|
||||
|
@ -908,8 +908,8 @@ void PhysicsDemoPump::onEnter()
|
|||
|
||||
Point vec[4] =
|
||||
{
|
||||
VisibleRect::leftTop() + Point(102, -146),
|
||||
VisibleRect::leftTop() + Point(148, -159),
|
||||
VisibleRect::leftTop() + Point(102, -148),
|
||||
VisibleRect::leftTop() + Point(148, -161),
|
||||
VisibleRect::leftBottom() + Point(148, 20),
|
||||
VisibleRect::leftBottom() + Point(102, 20)
|
||||
};
|
||||
|
@ -918,7 +918,7 @@ void PhysicsDemoPump::onEnter()
|
|||
|
||||
// small gear
|
||||
auto sgear = Node::create();
|
||||
auto sgearB = PhysicsBody::createCircle(50);
|
||||
auto sgearB = PhysicsBody::createCircle(44);
|
||||
sgear->setPhysicsBody(sgearB);
|
||||
sgear->setPosition(VisibleRect::leftBottom() + Point(125, 0));
|
||||
this->addChild(sgear);
|
||||
|
@ -946,7 +946,7 @@ void PhysicsDemoPump::onEnter()
|
|||
this->addChild(pump);
|
||||
pumpB->setCategoryBitmask(0x02);
|
||||
pumpB->setGravityEnable(false);
|
||||
_world->addJoint(PhysicsJointDistance::create(pumpB, sgearB, Point(0, 0), Point(0, -50)));
|
||||
_world->addJoint(PhysicsJointDistance::create(pumpB, sgearB, Point(0, 0), Point(0, -44)));
|
||||
|
||||
// plugger
|
||||
Point seg[] = {VisibleRect::leftTop() + Point(75, -120), VisibleRect::leftBottom() + Point(75, -100)};
|
||||
|
@ -964,7 +964,7 @@ void PhysicsDemoPump::onEnter()
|
|||
pluggerB->setCategoryBitmask(0x02);
|
||||
sgearB->setCollisionBitmask(0x04 | 0x01);
|
||||
_world->addJoint(PhysicsJointPin::create(body, pluggerB, VisibleRect::leftBottom() + Point(75, -90)));
|
||||
_world->addJoint(PhysicsJointDistance::create(pluggerB, sgearB, pluggerB->world2Local(VisibleRect::leftBottom() + Point(75, 0)), Point(50, 0)));
|
||||
_world->addJoint(PhysicsJointDistance::create(pluggerB, sgearB, pluggerB->world2Local(VisibleRect::leftBottom() + Point(75, 0)), Point(44, 0)));
|
||||
}
|
||||
|
||||
void PhysicsDemoPump::update(float delta)
|
||||
|
@ -1024,7 +1024,6 @@ std::string PhysicsDemoPump::title()
|
|||
return "Pump";
|
||||
}
|
||||
|
||||
|
||||
void PhysicsDemoOneWayPlatform::onEnter()
|
||||
{
|
||||
PhysicsDemo::onEnter();
|
||||
|
@ -1044,7 +1043,17 @@ void PhysicsDemoOneWayPlatform::onEnter()
|
|||
platform->setPosition(VisibleRect::center());
|
||||
this->addChild(platform);
|
||||
|
||||
this->addChild(makeBall(VisibleRect::center() + Point(0, 50), 5));
|
||||
auto ball = makeBall(VisibleRect::center() + Point(0, 50), 5);
|
||||
this->addChild(ball);
|
||||
|
||||
auto contactListener = EventListenerPhysicsContactWithBodies::create(platform->getPhysicsBody(), ball->getPhysicsBody());
|
||||
contactListener->onContactPreSolve = CC_CALLBACK_3(PhysicsDemoOneWayPlatform::onPreSolve, this);
|
||||
_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);
|
||||
}
|
||||
|
||||
bool PhysicsDemoOneWayPlatform::onPreSolve(EventCustom* event, const PhysicsContact& contact, const PhysicsContactPreSolve& solve)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string PhysicsDemoOneWayPlatform::title()
|
||||
|
|
|
@ -139,6 +139,8 @@ class PhysicsDemoOneWayPlatform : public PhysicsDemo
|
|||
public:
|
||||
void onEnter() override;
|
||||
std::string title() override;
|
||||
|
||||
bool onPreSolve(EventCustom* event, const PhysicsContact& contact, const PhysicsContactPreSolve& solve);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче