Cocos2d-x Box2d札记: 愤怒的小鸟demo 弹弓和轨迹实现
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.0 using 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 instance bool HelloWorld::init() { bool bRet = false; do { ////////////////////////////////////////////////////////////////////////// // super init first ////////////////////////////////////////////////////////////////////////// CC_BREAK_IF(! CCLayer::init()); CCSize winSize=CCDirector::sharedDirector()->getWinSize(); //create bg CCSprite *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 source batch=CCSpriteBatchNode::create("bird2.png"); this->addChild(batch); CCTexture2D *batchTexture=batch->getTexture(); //init slingshot CCSprite*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 bird bird=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 world b2Vec2 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); // bottom groundBox.Set(b2Vec2(0,slingshot2->getPositionY()/PTM_RATIO/2.1), b2Vec2(s.width/PTM_RATIO,slingshot2->getPositionY()/PTM_RATIO/2.1)); groundBody->CreateFixture(&groundBox,0); // top groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO)); groundBody->CreateFixture(&groundBox,0); // left groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(0,0)); groundBody->CreateFixture(&groundBox,0); // right groundBox.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); //init r=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 body b2CircleShape 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 body myActor->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 route CCSprite *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 line if(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() ); } }
资源图在这: