个人原创,欢迎转载http://blog.csdn.net/dawn_moon/article/details/20466245
天天飞翔,物理特性用了box2d来做的。关于box2d的入门教程网上有很多,推荐官方手册,中文版,地址。我不再做重复介绍,稍微写点自己理解的东西。
cocos2d-x可以和box2d的C++版完美融合,集成起来很方便。
#include "Box2D.h"
#include "Box2D/Box2D.h"
开启box2d的debug渲染
一般为了方便调试box2d,会将物理世界的物体绘制出来,官方有debug draw,cocos2dx里面有个debug的工具类GLESDebugDraw,在test工程里面,文件名GLES-Render.h,加入进来。
步骤如下:
1。需要有个box2d的物理世界b2World,一个debug渲染器,GLESDebugDraw。demo如下:
// // TestBox.h // TestBox2d // // Created by lerry on 14-3-4. // Copyright (c) 2014年 GoonearTechnology Co.,Ltd. All rights reserved. // #ifndef __TestBox2d__TestBox__ #define __TestBox2d__TestBox__ #include "cocos2d.h" #include "Box2D.h" #include "GLES-Render.h" #define RATIO 96 class TestBox : public cocos2d::CCLayer { cocos2d::CCSprite* role; b2World* mWorld; GLESDebugDraw* mDebugDraw; cocos2d::CCSize visualSize; private: void draw(); void drawBox(); public: ~TestBox(); virtual void update(float dt); virtual bool init(); virtual void onEnter(); virtual void onExit(); virtual bool ccTouchBegan(cocos2d::CCTouch* touch, cocos2d::CCEvent* event); virtual void ccTouchMoved(cocos2d::CCTouch* touch, cocos2d::CCEvent* event); virtual void ccTouchEnded(cocos2d::CCTouch* touch, cocos2d::CCEvent* event); void initWorld(); void setDebug(bool isDebug); static cocos2d::CCScene* scene(); CREATE_FUNC(TestBox); }; #endif /* defined(__TestBox2d__TestBox__) */
void TestBox::initWorld() { mWorld = new b2World(b2Vec2(0, -10)); mWorld->SetAllowSleeping(true); mWorld->SetContinuousPhysics(true); setDebug(true); }3。如果开启debug模式,启用debug绘制
void TestBox::setDebug(bool isDebug) { if (isDebug) { mDebugDraw = new GLESDebugDraw(RATIO); mWorld->SetDebugDraw(mDebugDraw); uint32 flags = 0; flags += b2Draw::e_shapeBit; flags += b2Draw::e_jointBit; flags += b2Draw::e_pairBit; flags += b2Draw::e_centerOfMassBit; mDebugDraw->SetFlags(flags); draw(); } } void TestBox::draw() { ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); kmGLPushMatrix(); mWorld->DrawDebugData(); kmGLPopMatrix(); }4.init里面初始化世界,调用update函数即可。
代码如下:
// // TestBox.cpp // TestBox2d // // Created by lerry on 14-3-4. // Copyright (c) 2014年 GoonearTechnology Co.,Ltd. All rights reserved. // #include "TestBox.h" USING_NS_CC; TestBox::~TestBox() { delete mWorld; mWorld = NULL; delete mDebugDraw; mDebugDraw = NULL; } CCScene* TestBox::scene() { CCScene* s = CCScene::create(); TestBox* test = TestBox::create(); s->addChild(test); return s; } bool TestBox::init() { if(!CCLayer::init()) { return false; } visualSize = CCDirector::sharedDirector()->getVisibleSize(); initWorld(); drawBox(); scheduleUpdate(); return true; } void TestBox::update(float dt) { int velocityIterat = 8; int positionIterat = 1; mWorld->Step(dt, velocityIterat, positionIterat); for(b2Body *b=mWorld->GetBodyList(); b; b=b->GetNext()) { if(b->GetUserData()!=NULL) { CCSprite *sprite=(CCSprite*)b->GetUserData(); sprite->setPosition(ccp(b->GetPosition().x*RATIO,b->GetPosition().y*RATIO)); sprite->setRotation((-1)*CC_RADIANS_TO_DEGREES(b->GetAngle())); } } } void TestBox::drawBox() { { // 地板 b2Body* ground = NULL; b2BodyDef bd; ground = mWorld->CreateBody(&bd); // 底边 b2EdgeShape shape; shape.Set(b2Vec2(0.1f, 0.1f), b2Vec2(visualSize.width / RATIO - 0.1f, 0.1f)); ground->CreateFixture(&shape, 0.0f); shape.Set(b2Vec2(0.1f, 0.1f), b2Vec2(0.1f, visualSize.height / RATIO - 0.1f)); ground->CreateFixture(&shape, 0.0f); shape.Set(b2Vec2(0.1f, visualSize.height / RATIO - 0.1f), b2Vec2(visualSize.width / RATIO - 0.1f, visualSize.height / RATIO - 0.1f)); ground->CreateFixture(&shape, 0.0f); shape.Set(b2Vec2(visualSize.width / RATIO - 0.1f, 0.1f), b2Vec2(visualSize.width / RATIO - 0.1f, visualSize.height / RATIO - 0.1f)); ground->CreateFixture(&shape, 0.0f); } { role = CCSprite::create("poop_1.png"); CCSize size = role->getContentSize(); role->setPosition(ccp(visualSize.width / 2, visualSize.height / 2)); b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; bodyDef.userData = role; bodyDef.position.Set(visualSize.width / 2 / RATIO, visualSize.height / 2 / RATIO); b2Body* body = mWorld->CreateBody(&bodyDef); b2PolygonShape shape; shape.SetAsBox(size.width / 2 / RATIO, size.height / 2 / RATIO); b2FixtureDef fixDef; fixDef.shape = &shape; body->CreateFixture(&fixDef); addChild(role); } } void TestBox::initWorld() { mWorld = new b2World(b2Vec2(0, -10)); mWorld->SetAllowSleeping(true); mWorld->SetContinuousPhysics(true); setDebug(true); } void TestBox::setDebug(bool isDebug) { if (isDebug) { mDebugDraw = new GLESDebugDraw(RATIO); mWorld->SetDebugDraw(mDebugDraw); uint32 flags = 0; flags += b2Draw::e_shapeBit; flags += b2Draw::e_jointBit; flags += b2Draw::e_pairBit; flags += b2Draw::e_centerOfMassBit; mDebugDraw->SetFlags(flags); draw(); } } void TestBox::draw() { ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); kmGLPushMatrix(); mWorld->DrawDebugData(); kmGLPopMatrix(); } bool TestBox::ccTouchBegan(cocos2d::CCTouch *touch, cocos2d::CCEvent *event) { CCLog("touch"); return true; } void TestBox::ccTouchMoved(cocos2d::CCTouch *touch, cocos2d::CCEvent *event) { } void TestBox::ccTouchEnded(cocos2d::CCTouch *touch, cocos2d::CCEvent *event) { } void TestBox::onEnter() { CCDirector* pDirector = CCDirector::sharedDirector(); pDirector->getTouchDispatcher()->addTargetedDelegate(this, 0, true); CCLayer::onEnter(); } void TestBox::onExit() { CCDirector* pDirector = CCDirector::sharedDirector(); pDirector->getTouchDispatcher()->removeDelegate(this); CCLayer::onExit(); }