Cocos2d-x Box2d笔记: 愤怒的小鸟demo 弹弓和轨迹实现
先上图,源码不多,直接上
#ifndef __HELLOWORLD_SCENE_H__#define __HELLOWORLD_SCENE_H__#include "cocos2d.h"#include "GLES-Render.h"#include "Box2D/Box2D.h"using namespace cocos2d;class HelloWorld : public cocos2d::CCLayer{public: // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone virtual bool init(); // there's no 'id' in cpp, so we recommand to return the exactly class pointer static cocos2d::CCScene* scene();virtual void draw();virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent);virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent); void update(float dt);public:b2Body *groundBody;b2World *world;CCSpriteBatchNode *batch;CCSprite *bird;CCPoint center,currentPoint;float ratio;int r,canFly; LAYER_CREATE_FUNC(HelloWorld);};#endif // __HELLOWORLD_SCENE_H__
#include "HelloWorldScene.h"#define PTM_RATIO 32.0using namespace cocos2d;CCScene* HelloWorld::scene(){ CCScene * scene = NULL; do { // 'scene' is an autorelease object scene = CCScene::create(); CC_BREAK_IF(! scene); // 'layer' is an autorelease object HelloWorld *layer = HelloWorld::create(); CC_BREAK_IF(! layer); // add layer as a child to scene scene->addChild(layer); } while (0); // return the scene return scene;}// on "init" you need to initialize your instancebool HelloWorld::init(){ bool bRet = false; do { ////////////////////////////////////////////////////////////////////////// // super init first ////////////////////////////////////////////////////////////////////////// CC_BREAK_IF(! CCLayer::init());CCSize winSize=CCDirector::sharedDirector()->getWinSize();//create bgCCSprite *bg=CCSprite::create("bg.png");ratio=winSize.height/bg->getContentSize().height;bg->setAnchorPoint(ccp(0,0));bg->setPosition(ccp(0,0));bg->setScaleY(ratio);this->addChild(bg,-2);//load sourcebatch=CCSpriteBatchNode::create("bird2.png");this->addChild(batch);CCTexture2D *batchTexture=batch->getTexture();//init slingshotCCSprite*slingshot1=CCSprite::create(batchTexture,CCRectMake(1,1,38,199));slingshot1->setScale(ratio*0.7);slingshot1->setPosition(ccp(90,ratio*130));batch->addChild(slingshot1);CCSprite*slingshot2=CCSprite::create(batchTexture,CCRectMake(833,1,43,124));slingshot2->setScale(ratio*0.7);slingshot2->setPosition(ccp(78,ratio*155));batch->addChild(slingshot2);//init birdbird=CCSprite::create(batchTexture,CCRectMake(1,379,31,30));bird->setScale(ratio);bird->setPosition(ccp((slingshot1->getPositionX()+slingshot2->getPositionX())/2,slingshot1->getPositionY()*1.4));center=bird->getPosition();this->addChild(bird);//define the worldb2Vec2 gravity;gravity.Set(0.0f, -10.0f);world = new b2World(gravity);// Do we want to let bodies sleep?world->SetAllowSleeping(true);world->SetContinuousPhysics(true);// Define the ground body.b2BodyDef groundBodyDef;groundBodyDef.position.Set(0, 0); // bottom-left corner// Call the body factory which allocates memory for the ground body// from a pool and creates the ground box shape (also from a pool).// The body is also added to the world.b2Body* groundBody = world->CreateBody(&groundBodyDef);// Define the ground box shape.b2EdgeShape groundBox;CCSize s=CCSize(bg->getContentSize().width,bg->getContentSize().height*ratio);// bottomgroundBox.Set(b2Vec2(0,slingshot2->getPositionY()/PTM_RATIO/2.1), b2Vec2(s.width/PTM_RATIO,slingshot2->getPositionY()/PTM_RATIO/2.1));groundBody->CreateFixture(&groundBox,0);// topgroundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO));groundBody->CreateFixture(&groundBox,0);// leftgroundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(0,0));groundBody->CreateFixture(&groundBox,0);// rightgroundBox.Set(b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,0));groundBody->CreateFixture(&groundBox,0);GLESDebugDraw*m_debugDraw = new GLESDebugDraw( PTM_RATIO );world->SetDebugDraw(m_debugDraw);uint32 flags = 0;//flags += b2Draw::e_shapeBit;//flags += b2Draw::e_jointBit;//flags += b2Draw::e_aabbBit; // flags += b2Draw::e_pairBit; // flags += b2Draw::e_centerOfMassBit;m_debugDraw->SetFlags(flags);//initr=60;//活动范围canFly=0;setTouchEnabled(true);scheduleUpdate();this->runAction(CCFollow::create(bird,CCRectMake(0,0,bg->getContentSize().width,bg->getContentSize().height*ratio))); bRet = true; } while (0); return bRet;}void HelloWorld::ccTouchesBegan(CCSet *touches, CCEvent *pEvent){}void HelloWorld::ccTouchesMoved(CCSet *touches, CCEvent *pEvent){CCTouch *touch=(CCTouch*)touches->anyObject();CCPoint pt1=touch->locationInView();pt1=CCDirector::sharedDirector()->convertToGL(pt1);CCSize s=CCDirector::sharedDirector()->getWinSize();if(CCRect::CCRectContainsPoint(bird->boundingBox(),pt1)==false)return;canFly=1;float distance=ccpDistance(pt1,center);if(distance>r){CCPoint pos;float cos=(pt1.x-center.x)/distance,sin=(pt1.y-center.y)/distance;pos.x=center.x+r*cos;pos.y=center.y+r*sin;bird->setPosition(pos);}else{bird->setPosition(pt1);}}void HelloWorld::ccTouchesEnded(CCSet *touches, CCEvent *pEvent){CCTouch *touch=(CCTouch*)touches->anyObject();CCPoint pt1=touch->locationInView();pt1=CCDirector::sharedDirector()->convertToGL(pt1);if(canFly==0){return;}else{canFly=0;}float distance=ccpDistance(pt1,center);float cos=(pt1.x-center.x)/distance,sin=(pt1.y-center.y)/distance;//add box2d bodyb2CircleShape birdShape;birdShape.m_radius=ratio*bird->getContentSize().width/PTM_RATIO/2;//CCLOG("%f",birdShape.m_radius);b2FixtureDef birdFixtureDef;birdFixtureDef.shape=&birdShape;birdFixtureDef.density=1;birdFixtureDef.friction=0.3;birdFixtureDef.restitution=0.1;b2BodyDef birdBodyDef;birdBodyDef.type=b2_dynamicBody;birdBodyDef.position.Set(bird->getPositionX()/PTM_RATIO,bird->getPositionY()/PTM_RATIO);b2Body *birdBody=world->CreateBody(&birdBodyDef);birdBody->SetUserData(bird);birdBody->CreateFixture(&birdFixtureDef);birdBody->ApplyForce(b2Vec2(-5.5f*distance*cos,-5.5f*distance*sin),birdBody->GetWorldCenter());birdBody->SetLinearDamping(0.2f);}void HelloWorld::update(float dt){int32 velocityIterations = 8;int32 positionIterations = 8;// Instruct the world to perform a single step of simulation.world->Step(dt, velocityIterations, positionIterations);for (b2Body* b = world->GetBodyList(); b; b = b->GetNext()){CCSprite *myActor = (CCSprite*)b->GetUserData();if (myActor){//Synchronize the AtlasSprites position and rotation with the corresponding bodymyActor->setPosition(CCPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO));myActor->setRotation(-1 * CC_RADIANS_TO_DEGREES(b->GetAngle()));}}//CCLOG("%f",dt);static float countTime=0.0f;countTime+=dt;if((countTime>0.08f)&&(bird->getPositionX()>center.x+r)&&(bird->getPositionY()>center.y)){countTime=0;//show the routeCCSprite *route=CCSprite::create(batch->getTexture(),CCRectMake(0,345,35,33));route->setScale(0.4*ratio);batch->addChild(route);route->setPosition(bird->getPosition());}}void HelloWorld::draw(){//// IMPORTANT:// This is only for debug purposes// It is recommend to disable it//CCLayer::draw();ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );kmGLPushMatrix();glLineWidth(3.0f);world->DrawDebugData();kmGLPopMatrix();//draw lineif(canFly==1){CHECK_GL_ERROR_DEBUG();// line: color, width, aliased// glLineWidth > 1 and GL_LINE_SMOOTH are not compatible// GL_SMOOTH_LINE_WIDTH_RANGE = (1,1) on iPhone// glDisable(GL_LINE_SMOOTH);glLineWidth( 4.0f );ccDrawColor4B(0,0,0,255);ccDrawLine( ccpAdd(center,ccp(bird->getContentSize().width/3,0)), bird->getPosition() );ccDrawLine( ccpAdd(center,ccp(-bird->getContentSize().width/3,0)), bird->getPosition() );}}
资源图在这: