这里讲两个Box2d物理引擎的例子,一个新的cocos2d3.x版本,另一个是旧的2.x版。
关于Box2d的基础知识,这里不再详述,详细参考:http://www.jb51.cc/article/p-xtkktxxp-gy.html
新版本:
HelloNewBox2d.h:
#ifndef __HELLONEWBox2D_H__#define __HELLONEWBox2D_H__#include "cocos2d.h"#include "Box2D\Box2D.h"using namespace cocos2d;class HelloNewBox2d : public Layer{private: CCTexture2D* _spriteTexture;public: HelloNewBox2d(); ~HelloNewBox2d(); // there's no 'ID' in cpp,so we recommend returning the class instance pointer static Scene* createNewBox2dScene(); // Here's a difference. Method 'init' in cocos2d-x returns bool,instead of returning 'ID' in cocos2d-iphone virtual bool init(); // implement the "static create()" method manually CREATE_FUNC(HelloNewBox2d); // 初始化物理引擎设置 voID initSprite(); virtual bool ontouchBegan(cocos2d::touch* touch,cocos2d::Event* event); voID onacceleration(acceleration* acc,Event* event); // 在指定位置添加精灵 voID addNewSpriteAtposition(Vec2 p);};#endif // __HELLOWORLD_SCENE_H__
HelloNewBox2d.cpp:
#include "HelloNewBox2d.h"USING_NS_CC;#define SCENERATIO 480/1024Scene* HelloNewBox2d::createNewBox2dScene(){ auto Box2dScene = Scene::create(); // 初始化物理引擎 Box2dScene->initWithPhysics(); auto Box2dLayer = HelloNewBox2d::create(); Box2dScene->addChild(Box2dLayer); return Box2dScene;}HelloNewBox2d::HelloNewBox2d() :_spriteTexture(NulL){}HelloNewBox2d::~HelloNewBox2d(){ // 关闭重力感应 Device::setAccelerometerEnabled(false);}bool HelloNewBox2d::init(){ if (!Layer::init()) { return false; } // 初始化物理引擎 this->initSprite(); settouchEnabled(true); return true;}voID HelloNewBox2d::initSprite(){ // 获取精灵纹理缓存 _spriteTexture = Sprite::create("blocks.png")->getTexture(); // 设置添加多点触控监听 auto touchListener = EventListenertouchOneByOne::create(); touchListener->ontouchBegan = CC_CALLBACK_2(HelloNewBox2d::ontouchBegan,this); _eventdispatcher->addEventListenerWithSceneGraPHPriority(touchListener,this); // 打开设备重力感应 Device::setAccelerometerEnabled(true); // 设置重力感应监听 auto accListener = EventListeneracceleration::create( CC_CALLBACK_2(HelloNewBox2d::onacceleration,this)); _eventdispatcher->addEventListenerWithSceneGraPHPriority(accListener,this); // 获得OpenGL可见区域的矩形(一般大小为窗口屏幕的大小) Rect s_visibleRect = Director::getInstance()->getopenGLVIEw()->getVisibleRect(); // 可见区域的中心点(窗口屏幕中心点) Vec2 vec = Vec2(s_visibleRect.origin.x + s_visibleRect.size.wIDth / 2,s_visibleRect.origin.y + s_visibleRect.size.height / 2); // 创建节点 auto node = Node::create(); // 设置刚体,且为边框属性 node->setPhysicsBody(PhysicsBody::createEdgeBox(s_visibleRect.size)); node->setposition(vec); this->addChild(node);}voID HelloNewBox2d::addNewSpriteAtposition(Vec2 p){ // 产生0和1的随机数 int IDx = CCRANDOM_0_1() > .5f ? 0 : 1; int IDy = CCRANDOM_0_1() > .5f ? 0 : 1; // 从缓存中获取精灵,并设置添加刚体(考虑屏幕适应性问题) auto sp = Sprite::createWithTexture(_spriteTexture,Rect(IDx*32.0f*SCENERATIO,IDy*32.0f*SCENERATIO,32.0f*SCENERATIO,32.0f*SCENERATIO)); sp->setPhysicsBody(PhysicsBody::createBox(Size(32.0f*SCENERATIO,32.0f*SCENERATIO))); this->addChild(sp); sp->setposition(p);}bool HelloNewBox2d::ontouchBegan(touch* touch,Event* event){ auto location = touch->getLocation(); // 添加新的精灵 addNewSpriteAtposition(location); return true;}voID HelloNewBox2d::onacceleration(acceleration* acc,Event* event){ static float prevX = 0,prevY = 0;#define kFilterFactor 0.05f float accelX = (float)acc->x * kFilterFactor + (1 - kFilterFactor)*prevX; float accelY = (float)acc->y * kFilterFactor + (1 - kFilterFactor)*prevY; prevX = accelX; prevY = accelY; auto v = Vec2(accelX,accelY); v = v * 200; // 设置物理世界的重力 this->getScene()->getPhysicsWorld()->setGravity(v);}
旧版本:
HelloBox2d.h:
#ifndef __HELLOBox2D_H__#define __HELLOBox2D_H__#include "cocos2d.h"#include "Box2D\Box2D.h"using namespace cocos2d;class HelloBox2d : public Layer{private: // 世界,可看做游戏世界 b2World* _world; CCTexture2D* _spriteTexture;public: HelloBox2d(); ~HelloBox2d(); // there's no 'ID' in cpp,so we recommend returning the class instance pointer static Scene* createBox2dScene(); // Here's a difference. Method 'init' in cocos2d-x returns bool,instead of returning 'ID' in cocos2d-iphone virtual bool init(); // implement the "static create()" method manually CREATE_FUNC(HelloBox2d); voID setSpriteTexture(); // 初始化物理引擎设置 voID initPhysics(); // 根据传入的数值进行更新 virtual voID update(float dt); virtual bool ontouchBegan(cocos2d::touch* touch,cocos2d::Event* event); // 在指定位置添加精灵 voID addNewSpriteAtposition(cocos2d::Vec2 p);};#endif // __HELLOWORLD_SCENE_H__
HelloBox2d.cpp:
#include "HelloBox2d.h"USING_NS_CC;#define PTM_RATIO 32Scene* HelloBox2d::createBox2dScene(){ auto Box2dScene = Scene::create(); auto Box2dLayer = HelloBox2d::create(); Box2dScene->addChild(Box2dLayer); return Box2dScene;}HelloBox2d::HelloBox2d():_world(NulL){}HelloBox2d::~HelloBox2d(){ CC_SAFE_DELETE(_world);}bool HelloBox2d::init(){ if (!Layer::init()) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); // 初始化物理引擎,并创建世界边界 this->initPhysics(); settouchEnabled(true); // 设置为单点触摸 settouchMode(touch::dispatchMode::ONE_BY_ONE); // 利用时间调度器开始循环 scheduleUpdate(); return true;}voID HelloBox2d::initPhysics(){ Size s = Director::getInstance()->getVisibleSize(); // 重力参数,参数:1、水平方向,正值,重力向左;1、竖直方向,正值,重力向上 b2Vec2 gravity; gravity.Set(0.0f,-10.0f); // 创建重力世界 _world = new b2World(gravity); // 允许物体是否休眠 _world->SetAllowSleePing(true); // 开启连续物理测试,防止物体会穿过另一个物体 _world->SetContinuousPhysics(true); // 刚体,地面物体定义 b2BodyDef groundBodyDef; // 左下角 groundBodyDef.position.Set(0,0); // 创建刚体,地面物体 b2Body* groundBody = _world->CreateBody(&groundBodyDef); // 定义一个有边的形状,连接起来,可看做一个盒子 b2EdgeShape groundBox; // 底部 groundBox.Set(b2Vec2(0,0),b2Vec2(s.wIDth / PTM_RATIO,0)); // 使用夹具固定形状到物体上 groundBody->CreateFixture(&groundBox,0); // 顶部 groundBox.Set(b2Vec2(0,s.height / PTM_RATIO),s.height / PTM_RATIO)); groundBody->CreateFixture(&groundBox,0); // 左边 groundBox.Set(b2Vec2(0,b2Vec2(0,0)); groundBody->CreateFixture(&groundBox,0); // 右边 groundBox.Set(b2Vec2(s.wIDth / PTM_RATIO,0)); groundBody->CreateFixture(&groundBox,0);}voID HelloBox2d::addNewSpriteAtposition(Vec2 p){ // 创建物理引擎精灵对象 auto sprite = Sprite::create("blocks.png"); sprite->setposition(Vec2(p.x,p.y)); this->addChild(sprite); // 物体定义 b2BodyDef bodyDef; // 定义动态刚体类型 bodyDef.type = b2_dynamicBody; bodyDef.position.Set(p.x / PTM_RATIO,p.y / PTM_RATIO); // 创建刚体 b2Body *body = _world->CreateBody(&bodyDef); // 设置用户数据,辨别和调用创建好的刚体 body->SetUserData(sprite); // 定义2米见方的盒子形状 b2polygonShape dynamicBox; dynamicBox.SetAsBox(.5f,.5f); // 夹具定义 b2FixtureDef fixtureDef; //设置夹具的形状 fixtureDef.shape = &dynamicBox; //设置密度 fixtureDef.density = 1.0f; //设置摩擦系数 fixtureDef.friction = 0.3f; //使用夹具固定形状到物体上 body->CreateFixture(&fixtureDef);}voID HelloBox2d::update(float dt){ float timestep = 0.03f; int32 veLocityIterations = 8; int32 positionIterations = 1; // 引擎自己检查节点位置和速率,进行实时更新 _world->Step(timestep,veLocityIterations,positionIterations); // 遍历世界中创建的刚体,不断更新刚体,即盒子的角度和位置 for (b2Body* b = _world->GetbodyList(); b; b = b->GetNext()) { if (b->GetUserData() != nullptr) { Sprite* sprite = (Sprite*)b->GetUserData(); sprite->setposition(Vec2(b->Getposition().x * PTM_RATIO,b->Getposition().y * PTM_RATIO)); sprite->setRotation(-1 * CC_radians_TO_degrees(b->GetAngle())); } }}bool HelloBox2d::ontouchBegan(cocos2d::touch* touch,cocos2d::Event* event){ auto loc = touch->getLocation(); addNewSpriteAtposition(loc); return true;}
效果图:
这里是源代码,由于文件过于庞大,只上传代码部分,复制覆盖项目即可,运行时,在AppDelegate.cpp文件中修改运用的场景即可,两个例子实现的功能一致。
auto Box2dscene = HelloBox2d::createBox2dScene();auto newBox2dscene = HelloNewBox2d::createNewBox2dScene();// rundirector->runWithScene(newBox2dscene);下载地址:http://download.csdn.net/detail/u013707014/9016823
HelloBox2d.cpp: 总结
以上是内存溢出为你收集整理的Cocos2d-x学习笔记(十二)—— Box2d物理引擎(未完)全部内容,希望文章能够帮你解决Cocos2d-x学习笔记(十二)—— Box2d物理引擎(未完)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)