物理引擎能夠模仿真實世界物理運動規律,使得精靈做出自由落體、拋物線運動、互相碰撞、反彈等效果,使用物理引擎還可以進行準確的碰撞檢測。
物理引擎本身不包括精靈,它與精靈關系之間是相互獨立的,精靈不會自動跟著物理引擎中的物體做物理運動,通常需要編寫代碼將物體與精靈連接起來,同步它們的狀態。
在Cocos2d-x 3.x 中物理世界被融入游戲引擎的場景中,我們可以指定這個場景是否使用物理引擎,為此創建類Scene增加如下函數:
static Scene * createWithPhysics()
:創建場景對象。bool initWithPhysics()
:初始化具有物理引擎場景對象。void addChlidToPhysicsWorld(Node * child)
:增加節點對象到物理世界。PhysicsWorld * getPhysicsWorld()
:獲得物理世界對象。Cocos2d-x 3.x 在節點類Node中增加了physicsBody屬性,我們可以將物理引擎中的物體添加到Node對象中。 此外,Cocos2d-x 3.x為物理引擎增加了很多類,其中主要的類如下:
PhysicsWorld類:封裝物理引擎世界(World)。PhysicsBody類:封裝物理引擎物體(Body)。PhysiCSShape類:封裝物理疫情形狀(Shape)。PhysicsContact類:封裝物理引擎碰撞類(Contact)。EventListenerPhysicsContact類:碰撞檢測監聽類。PhysicsJoint類:封裝物理引擎關節(Joint)。形狀類PhysicsShape是一個抽象類,它有很多子類:
PhysicsShapeCircle:圓圈。PhysicsShapeBox:矩形盒子。PhysicsShapePolygon:多邊形。PhysicsShapeEdgeSegment:有邊的線段。PhysicsShapeEdgeBox:有邊的矩形盒子。PhysicsShapeEdgePolygon:有邊的多邊形。PhysicsShapeEdgeChain:有邊的鏈形。
碰撞檢測監聽類EventListenerPhysicsShapeContact,子類如下: EventListenerPhysicsContact中碰撞檢測事件響應屬性:
std::function<bool(PhysicsContact & contact)>onContactBegin
:兩個物體開始接觸時會響應,但只調用一次。返回false情況下后面的兩個屬性(onContactPReSolve 和 onContactPostSolve)所指定的函數,不調用。std::function<bool(PhysicsContact & contact, PhysicsContactPreSolve & solve)>onContactPreSolve
:持續接觸時響應,它會被多次調用。返回false情況下后面的onContactPostSolve屬性所指定的函數,不調用。std::function<void(PhysicsContact & contact, const PhysicsContactPostSolve & solve)>onContactPostSolve
:持續接觸時響應,調用完PreSolve后調用。std::function<void(PhysicsContact & contact)>onContactSeparate
:分離時響應,但只調用一次。關節類PhysicsJoint是一個抽象類,其子類如下: PhysicsJointDistance類是距離關節類,兩個物體上面各自有一點,兩點之間的距離必須固定不變。創建PhysicsJointDistace的靜態函數定義如下:
static PhysicsJointDistance * construct ( PhysicsBody * a, PhysicsBody * b, const Vec2 & anchr1, const Vec2 & anchr2)其中參數a和b是兩個互相約束的物體,anchr1是連接a物體的錨點,anchr2是b物體的錨點。
實例
小球
HelloWorld.h文件
#ifndef __HELLOWORLD_SCENE_H__#define __HELLOWORLD_SCENE_H__#include "cocos2d.h"USING_NS_CC;class HelloWorld : public cocos2d::Layer{public: static cocos2d::Scene* createScene(); virtual bool init(); virtual bool onTouchBegan(cocos2d::Touch * touch, cocos2d::Event * event); void addNewSpriteAtPosition(Vec2 p); // implement the "static create()" method manually CREATE_FUNC(HelloWorld);};#endif // __HELLOWORLD_SCENE_H__HelloWorld.cpp文件
#include "HelloWorldScene.h"USING_NS_CC;Scene* HelloWorld::createScene(){ // 'scene' is an autorelease object auto scene = Scene::createWithPhysics();//創建帶物理引擎的場景 scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);//設置在物理世界中調試遮罩,當調試結束時,需要把它關閉 // 'layer' is an autorelease object auto layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene;}// on "init" you need to initialize your instancebool HelloWorld::init(){ ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } log("HelloWorld init"); Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); //定義世界的邊界 //創建物體對象,靜態函數createEdgeBox指定世界邊界是矩形盒子,第一個參數指定矩形的大小,第二個參數是設置材質,第三個參數是設置邊的寬度 auto body = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 5.0f); auto edgeNode = Node::create();//創建邊界節點對象,這個節點對象作為世界邊界的對象 edgeNode->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2)); edgeNode->setPhysicsBody(body);//設置與節點相關的物體對象 this->addChild(edgeNode); setTouchEnabled(true); //設置為單點觸摸 setTouchMode(Touch::DispatchMode::ONE_BY_ONE); return true;}bool HelloWorld::onTouchBegan(Touch * touch, Event * event){ Vec2 location = touch->getLocation(); addNewSpriteAtPosition(location); return false;}void HelloWorld::addNewSpriteAtPosition(Vec2 p){ auto sp = Sprite::create("Ball.png"); sp->setTag(1); auto body = PhysicsBody::createCircle(sp->getContentSize().width / 2);//創建圓圈形狀物體 sp->setPhysicsBody(body); sp->setPosition(p); this->addChild(sp);}
新聞熱點
疑難解答