物理引擎能够模仿真实世界物理运动规律,使得精灵做出自由落体、抛物线运动、互相碰撞、反弹等效果,使用物理引擎还可以进行准确的碰撞检测。
物理引擎本身不包括精灵,它与精灵关系之间是相互独立的,精灵不会自动跟着物理引擎中的物体做物理运动,通常需要编写代码将物体与精灵连接起来,同步它们的状态。
在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);}
新闻热点
疑难解答