2019-11-23 20:27:39 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
|
|
|
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
http://www.cocos2d-x.org
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#ifndef __CCPHYSICS_CONTACT_H__
|
|
|
|
#define __CCPHYSICS_CONTACT_H__
|
|
|
|
|
|
|
|
#include "base/ccConfig.h"
|
|
|
|
#if CC_USE_PHYSICS
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
# include "base/CCRef.h"
|
|
|
|
# include "math/CCMath.h"
|
|
|
|
# include "base/CCEventListenerCustom.h"
|
|
|
|
# include "base/CCEvent.h"
|
|
|
|
# include "base/CCEventCustom.h"
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
NS_CC_BEGIN
|
|
|
|
|
|
|
|
class PhysicsShape;
|
|
|
|
class PhysicsBody;
|
|
|
|
class PhysicsWorld;
|
|
|
|
|
|
|
|
typedef struct CC_DLL PhysicsContactData
|
|
|
|
{
|
|
|
|
static const int POINT_MAX = 4;
|
|
|
|
Vec2 points[POINT_MAX];
|
2021-12-25 10:04:45 +08:00
|
|
|
int count;
|
2019-11-23 20:27:39 +08:00
|
|
|
Vec2 normal;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
|
|
|
PhysicsContactData() : count(0) {}
|
|
|
|
} PhysicsContactData;
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @addtogroup physics
|
|
|
|
* @{
|
|
|
|
* @addtogroup physics_2d
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2021-12-25 10:04:45 +08:00
|
|
|
* @brief Contact information.
|
|
|
|
|
|
|
|
* It will created automatically when two shape contact with each other. And it will destroyed automatically when two
|
|
|
|
shape separated.
|
2019-11-23 20:27:39 +08:00
|
|
|
*/
|
|
|
|
class CC_DLL PhysicsContact : public EventCustom
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum class EventCode
|
|
|
|
{
|
|
|
|
NONE,
|
|
|
|
BEGIN,
|
|
|
|
PRESOLVE,
|
|
|
|
POSTSOLVE,
|
|
|
|
SEPARATE
|
|
|
|
};
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
/** Get contact shape A. */
|
|
|
|
PhysicsShape* getShapeA() const { return _shapeA; }
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
/** Get contact shape B. */
|
|
|
|
PhysicsShape* getShapeB() const { return _shapeB; }
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
/** Get contact data. */
|
|
|
|
const PhysicsContactData* getContactData() const { return _contactData; }
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
/** Get previous contact data */
|
|
|
|
const PhysicsContactData* getPreContactData() const { return _preContactData; }
|
2021-12-25 10:04:45 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get data.
|
2019-11-23 20:27:39 +08:00
|
|
|
* @lua NA
|
|
|
|
*/
|
|
|
|
void* getData() const { return _data; }
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
/**
|
2021-12-25 10:04:45 +08:00
|
|
|
* @brief Set data to contact.
|
|
|
|
|
|
|
|
* You must manage the memory yourself, Generally you can set data at contact begin, and destroy it at contact
|
|
|
|
separate.
|
2019-11-23 20:27:39 +08:00
|
|
|
*
|
|
|
|
* @lua NA
|
|
|
|
*/
|
|
|
|
void setData(void* data) { _data = data; }
|
|
|
|
|
|
|
|
/** Get the event code */
|
|
|
|
EventCode getEventCode() const { return _eventCode; };
|
|
|
|
|
|
|
|
private:
|
|
|
|
static PhysicsContact* construct(PhysicsShape* a, PhysicsShape* b);
|
|
|
|
bool init(PhysicsShape* a, PhysicsShape* b);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
void setEventCode(EventCode eventCode) { _eventCode = eventCode; };
|
|
|
|
bool isNotificationEnabled() const { return _notificationEnable; }
|
|
|
|
void setNotificationEnable(bool enable) { _notificationEnable = enable; }
|
|
|
|
PhysicsWorld* getWorld() const { return _world; }
|
|
|
|
void setWorld(PhysicsWorld* world) { _world = world; }
|
|
|
|
void setResult(bool result) { _result = result; }
|
2021-12-25 10:04:45 +08:00
|
|
|
bool resetResult()
|
|
|
|
{
|
|
|
|
bool ret = _result;
|
|
|
|
_result = true;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
void generateContactData();
|
|
|
|
|
|
|
|
private:
|
|
|
|
PhysicsContact();
|
|
|
|
~PhysicsContact();
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
private:
|
|
|
|
PhysicsWorld* _world;
|
|
|
|
PhysicsShape* _shapeA;
|
|
|
|
PhysicsShape* _shapeB;
|
|
|
|
EventCode _eventCode;
|
|
|
|
bool _notificationEnable;
|
|
|
|
bool _result;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
void* _data;
|
|
|
|
void* _contactInfo;
|
|
|
|
PhysicsContactData* _contactData;
|
|
|
|
PhysicsContactData* _preContactData;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
friend class EventListenerPhysicsContact;
|
|
|
|
friend class PhysicsWorldCallback;
|
|
|
|
friend class PhysicsWorld;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Presolve value generated when onContactPreSolve called.
|
|
|
|
*/
|
|
|
|
class CC_DLL PhysicsContactPreSolve
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/** Get restitution between two bodies.*/
|
|
|
|
float getRestitution() const;
|
|
|
|
/** Get friction between two bodies.*/
|
|
|
|
float getFriction() const;
|
|
|
|
/** Get surface velocity between two bodies.*/
|
|
|
|
Vec2 getSurfaceVelocity() const;
|
|
|
|
/** Set the restitution.*/
|
|
|
|
void setRestitution(float restitution);
|
|
|
|
/** Set the friction.*/
|
|
|
|
void setFriction(float friction);
|
|
|
|
/** Set the surface velocity.*/
|
|
|
|
void setSurfaceVelocity(const Vec2& velocity);
|
|
|
|
/** Ignore the rest of the contact presolve and postsolve callbacks. */
|
|
|
|
void ignore();
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
private:
|
|
|
|
PhysicsContactPreSolve(void* contactInfo);
|
|
|
|
~PhysicsContactPreSolve();
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
private:
|
|
|
|
void* _contactInfo;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
friend class EventListenerPhysicsContact;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Postsolve value generated when onContactPostSolve called.
|
|
|
|
*/
|
|
|
|
class CC_DLL PhysicsContactPostSolve
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/** Get restitution between two bodies.*/
|
|
|
|
float getRestitution() const;
|
|
|
|
/** Get friction between two bodies.*/
|
|
|
|
float getFriction() const;
|
|
|
|
/** Get surface velocity between two bodies.*/
|
|
|
|
Vec2 getSurfaceVelocity() const;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
private:
|
|
|
|
PhysicsContactPostSolve(void* contactInfo);
|
|
|
|
~PhysicsContactPostSolve();
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
private:
|
|
|
|
void* _contactInfo;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
friend class EventListenerPhysicsContact;
|
|
|
|
};
|
|
|
|
|
|
|
|
/** Contact listener. It will receive all the contact callbacks. */
|
|
|
|
class CC_DLL EventListenerPhysicsContact : public EventListenerCustom
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/** Create the listener. */
|
|
|
|
static EventListenerPhysicsContact* create();
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
/** Check the listener is available.
|
|
|
|
|
|
|
|
* @return True if there's one available callback function at least, false if there's no one.
|
|
|
|
*/
|
|
|
|
virtual bool checkAvailable() override;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
/** Clone an object from this listener.*/
|
|
|
|
virtual EventListenerPhysicsContact* clone() override;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
protected:
|
|
|
|
/**
|
|
|
|
* It will be call when two body have contact.
|
|
|
|
* if return false, it will not invoke callbacks.
|
|
|
|
*/
|
|
|
|
virtual bool hitTest(PhysicsShape* shapeA, PhysicsShape* shapeB);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* @brief It will called at two shapes start to contact, and only call it once.
|
|
|
|
*/
|
|
|
|
std::function<bool(PhysicsContact& contact)> onContactBegin;
|
|
|
|
/**
|
2021-12-25 10:04:45 +08:00
|
|
|
* @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, restitution,
|
|
|
|
* or surface velocity values.
|
2019-11-23 20:27:39 +08:00
|
|
|
*/
|
|
|
|
std::function<bool(PhysicsContact& contact, PhysicsContactPreSolve& solve)> onContactPreSolve;
|
|
|
|
/**
|
2021-12-25 10:04:45 +08:00
|
|
|
* @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
|
2019-11-23 20:27:39 +08:00
|
|
|
*/
|
|
|
|
std::function<void(PhysicsContact& contact, const PhysicsContactPostSolve& solve)> onContactPostSolve;
|
|
|
|
/**
|
|
|
|
* @brief It will called at two shapes separated, and only call it once.
|
|
|
|
* onContactBegin and onContactSeparate will called in pairs.
|
|
|
|
*/
|
|
|
|
std::function<void(PhysicsContact& contact)> onContactSeparate;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
protected:
|
|
|
|
bool init();
|
|
|
|
void onEvent(EventCustom* event);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
protected:
|
|
|
|
EventListenerPhysicsContact();
|
|
|
|
virtual ~EventListenerPhysicsContact();
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
friend class PhysicsWorld;
|
|
|
|
};
|
|
|
|
|
|
|
|
/** This event listener only be called when bodyA and bodyB have contacts. */
|
|
|
|
class CC_DLL EventListenerPhysicsContactWithBodies : public EventListenerPhysicsContact
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/** Create the listener. */
|
|
|
|
static EventListenerPhysicsContactWithBodies* create(PhysicsBody* bodyA, PhysicsBody* bodyB);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
virtual bool hitTest(PhysicsShape* shapeA, PhysicsShape* shapeB) override;
|
|
|
|
|
|
|
|
virtual EventListenerPhysicsContactWithBodies* clone() override;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
protected:
|
|
|
|
PhysicsBody* _a;
|
|
|
|
PhysicsBody* _b;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
protected:
|
|
|
|
EventListenerPhysicsContactWithBodies();
|
|
|
|
virtual ~EventListenerPhysicsContactWithBodies();
|
|
|
|
};
|
|
|
|
|
|
|
|
/** This event listener only be called when shapeA and shapeB have contacts. */
|
|
|
|
class CC_DLL EventListenerPhysicsContactWithShapes : public EventListenerPhysicsContact
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/** Create the listener. */
|
|
|
|
static EventListenerPhysicsContactWithShapes* create(PhysicsShape* shapeA, PhysicsShape* shapeB);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
virtual bool hitTest(PhysicsShape* shapeA, PhysicsShape* shapeB) override;
|
|
|
|
virtual EventListenerPhysicsContactWithShapes* clone() override;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
protected:
|
|
|
|
PhysicsShape* _a;
|
|
|
|
PhysicsShape* _b;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
protected:
|
|
|
|
EventListenerPhysicsContactWithShapes();
|
|
|
|
virtual ~EventListenerPhysicsContactWithShapes();
|
|
|
|
};
|
|
|
|
|
|
|
|
/** This event listener only be called when shapeA or shapeB is in the group your specified */
|
|
|
|
class CC_DLL EventListenerPhysicsContactWithGroup : public EventListenerPhysicsContact
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/** Create the listener. */
|
|
|
|
static EventListenerPhysicsContactWithGroup* create(int group);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
virtual bool hitTest(PhysicsShape* shapeA, PhysicsShape* shapeB) override;
|
|
|
|
virtual EventListenerPhysicsContactWithGroup* clone() override;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
protected:
|
|
|
|
int _group;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
protected:
|
|
|
|
EventListenerPhysicsContactWithGroup();
|
|
|
|
virtual ~EventListenerPhysicsContactWithGroup();
|
|
|
|
};
|
|
|
|
|
|
|
|
/** @} */
|
|
|
|
/** @} */
|
|
|
|
|
|
|
|
NS_CC_END
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
#endif // CC_USE_PHYSICS
|
|
|
|
#endif //__CCPHYSICS_CONTACT_H__
|