diff --git a/README.md b/README.md index 41e0503cc6..67565b6b20 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ ### [Roadmap](issues/1) ### Quick Start -Open [Wiki](https://github.com/c4games/engine-x-wiki) for additional information too. +Open [Wiki](https://github.com/c4games/engine-x/wiki) for additional information too. #### Common Requirement [Python](https://www.python.org/downloads/) * Python-2.7.17+, Python-3.7+ diff --git a/cocos/base/ccConfig.h b/cocos/base/ccConfig.h index 4c404ed51b..9e00848da5 100644 --- a/cocos/base/ccConfig.h +++ b/cocos/base/ccConfig.h @@ -258,7 +258,7 @@ THE SOFTWARE. #if (CC_USE_PHYSICS) /** Use chipmunk physics 2d engine. */ #ifndef CC_ENABLE_CHIPMUNK_INTEGRATION -#define CC_ENABLE_CHIPMUNK_INTEGRATION 0 +#define CC_ENABLE_CHIPMUNK_INTEGRATION 1 #endif /** or use box2d physics 2d engine. */ diff --git a/extensions/cocos-ext.h b/extensions/cocos-ext.h index 55cd6f53a2..1efc269a5d 100644 --- a/extensions/cocos-ext.h +++ b/extensions/cocos-ext.h @@ -30,6 +30,9 @@ // Physics integration #include "physics-nodes/CCPhysicsDebugNode.h" #include "physics-nodes/CCPhysicsSprite.h" +#include "physics-nodes/CCPhysicsSpriteBox2D.h" +#include "physics-nodes/CCPhysicsSpriteChipmunk2D.h" + #include "assets-manager/AssetsManager.h" #include "assets-manager/AssetsManagerEx.h" diff --git a/extensions/physics-nodes/CCPhysicsSprite.cpp b/extensions/physics-nodes/CCPhysicsSprite.cpp index 114e069b81..468afee7a2 100644 --- a/extensions/physics-nodes/CCPhysicsSprite.cpp +++ b/extensions/physics-nodes/CCPhysicsSprite.cpp @@ -27,9 +27,6 @@ #if (CC_ENABLE_CHIPMUNK_INTEGRATION || CC_ENABLE_BOX2D_INTEGRATION) -#if (CC_ENABLE_CHIPMUNK_INTEGRATION && CC_ENABLE_BOX2D_INTEGRATION) -#error "Either Chipmunk or Box2d should be enabled, but not both at the same time" -#endif #if CC_ENABLE_CHIPMUNK_INTEGRATION #include "chipmunk/chipmunk.h" diff --git a/extensions/physics-nodes/CCPhysicsSpriteBox2D.cpp b/extensions/physics-nodes/CCPhysicsSpriteBox2D.cpp new file mode 100644 index 0000000000..095affe9d0 --- /dev/null +++ b/extensions/physics-nodes/CCPhysicsSpriteBox2D.cpp @@ -0,0 +1,375 @@ +/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software + * Copyright (c) 2012 cocos2d-x.org + * Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + * + * 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: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 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. + */ + +#include "CCPhysicsSpriteBox2D.h" +#include "base/CCDirector.h" +#include "base/CCEventDispatcher.h" + +#if (CC_ENABLE_CHIPMUNK_INTEGRATION || CC_ENABLE_BOX2D_INTEGRATION) + +#if (CC_ENABLE_CHIPMUNK_INTEGRATION && CC_ENABLE_BOX2D_INTEGRATION) +//#error "Either Chipmunk or Box2d should be enabled, but not both at the same time" +#endif + + +#include "box2d/box2d.h" + + +NS_CC_EXT_BEGIN + +PhysicsSpriteBox2D::PhysicsSpriteBox2D() +: _ignoreBodyRotation(false) +, _CPBody(nullptr) +, _pB2Body(nullptr) +, _PTMRatio(0.0f) +, _syncTransform(nullptr) +{} + +PhysicsSpriteBox2D* PhysicsSpriteBox2D::create() +{ + PhysicsSpriteBox2D* pRet = new (std::nothrow) PhysicsSpriteBox2D(); + if (pRet && pRet->init()) + { + pRet->autorelease(); + } + else + { + CC_SAFE_DELETE(pRet); + } + + return pRet; +} + +PhysicsSpriteBox2D* PhysicsSpriteBox2D::createWithTexture(Texture2D *pTexture) +{ + PhysicsSpriteBox2D* pRet = new (std::nothrow) PhysicsSpriteBox2D(); + if (pRet && pRet->initWithTexture(pTexture)) + { + pRet->autorelease(); + } + else + { + CC_SAFE_DELETE(pRet); + } + + return pRet; +} + +PhysicsSpriteBox2D* PhysicsSpriteBox2D::createWithTexture(Texture2D *pTexture, const Rect& rect) +{ + PhysicsSpriteBox2D* pRet = new (std::nothrow) PhysicsSpriteBox2D(); + if (pRet && pRet->initWithTexture(pTexture, rect)) + { + pRet->autorelease(); + } + else + { + CC_SAFE_DELETE(pRet); + } + + return pRet; +} + +PhysicsSpriteBox2D* PhysicsSpriteBox2D::createWithSpriteFrame(SpriteFrame *pSpriteFrame) +{ + PhysicsSpriteBox2D* pRet = new (std::nothrow) PhysicsSpriteBox2D(); + if (pRet && pRet->initWithSpriteFrame(pSpriteFrame)) + { + pRet->autorelease(); + } + else + { + CC_SAFE_DELETE(pRet); + } + + return pRet; +} + +PhysicsSpriteBox2D* PhysicsSpriteBox2D::createWithSpriteFrameName(const char *pszSpriteFrameName) +{ + PhysicsSpriteBox2D* pRet = new (std::nothrow) PhysicsSpriteBox2D(); + if (pRet && pRet->initWithSpriteFrameName(pszSpriteFrameName)) + { + pRet->autorelease(); + } + else + { + CC_SAFE_DELETE(pRet); + } + + return pRet; +} + +PhysicsSpriteBox2D* PhysicsSpriteBox2D::create(const char *pszFileName) +{ + PhysicsSpriteBox2D* pRet = new (std::nothrow) PhysicsSpriteBox2D(); + if (pRet && pRet->initWithFile(pszFileName)) + { + pRet->autorelease(); + } + else + { + CC_SAFE_DELETE(pRet); + } + + return pRet; +} + +PhysicsSpriteBox2D* PhysicsSpriteBox2D::create(const char *pszFileName, const Rect& rect) +{ + PhysicsSpriteBox2D* pRet = new (std::nothrow) PhysicsSpriteBox2D(); + if (pRet && pRet->initWithFile(pszFileName, rect)) + { + pRet->autorelease(); + } + else + { + CC_SAFE_DELETE(pRet); + } + + return pRet; +} + +// this method will only get called if the sprite is batched. +// return YES if the physic's values (angles, position ) changed. +// If you return NO, then getNodeToParentTransform won't be called. +bool PhysicsSpriteBox2D::isDirty() const +{ + return true; +} + +bool PhysicsSpriteBox2D::isIgnoreBodyRotation() const +{ + return _ignoreBodyRotation; +} + +void PhysicsSpriteBox2D::setIgnoreBodyRotation(bool bIgnoreBodyRotation) +{ + _ignoreBodyRotation = bIgnoreBodyRotation; +} + +// Override the setters and getters to always reflect the body's properties. +const Vec2& PhysicsSpriteBox2D::getPosition() const +{ + return getPosFromPhysics(); +} + +void PhysicsSpriteBox2D::getPosition(float* x, float* y) const +{ + if (x == nullptr || y == nullptr) { + return; + } + const Vec2& pos = getPosFromPhysics(); + *x = pos.x; + *y = pos.y; +} + +float PhysicsSpriteBox2D::getPositionX() const +{ + return getPosFromPhysics().x; +} + +float PhysicsSpriteBox2D::getPositionY() const +{ + return getPosFromPhysics().y; +} + +Vec3 PhysicsSpriteBox2D::getPosition3D() const +{ + Vec2 pos = getPosFromPhysics(); + return Vec3(pos.x, pos.y, 0); +} + +// +// Chipmunk only +// + + + +cpBody* PhysicsSpriteBox2D::getCPBody() const +{ + + CCASSERT(false, "Can't call chipmunk methods when Chipmunk is disabled"); + return nullptr; +} + +void PhysicsSpriteBox2D::setCPBody(cpBody *pBody) +{ + _CPBody = pBody; +} + +b2Body* PhysicsSpriteBox2D::getB2Body() const +{ + return _pB2Body; +} + +void PhysicsSpriteBox2D::setB2Body(b2Body *pBody) +{ + _pB2Body = pBody; +} + +float PhysicsSpriteBox2D::getPTMRatio() const +{ + return _PTMRatio; +} + +void PhysicsSpriteBox2D::setPTMRatio(float fRatio) +{ + _PTMRatio = fRatio; +} + +// +// Common to Box2d and Chipmunk +// + +const Vec2& PhysicsSpriteBox2D::getPosFromPhysics() const +{ + static Vec2 s_physicPosion; + + b2Vec2 pos = _pB2Body->GetPosition(); + float x = pos.x * _PTMRatio; + float y = pos.y * _PTMRatio; + s_physicPosion.set(x,y); + + return s_physicPosion; +} + +void PhysicsSpriteBox2D::setPosition(float x, float y) +{ + + + float angle = _pB2Body->GetAngle(); + _pB2Body->SetTransform(b2Vec2(x / _PTMRatio, y / _PTMRatio), angle); + +} + +void PhysicsSpriteBox2D::setPosition(const Vec2 &pos) +{ + setPosition(pos.x, pos.y); +} + +void PhysicsSpriteBox2D::setPositionX(float x) +{ + setPosition(x, getPositionY()); +} + +void PhysicsSpriteBox2D::setPositionY(float y) +{ + setPosition(getPositionX(), y); +} + +void PhysicsSpriteBox2D::setPosition3D(const Vec3& position) +{ + setPosition(position.x, position.y); +} + +float PhysicsSpriteBox2D::getRotation() const +{ + return (_ignoreBodyRotation ? Sprite::getRotation() : + CC_RADIANS_TO_DEGREES(_pB2Body->GetAngle())); +} + +void PhysicsSpriteBox2D::setRotation(float fRotation) +{ + if (_ignoreBodyRotation) + { + Sprite::setRotation(fRotation); + } + + else + { + b2Vec2 p = _pB2Body->GetPosition(); + float radians = CC_DEGREES_TO_RADIANS(fRotation); + _pB2Body->SetTransform(p, radians); + } +} + +void PhysicsSpriteBox2D::syncPhysicsTransform() const +{ + // Although scale is not used by physics engines, it is calculated just in case + // the sprite is animated (scaled up/down) using actions. + // For more info see: http://www.cocos2d-iphone.org/forum/topic/68990 + + + b2Vec2 pos = _pB2Body->GetPosition(); + + float x = pos.x * _PTMRatio; + float y = pos.y * _PTMRatio; + + if (_ignoreAnchorPointForPosition) + { + x += _anchorPointInPoints.x; + y += _anchorPointInPoints.y; + } + + // Make matrix + float radians = _pB2Body->GetAngle(); + float c = cosf(radians); + float s = sinf(radians); + + if (!_anchorPointInPoints.isZero()) + { + x += ((c * -_anchorPointInPoints.x * _scaleX) + (-s * -_anchorPointInPoints.y * _scaleY)); + y += ((s * -_anchorPointInPoints.x * _scaleX) + (c * -_anchorPointInPoints.y * _scaleY)); + } + + // Rot, Translate Matrix + + float mat[] = { (float)c * _scaleX, (float)s * _scaleX, 0, 0, + (float)-s * _scaleY, (float)c * _scaleY, 0, 0, + 0, 0, 1, 0, + x, y, 0, 1}; + + _transform.set(mat); + +} + +void PhysicsSpriteBox2D::onEnter() +{ + Node::onEnter(); + _syncTransform = Director::getInstance()->getEventDispatcher()->addCustomEventListener(Director::EVENT_AFTER_UPDATE, std::bind(&PhysicsSpriteBox2D::afterUpdate, this, std::placeholders::_1)); + _syncTransform->retain(); +} + +void PhysicsSpriteBox2D::onExit() +{ + if (_syncTransform != nullptr) + { + Director::getInstance()->getEventDispatcher()->removeEventListener(_syncTransform); + _syncTransform->release(); + } + Node::onExit(); +} + +void PhysicsSpriteBox2D::afterUpdate(EventCustom* /*event*/) +{ + syncPhysicsTransform(); + + _transformDirty = false; + _transformUpdated = true; + setDirtyRecursively(true); +} + +NS_CC_EXT_END + +#endif // CC_ENABLE_CHIPMUNK_INTEGRATION || CC_ENABLE_BOX2D_INTEGRATION diff --git a/extensions/physics-nodes/CCPhysicsSpriteBox2D.h b/extensions/physics-nodes/CCPhysicsSpriteBox2D.h new file mode 100644 index 0000000000..2ffe679af3 --- /dev/null +++ b/extensions/physics-nodes/CCPhysicsSpriteBox2D.h @@ -0,0 +1,154 @@ +/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software + * Copyright (c) 2012 cocos2d-x.org + * Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + * + * 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: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 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 __PHYSICSNODES_CCPHYSICSSPRITEBOX2D_H__ +#define __PHYSICSNODES_CCPHYSICSSPRITEBOX2D_H__ + +#include "2d/CCSprite.h" +#include "extensions/ExtensionMacros.h" +#include "extensions/ExtensionExport.h" +#include "base/CCEventListenerCustom.h" + + //#if (CC_ENABLE_CHIPMUNK_INTEGRATION || CC_ENABLE_BOX2D_INTEGRATION) + +struct cpBody; +class b2Body; + +NS_CC_EXT_BEGIN + +/** A Sprite subclass that is bound to a physics body. + It works with: + - Chipmunk: Preprocessor macro CC_ENABLE_CHIPMUNK_INTEGRATION should be defined + - Objective-Chipmunk: Preprocessor macro CC_ENABLE_CHIPMUNK_INTEGRATION should be defined + - Box2d: Preprocessor macro CC_ENABLE_BOX2D_INTEGRATION should be defined + + Features and Limitations: + - Scale and Skew properties are ignored. + - Position and rotation are going to updated from the physics body + - If you update the rotation or position manually, the physics body will be updated + - You can't enble both Chipmunk support and Box2d support at the same time. Only one can be enabled at compile time + * @lua NA + */ + class CC_EX_DLL PhysicsSpriteBox2D : public Sprite +{ +public: + + static PhysicsSpriteBox2D* create(); + /** Creates an sprite with a texture. + The rect used will be the size of the texture. + The offset will be (0,0). + */ + static PhysicsSpriteBox2D* createWithTexture(Texture2D* pTexture); + + /** Creates an sprite with a texture and a rect. + The offset will be (0,0). + */ + static PhysicsSpriteBox2D* createWithTexture(Texture2D* pTexture, const Rect& rect); + + /** Creates an sprite with an sprite frame. */ + static PhysicsSpriteBox2D* createWithSpriteFrame(SpriteFrame* pSpriteFrame); + + /** Creates an sprite with an sprite frame name. + An SpriteFrame will be fetched from the SpriteFrameCache by name. + If the SpriteFrame doesn't exist it will raise an exception. + @since v0.9 + */ + static PhysicsSpriteBox2D* createWithSpriteFrameName(const char* pszSpriteFrameName); + + /** Creates an sprite with an image filename. + The rect used will be the size of the image. + The offset will be (0,0). + */ + static PhysicsSpriteBox2D* create(const char* pszFileName); + + /** Creates an sprite with an image filename and a rect. + The offset will be (0,0). + */ + static PhysicsSpriteBox2D* create(const char* pszFileName, const Rect& rect); + + PhysicsSpriteBox2D(); + + virtual bool isDirty() const override; + + /** Keep the sprite's rotation separate from the body. */ + bool isIgnoreBodyRotation() const; + void setIgnoreBodyRotation(bool bIgnoreBodyRotation); + + // + // Chipmunk specific + // + /** Body accessor when using regular Chipmunk */ + cpBody* getCPBody() const; + void setCPBody(cpBody* pBody); + + // + // Box2d specific + // + /** Body accessor when using box2d */ + b2Body* getB2Body() const; + void setB2Body(b2Body* pBody); + + float getPTMRatio() const; + void setPTMRatio(float fPTMRatio); + virtual void syncPhysicsTransform() const; + + // overrides + virtual const Vec2& getPosition() const override; + virtual void getPosition(float* x, float* y) const override; + virtual float getPositionX() const override; + virtual float getPositionY() const override; + virtual Vec3 getPosition3D() const override; + virtual void setPosition(const Vec2& position) override; + virtual void setPosition(float x, float y) override; + virtual void setPositionX(float x) override; + virtual void setPositionY(float y) override; + virtual void setPosition3D(const Vec3& position) override; + virtual float getRotation() const override; + virtual void setRotation(float fRotation) override; + + virtual void onEnter() override; + virtual void onExit() override; + +protected: + const Vec2& getPosFromPhysics() const; + void afterUpdate(EventCustom* event); + +protected: + bool _ignoreBodyRotation; + + // chipmunk specific + cpBody* _CPBody; + + // box2d specific + b2Body* _pB2Body; + float _PTMRatio; + + // Event for update synchronise physic transform + cocos2d::EventListenerCustom* _syncTransform; +}; + +NS_CC_EXT_END + +//#endif // CC_ENABLE_CHIPMUNK_INTEGRATION || CC_ENABLE_BOX2D_INTEGRATION + +#endif // __PHYSICSNODES_CCPHYSICSSPRITEBOX2D_H__ diff --git a/extensions/physics-nodes/CCPhysicsSpriteChipmunk2D.cpp b/extensions/physics-nodes/CCPhysicsSpriteChipmunk2D.cpp new file mode 100644 index 0000000000..0a256515c2 --- /dev/null +++ b/extensions/physics-nodes/CCPhysicsSpriteChipmunk2D.cpp @@ -0,0 +1,346 @@ +/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software + * Copyright (c) 2012 cocos2d-x.org + * Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + * + * 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: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 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. + */ + +#include "CCPhysicsSpriteChipmunk2D.h" +#include "base/CCDirector.h" +#include "base/CCEventDispatcher.h" + + +#include "chipmunk/chipmunk.h" + + +NS_CC_EXT_BEGIN + +PhysicsSpriteChipmunk2D::PhysicsSpriteChipmunk2D() +: _ignoreBodyRotation(false) +, _CPBody(nullptr) +, _pB2Body(nullptr) +, _PTMRatio(0.0f) +, _syncTransform(nullptr) +{} + +PhysicsSpriteChipmunk2D* PhysicsSpriteChipmunk2D::create() +{ + PhysicsSpriteChipmunk2D* pRet = new (std::nothrow) PhysicsSpriteChipmunk2D(); + if (pRet && pRet->init()) + { + pRet->autorelease(); + } + else + { + CC_SAFE_DELETE(pRet); + } + + return pRet; +} + +PhysicsSpriteChipmunk2D* PhysicsSpriteChipmunk2D::createWithTexture(Texture2D *pTexture) +{ + PhysicsSpriteChipmunk2D* pRet = new (std::nothrow) PhysicsSpriteChipmunk2D(); + if (pRet && pRet->initWithTexture(pTexture)) + { + pRet->autorelease(); + } + else + { + CC_SAFE_DELETE(pRet); + } + + return pRet; +} + +PhysicsSpriteChipmunk2D* PhysicsSpriteChipmunk2D::createWithTexture(Texture2D *pTexture, const Rect& rect) +{ + PhysicsSpriteChipmunk2D* pRet = new (std::nothrow) PhysicsSpriteChipmunk2D(); + if (pRet && pRet->initWithTexture(pTexture, rect)) + { + pRet->autorelease(); + } + else + { + CC_SAFE_DELETE(pRet); + } + + return pRet; +} + +PhysicsSpriteChipmunk2D* PhysicsSpriteChipmunk2D::createWithSpriteFrame(SpriteFrame *pSpriteFrame) +{ + PhysicsSpriteChipmunk2D* pRet = new (std::nothrow) PhysicsSpriteChipmunk2D(); + if (pRet && pRet->initWithSpriteFrame(pSpriteFrame)) + { + pRet->autorelease(); + } + else + { + CC_SAFE_DELETE(pRet); + } + + return pRet; +} + +PhysicsSpriteChipmunk2D* PhysicsSpriteChipmunk2D::createWithSpriteFrameName(const char *pszSpriteFrameName) +{ + PhysicsSpriteChipmunk2D* pRet = new (std::nothrow) PhysicsSpriteChipmunk2D(); + if (pRet && pRet->initWithSpriteFrameName(pszSpriteFrameName)) + { + pRet->autorelease(); + } + else + { + CC_SAFE_DELETE(pRet); + } + + return pRet; +} + +PhysicsSpriteChipmunk2D* PhysicsSpriteChipmunk2D::create(const char *pszFileName) +{ + PhysicsSpriteChipmunk2D* pRet = new (std::nothrow) PhysicsSpriteChipmunk2D(); + if (pRet && pRet->initWithFile(pszFileName)) + { + pRet->autorelease(); + } + else + { + CC_SAFE_DELETE(pRet); + } + + return pRet; +} + +PhysicsSpriteChipmunk2D* PhysicsSpriteChipmunk2D::create(const char *pszFileName, const Rect& rect) +{ + PhysicsSpriteChipmunk2D* pRet = new (std::nothrow) PhysicsSpriteChipmunk2D(); + if (pRet && pRet->initWithFile(pszFileName, rect)) + { + pRet->autorelease(); + } + else + { + CC_SAFE_DELETE(pRet); + } + + return pRet; +} + +// this method will only get called if the sprite is batched. +// return YES if the physic's values (angles, position ) changed. +// If you return NO, then getNodeToParentTransform won't be called. +bool PhysicsSpriteChipmunk2D::isDirty() const +{ + return true; +} + +bool PhysicsSpriteChipmunk2D::isIgnoreBodyRotation() const +{ + return _ignoreBodyRotation; +} + +void PhysicsSpriteChipmunk2D::setIgnoreBodyRotation(bool bIgnoreBodyRotation) +{ + _ignoreBodyRotation = bIgnoreBodyRotation; +} + +// Override the setters and getters to always reflect the body's properties. +const Vec2& PhysicsSpriteChipmunk2D::getPosition() const +{ + return getPosFromPhysics(); +} + +void PhysicsSpriteChipmunk2D::getPosition(float* x, float* y) const +{ + if (x == nullptr || y == nullptr) { + return; + } + const Vec2& pos = getPosFromPhysics(); + *x = pos.x; + *y = pos.y; +} + +float PhysicsSpriteChipmunk2D::getPositionX() const +{ + return getPosFromPhysics().x; +} + +float PhysicsSpriteChipmunk2D::getPositionY() const +{ + return getPosFromPhysics().y; +} + +Vec3 PhysicsSpriteChipmunk2D::getPosition3D() const +{ + Vec2 pos = getPosFromPhysics(); + return Vec3(pos.x, pos.y, 0); +} + +// +// Chipmunk only +// + + + +cpBody* PhysicsSpriteChipmunk2D::getCPBody() const +{ + return _CPBody; +} + +void PhysicsSpriteChipmunk2D::setCPBody(cpBody *pBody) +{ + _CPBody = pBody; +} + +b2Body* PhysicsSpriteChipmunk2D::getB2Body() const +{ + CCASSERT(false, "Can't call box2d methods when Box2d is disabled"); + return nullptr; +} + +void PhysicsSpriteChipmunk2D::setB2Body(b2Body *pBody) +{ + CC_UNUSED_PARAM(pBody); + CCASSERT(false, "Can't call box2d methods when Box2d is disabled"); +} + +float PhysicsSpriteChipmunk2D::getPTMRatio() const +{ + CCASSERT(false, "Can't call box2d methods when Box2d is disabled"); + return 0; +} + +void PhysicsSpriteChipmunk2D::setPTMRatio(float fRatio) +{ + CC_UNUSED_PARAM(fRatio); + CCASSERT(false, "Can't call box2d methods when Box2d is disabled"); +} + +// +// Common to Box2d and Chipmunk +// + +const Vec2& PhysicsSpriteChipmunk2D::getPosFromPhysics() const +{ + static Vec2 s_physicPosion; + + cpVect cpPos = cpBodyGetPosition(_CPBody); + s_physicPosion = Vec2(cpPos.x, cpPos.y); + + return s_physicPosion; +} + +void PhysicsSpriteChipmunk2D::setPosition(float x, float y) +{ + cpVect cpPos = cpv(x, y); + cpBodySetPosition(_CPBody, cpPos); +} + +void PhysicsSpriteChipmunk2D::setPosition(const Vec2 &pos) +{ + setPosition(pos.x, pos.y); +} + +void PhysicsSpriteChipmunk2D::setPositionX(float x) +{ + setPosition(x, getPositionY()); +} + +void PhysicsSpriteChipmunk2D::setPositionY(float y) +{ + setPosition(getPositionX(), y); +} + +void PhysicsSpriteChipmunk2D::setPosition3D(const Vec3& position) +{ + setPosition(position.x, position.y); +} + +float PhysicsSpriteChipmunk2D::getRotation() const +{ + return (_ignoreBodyRotation ? Sprite::getRotation() : -CC_RADIANS_TO_DEGREES(cpBodyGetAngle(_CPBody))); +} + +void PhysicsSpriteChipmunk2D::setRotation(float fRotation) +{ + if (_ignoreBodyRotation) + { + Sprite::setRotation(fRotation); + } + else + { + cpBodySetAngle(_CPBody, -CC_DEGREES_TO_RADIANS(fRotation)); + } + +} + +void PhysicsSpriteChipmunk2D::syncPhysicsTransform() const +{ + // Although scale is not used by physics engines, it is calculated just in case + // the sprite is animated (scaled up/down) using actions. + // For more info see: http://www.cocos2d-iphone.org/forum/topic/68990 + + + cpVect rot = (_ignoreBodyRotation ? cpvforangle(-CC_DEGREES_TO_RADIANS(_rotationX)) : cpBodyGetRotation(_CPBody)); + float x = cpBodyGetPosition(_CPBody).x + rot.x * -_anchorPointInPoints.x * _scaleX - rot.y * -_anchorPointInPoints.y * _scaleY; + float y = cpBodyGetPosition(_CPBody).y + rot.y * -_anchorPointInPoints.x * _scaleX + rot.x * -_anchorPointInPoints.y * _scaleY; + + if (_ignoreAnchorPointForPosition) + { + x += _anchorPointInPoints.x; + y += _anchorPointInPoints.y; + } + + float mat[] = { (float)rot.x * _scaleX, (float)rot.y * _scaleX, 0, 0, + (float)-rot.y * _scaleY, (float)rot.x * _scaleY, 0, 0, + 0, 0, 1, 0, + x, y, 0, 1}; + + _transform.set(mat); +} + +void PhysicsSpriteChipmunk2D::onEnter() +{ + Node::onEnter(); + _syncTransform = Director::getInstance()->getEventDispatcher()->addCustomEventListener(Director::EVENT_AFTER_UPDATE, std::bind(&PhysicsSpriteChipmunk2D::afterUpdate, this, std::placeholders::_1)); + _syncTransform->retain(); +} + +void PhysicsSpriteChipmunk2D::onExit() +{ + if (_syncTransform != nullptr) + { + Director::getInstance()->getEventDispatcher()->removeEventListener(_syncTransform); + _syncTransform->release(); + } + Node::onExit(); +} + +void PhysicsSpriteChipmunk2D::afterUpdate(EventCustom* /*event*/) +{ + syncPhysicsTransform(); + + _transformDirty = false; + _transformUpdated = true; + setDirtyRecursively(true); +} + +NS_CC_EXT_END \ No newline at end of file diff --git a/extensions/physics-nodes/CCPhysicsSpriteChipmunk2D.h b/extensions/physics-nodes/CCPhysicsSpriteChipmunk2D.h new file mode 100644 index 0000000000..25417e0262 --- /dev/null +++ b/extensions/physics-nodes/CCPhysicsSpriteChipmunk2D.h @@ -0,0 +1,154 @@ +/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software + * Copyright (c) 2012 cocos2d-x.org + * Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + * + * 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: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 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 __PHYSICSNODES_CCPhysicsSpriteChipmunk2DCHIPMUNK2D_H__ +#define __PHYSICSNODES_CCPhysicsSpriteChipmunk2DCHIPMUNK2D_H__ + +#include "2d/CCSprite.h" +#include "extensions/ExtensionMacros.h" +#include "extensions/ExtensionExport.h" +#include "base/CCEventListenerCustom.h" + +#if (CC_ENABLE_CHIPMUNK_INTEGRATION || CC_ENABLE_BOX2D_INTEGRATION) + +struct cpBody; +class b2Body; + +NS_CC_EXT_BEGIN + +/** A Sprite subclass that is bound to a physics body. + It works with: + - Chipmunk: Preprocessor macro CC_ENABLE_CHIPMUNK_INTEGRATION should be defined + - Objective-Chipmunk: Preprocessor macro CC_ENABLE_CHIPMUNK_INTEGRATION should be defined + - Box2d: Preprocessor macro CC_ENABLE_BOX2D_INTEGRATION should be defined + + Features and Limitations: + - Scale and Skew properties are ignored. + - Position and rotation are going to updated from the physics body + - If you update the rotation or position manually, the physics body will be updated + - You can't enble both Chipmunk support and Box2d support at the same time. Only one can be enabled at compile time + * @lua NA + */ +class CC_EX_DLL PhysicsSpriteChipmunk2D : public Sprite +{ +public: + + static PhysicsSpriteChipmunk2D* create(); + /** Creates an sprite with a texture. + The rect used will be the size of the texture. + The offset will be (0,0). + */ + static PhysicsSpriteChipmunk2D* createWithTexture(Texture2D *pTexture); + + /** Creates an sprite with a texture and a rect. + The offset will be (0,0). + */ + static PhysicsSpriteChipmunk2D* createWithTexture(Texture2D *pTexture, const Rect& rect); + + /** Creates an sprite with an sprite frame. */ + static PhysicsSpriteChipmunk2D* createWithSpriteFrame(SpriteFrame *pSpriteFrame); + + /** Creates an sprite with an sprite frame name. + An SpriteFrame will be fetched from the SpriteFrameCache by name. + If the SpriteFrame doesn't exist it will raise an exception. + @since v0.9 + */ + static PhysicsSpriteChipmunk2D* createWithSpriteFrameName(const char *pszSpriteFrameName); + + /** Creates an sprite with an image filename. + The rect used will be the size of the image. + The offset will be (0,0). + */ + static PhysicsSpriteChipmunk2D* create(const char *pszFileName); + + /** Creates an sprite with an image filename and a rect. + The offset will be (0,0). + */ + static PhysicsSpriteChipmunk2D* create(const char *pszFileName, const Rect& rect); + + PhysicsSpriteChipmunk2D(); + + virtual bool isDirty() const override; + + /** Keep the sprite's rotation separate from the body. */ + bool isIgnoreBodyRotation() const; + void setIgnoreBodyRotation(bool bIgnoreBodyRotation); + + // + // Chipmunk specific + // + /** Body accessor when using regular Chipmunk */ + cpBody* getCPBody() const; + void setCPBody(cpBody *pBody); + + // + // Box2d specific + // + /** Body accessor when using box2d */ + b2Body* getB2Body() const; + void setB2Body(b2Body *pBody); + + float getPTMRatio() const; + void setPTMRatio(float fPTMRatio); + virtual void syncPhysicsTransform() const; + + // overrides + virtual const Vec2& getPosition() const override; + virtual void getPosition(float* x, float* y) const override; + virtual float getPositionX() const override; + virtual float getPositionY() const override; + virtual Vec3 getPosition3D() const override; + virtual void setPosition(const Vec2 &position) override; + virtual void setPosition(float x, float y) override; + virtual void setPositionX(float x) override; + virtual void setPositionY(float y) override; + virtual void setPosition3D(const Vec3& position) override; + virtual float getRotation() const override; + virtual void setRotation(float fRotation) override; + + virtual void onEnter() override; + virtual void onExit() override; + +protected: + const Vec2& getPosFromPhysics() const; + void afterUpdate(EventCustom *event); + +protected: + bool _ignoreBodyRotation; + + // chipmunk specific + cpBody *_CPBody; + + // box2d specific + b2Body *_pB2Body; + float _PTMRatio; + + // Event for update synchronise physic transform + cocos2d::EventListenerCustom* _syncTransform; +}; + +NS_CC_EXT_END + +#endif // CC_ENABLE_CHIPMUNK_INTEGRATION || CC_ENABLE_BOX2D_INTEGRATION + +#endif // __PHYSICSNODES_CCPhysicsSpriteChipmunk2DCHIPMUNK2D_H__ diff --git a/tests/cpp-tests/Classes/AppDelegate.cpp b/tests/cpp-tests/Classes/AppDelegate.cpp index ce7b1ac59a..5405e245a9 100644 --- a/tests/cpp-tests/Classes/AppDelegate.cpp +++ b/tests/cpp-tests/Classes/AppDelegate.cpp @@ -54,11 +54,7 @@ void AppDelegate::initGLContextAttrs() GLView::setGLContextAttrs(glContextAttrs); } -#if defined(CC_PLATFORM_PC) -static Size resourceSize(1280, 720); -#else static Size resourceSize(960, 640); -#endif static Size designSize(480, 320); bool AppDelegate::applicationDidFinishLaunching() diff --git a/tests/cpp-tests/Classes/Box2DTest/Box2dTest.cpp b/tests/cpp-tests/Classes/Box2DTest/Box2dTest.cpp index 9f3dd261fa..4997a37f7b 100644 --- a/tests/cpp-tests/Classes/Box2DTest/Box2dTest.cpp +++ b/tests/cpp-tests/Classes/Box2DTest/Box2dTest.cpp @@ -28,6 +28,8 @@ #include "renderer/CCRenderer.h" #include "renderer/CCCustomCommand.h" + + USING_NS_CC; USING_NS_CC_EXT; @@ -227,7 +229,7 @@ void Box2DTest::addNewSpriteAtPosition(Vec2 p) //just randomly picking one of the images int idx = (CCRANDOM_0_1() > .5 ? 0 : 1); int idy = (CCRANDOM_0_1() > .5 ? 0 : 1); - auto sprite = PhysicsSprite::createWithTexture(_spriteTexture, Rect(32 * idx, 32 * idy, 32, 32)); + auto sprite = PhysicsSpriteBox2D::createWithTexture(_spriteTexture, Rect(32 * idx, 32 * idy, 32, 32)); parent->addChild(sprite); sprite->setB2Body(body); sprite->setPTMRatio(PTM_RATIO); diff --git a/tests/cpp-tests/Classes/ChipmunkTest/ChipmunkTest.cpp b/tests/cpp-tests/Classes/ChipmunkTest/ChipmunkTest.cpp index e7af66af9d..4b13c62afa 100644 --- a/tests/cpp-tests/Classes/ChipmunkTest/ChipmunkTest.cpp +++ b/tests/cpp-tests/Classes/ChipmunkTest/ChipmunkTest.cpp @@ -32,6 +32,7 @@ #include "ChipmunkTest.h" + USING_NS_CC; USING_NS_CC_EXT; @@ -46,8 +47,7 @@ enum { // callback to remove Shapes from the Space ChipmunkTest::ChipmunkTest() -{ -#if CC_ENABLE_CHIPMUNK_INTEGRATION +{ // enable events auto touchListener = EventListenerTouchAllAtOnce::create(); @@ -91,16 +91,6 @@ ChipmunkTest::ChipmunkTest() menu->setPosition(VisibleRect::right().x-100, VisibleRect::top().y-60); scheduleUpdate(); -#else - auto label = Label::createWithTTF("Should define CC_ENABLE_CHIPMUNK_INTEGRATION=1\n to run this test case", - "fonts/arial.ttf", - 18); - auto size = Director::getInstance()->getWinSize(); - label->setPosition(size.width/2, size.height/2); - - addChild(label); - -#endif } @@ -131,7 +121,7 @@ ChipmunkTest::~ChipmunkTest() void ChipmunkTest::initPhysics() { -#if CC_ENABLE_CHIPMUNK_INTEGRATION + // init chipmunk //cpInitChipmunk(); @@ -178,7 +168,7 @@ void ChipmunkTest::initPhysics() // Physics debug layer _debugLayer = PhysicsDebugNode::create(_space); this->addChild(_debugLayer, Z_PHYSICS_DEBUG); -#endif + } void ChipmunkTest::update(float delta) @@ -214,7 +204,6 @@ void ChipmunkTest::reset(Ref* sender) void ChipmunkTest::addNewSpriteAtPosition(cocos2d::Vec2 pos) { -#if CC_ENABLE_CHIPMUNK_INTEGRATION int posx, posy; auto parent = getChildByTag(kTagParentNode); @@ -244,12 +233,12 @@ void ChipmunkTest::addNewSpriteAtPosition(cocos2d::Vec2 pos) cpShapeSetFriction(shape, 0.5f); cpSpaceAddShape(_space, shape); - auto sprite = PhysicsSprite::createWithTexture(_spriteTexture, cocos2d::Rect(posx, posy, 85, 121)); + auto sprite = PhysicsSpriteChipmunk2D::createWithTexture(_spriteTexture, cocos2d::Rect(posx, posy, 85, 121)); parent->addChild(sprite); sprite->setCPBody(body); sprite->setPosition(pos); -#endif + } void ChipmunkTest::onEnter() diff --git a/tests/cpp-tests/Classes/ChipmunkTest/ChipmunkTest.h b/tests/cpp-tests/Classes/ChipmunkTest/ChipmunkTest.h index 0555434884..41f4563e34 100644 --- a/tests/cpp-tests/Classes/ChipmunkTest/ChipmunkTest.h +++ b/tests/cpp-tests/Classes/ChipmunkTest/ChipmunkTest.h @@ -52,10 +52,9 @@ public: virtual void onAcceleration(cocos2d::Acceleration* acc, cocos2d::Event* event); private: - cocos2d::Texture2D* _spriteTexture; // weak ref -#if CC_ENABLE_CHIPMUNK_INTEGRATION + cocos2d::Texture2D* _spriteTexture; // weak ref cocos2d::extension::PhysicsDebugNode* _debugLayer; // weak ref -#endif + cpSpace* _space; // strong ref cpShape* _walls[4]; }; diff --git a/tests/cpp-tests/Classes/ImGuiEXTTest/ImGuiEXTTest.cpp b/tests/cpp-tests/Classes/ImGuiEXTTest/ImGuiEXTTest.cpp index 48301e7e62..10aacf9b2b 100644 --- a/tests/cpp-tests/Classes/ImGuiEXTTest/ImGuiEXTTest.cpp +++ b/tests/cpp-tests/Classes/ImGuiEXTTest/ImGuiEXTTest.cpp @@ -14,6 +14,12 @@ static ImVec4 clear_color = ImColor(114, 144, 154); ImGuiEXTTests::ImGuiEXTTests() { + static Size resourceSize(1280, 720); + + auto director = Director::getInstance(); + GLViewImpl* view = (GLViewImpl*)Director::getInstance()->getOpenGLView(); + view->setWindowed(resourceSize.width, resourceSize.height); + ADD_TEST_CASE(ImGuiEXTTest); } @@ -32,6 +38,10 @@ void ImGuiEXTTest::onExit() ImGuiEXT::destroyInstance(); + static Size resourceSize(960, 640); + GLViewImpl* view = (GLViewImpl*)Director::getInstance()->getOpenGLView(); + view->setWindowed(resourceSize.width, resourceSize.height); + TestCase::onExit(); } diff --git a/tests/cpp-tests/Classes/controller.cpp b/tests/cpp-tests/Classes/controller.cpp index e2849360e4..c9178b9643 100644 --- a/tests/cpp-tests/Classes/controller.cpp +++ b/tests/cpp-tests/Classes/controller.cpp @@ -53,13 +53,12 @@ public: addTest("Actions - Ease", [](){return new (std::nothrow) ActionsEaseTests(); }); addTest("Actions - Progress", [](){return new (std::nothrow) ActionsProgressTests(); }); addTest("Audio - NewAudioEngine", []() { return new (std::nothrow) AudioEngineTests(); }); -#if CC_ENABLE_BOX2D_INTEGRATION + + addTest("Box2d - Basic", []() { return new (std::nothrow) Box2DTests(); }); // addTest("Box2d - TestBed", []() { return new (std::nothrow) Box2dTestBedSuite(); }); -#endif -#if CC_ENABLE_CHIPMUNK_INTEGRATION - addTest("Chipmunk", []() { return new ChipmunkTests(); }); -#endif + addTest("Chipmunk", []() { return new ChipmunkTests(); }); + addTest("Bugs", []() { return new BugsTests(); }); addTest("Click and Move", [](){return new ClickAndMoveTest(); }); addTest("Configuration", []() { return new ConfigurationTests(); }); diff --git a/tests/cpp-tests/Classes/tests.h b/tests/cpp-tests/Classes/tests.h index dcc75ac8db..6a2deb8344 100644 --- a/tests/cpp-tests/Classes/tests.h +++ b/tests/cpp-tests/Classes/tests.h @@ -25,13 +25,12 @@ #ifndef _TESTS_H_ #define _TESTS_H_ -#if CC_ENABLE_BOX2D_INTEGRATION + #include "Box2DTest/Box2dTest.h" //#include "Box2DTestBed/Box2dView.h" -#endif -#if CC_ENABLE_CHIPMUNK_INTEGRATION + #include "ChipmunkTest/ChipmunkTest.h" -#endif + #if (CC_TARGET_PLATFORM != CC_PLATFORM_MARMALADE) #include "ClippingNodeTest/ClippingNodeTest.h" #endif