cocs2d-x 学习例子 box2d 实现类似愤怒的小鸟的简单参考例子

来源:互联网 发布:js面向对象实现过程 编辑:程序博客网 时间:2024/05/16 07:15

首先贴出最初的出处:http://www.raywenderlich.com/4756/how-to-make-a-catapult-shooting-game-with-cocos2d-and-box2d-part-1

再贴出我主要参考的贴:http://mssyy2010.blog.51cto.com/4595971/847000

然后是我稍加调整后可以在cocos2d-2.14编译运行的代码(整个vs project包括resources):https://github.com/serika00/android/tree/master/cocos2d-x/CatapultShootingGame


再顺手把代码贴上,原来两个出处解释得都比较清楚了,不多加解释。


HelloWorld.h

#ifndef __HELLOWORLD_SCENE_H__#define __HELLOWORLD_SCENE_H__#include "cocos2d.h"#include "Box2D/Box2D.h"#include "MyContactListener.h"USING_NS_CC;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 recommend returning the class instance pointer    static cocos2d::CCScene* scene();        // a selector callback    void menuCloseCallback(CCObject* pSender);        // implement the "static node()" method manually    CREATE_FUNC(HelloWorld);HelloWorld() {};~HelloWorld();void tick(float dt);void ccTouchesBegan(CCSet* pTouches, CCEvent* pEvent);void ccTouchesMoved(CCSet* pTouches, CCEvent* pEvent);void ccTouchesEnded(CCSet* pTouches, CCEvent* pEvent);void createBullets(int count);bool attachBullet();void resetGame();void createTarget(char   *imageName,  CCPoint position,  float   rotation,  bool  isCircle,  bool    isStatic,  bool    isEnemy);void createTargets();void resetBullet();private:b2World* m_world;b2Body* m_groundBody;b2RevoluteJoint *m_armJoint;b2MouseJoint *m_mouseJoint;b2Fixture* m_armFixture;b2Body* m_armBody;std::vector<b2Body*> m_bullets;int m_currentBullet;b2Body* m_bulletBody;b2WeldJoint* m_bulletJoint;bool m_releasingArm;vector<b2Body*> *targets;vector<b2Body*> *enemies;MyContactListener* contactListener;};#endif // __HELLOWORLD_SCENE_H__


HelloWorld.cpp

#include "HelloWorldScene.h"#define PTM_RATIO 32#define FLOOR_HEIGHT 62.0fUSING_NS_CC;CCScene* HelloWorld::scene(){    // 'scene' is an autorelease object    CCScene *scene = CCScene::create();        // 'layer' is an autorelease object    HelloWorld *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 firsttargets = new vector<b2Body*>;enemies = new vector<b2Body*>;    CCSprite* sprite1 = CCSprite::create("bg.png");sprite1->setAnchorPoint(CCPointZero);addChild(sprite1, -1);CCSprite* sprite2 = CCSprite::create("catapult_base_2.png");sprite2->setAnchorPoint(CCPointZero);sprite2->setPosition(CCPointMake(181.0, FLOOR_HEIGHT));addChild(sprite2, 0);CCSprite* sprite3 = CCSprite::create("squirrel_1.png");sprite3->setAnchorPoint(CCPointZero);sprite3->setPosition(CCPointMake(11.0, FLOOR_HEIGHT));addChild(sprite3, 0);CCSprite* sprite4 = CCSprite::create("catapult_base_1.png");sprite4->setAnchorPoint(CCPointZero);sprite4->setPosition(CCPointMake(181.0, FLOOR_HEIGHT));addChild(sprite4, 9);CCSprite* sprite5 = CCSprite::create("squirrel_2.png");sprite5->setAnchorPoint(CCPointZero);sprite5->setPosition(CCPointMake(240.0, FLOOR_HEIGHT));addChild(sprite5, 9);CCSprite* sprite6 = CCSprite::create("fg.png");sprite6->setAnchorPoint(CCPointZero);addChild(sprite6, 10);b2Vec2 gravity;gravity.Set(0.0f, -10.0f);m_world = new b2World(gravity);m_world->SetAllowSleeping(true);m_world->SetContinuousPhysics(true);b2BodyDef groundBodyDef;groundBodyDef.position.Set(0, 0);m_groundBody = m_world->CreateBody(&groundBodyDef);b2EdgeShape groundBox;CCSize screenSize = CCDirector::sharedDirector()->getWinSize(); groundBox.Set(b2Vec2(0,FLOOR_HEIGHT/PTM_RATIO), b2Vec2(screenSize.width*2.0f/PTM_RATIO,FLOOR_HEIGHT/PTM_RATIO));     m_groundBody->CreateFixture(&groundBox, 0);          // top     groundBox.Set(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width*2.0f/PTM_RATIO,screenSize.height/PTM_RATIO));     m_groundBody->CreateFixture(&groundBox, 0);          // left     groundBox.Set(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(0,0));     m_groundBody->CreateFixture(&groundBox, 0);          // right //    groundBox.Set(b2Vec2(screenSize.width*1.5f/PTM_RATIO,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width*1.5f/PTM_RATIO,0)); //    m_groundBody->CreateFixture(&groundBox, 0);     CCSprite *arm = CCSprite::create("catapult_arm.png");addChild(arm, 1);b2BodyDef armBodyDef;armBodyDef.type = b2_dynamicBody;armBodyDef.linearDamping = 1;armBodyDef.angularDamping = 1;armBodyDef.position.Set(230.0f/PTM_RATIO, (FLOOR_HEIGHT+91.0f)/PTM_RATIO);armBodyDef.userData = arm;m_armBody = m_world->CreateBody(&armBodyDef);b2PolygonShape armBox;b2FixtureDef armBoxDef;armBoxDef.shape = &armBox;armBoxDef.density = 0.3f;armBox.SetAsBox(11.0f/PTM_RATIO, 91.0f/PTM_RATIO);m_armFixture = m_armBody->CreateFixture(&armBoxDef);b2RevoluteJointDef armJointDef;armJointDef.Initialize(m_groundBody, m_armBody,b2Vec2(233.0f / PTM_RATIO, 50/PTM_RATIO));armJointDef.enableMotor = true;armJointDef.enableLimit = true;armJointDef.motorSpeed = -10;armJointDef.lowerAngle = CC_DEGREES_TO_RADIANS(9);armJointDef.upperAngle = CC_DEGREES_TO_RADIANS(75);armJointDef.maxMotorTorque = 700;m_armJoint = (b2RevoluteJoint*) m_world->CreateJoint(&armJointDef);m_mouseJoint = NULL;resetGame();m_releasingArm = false;createTargets();contactListener = new MyContactListener();m_world->SetContactListener(contactListener);setTouchEnabled(true);schedule(schedule_selector(HelloWorld::tick));    return true;}void HelloWorld::menuCloseCallback(CCObject* pSender){    CCDirector::sharedDirector()->end();#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)    exit(0);#endif}void HelloWorld::tick(float dt) {int velocityIterations = 8;int positionIterations = 1;m_world->Step(dt, velocityIterations, positionIterations);for (b2Body* b = m_world->GetBodyList(); b; b = b->GetNext()) {if (b->GetUserData() != NULL) {CCSprite* sprite = (CCSprite*)(b->GetUserData());sprite->setPosition(ccp(b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO));sprite->setRotation( -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()));}}if (m_releasingArm && m_bulletJoint != NULL) {if (m_armJoint->GetJointAngle() <= CC_DEGREES_TO_RADIANS(10)) {m_releasingArm = false;m_world->DestroyJoint(m_bulletJoint);m_bulletJoint = NULL;CCDelayTime* delayAction = CCDelayTime::create(5.0f);CCCallFunc* callSelectorAction = CCCallFunc::create(this, callfunc_selector(HelloWorld::resetBullet));this->runAction(CCSequence::create(delayAction, callSelectorAction, NULL));}}if (m_bulletBody && m_bulletJoint == NULL) {b2Vec2 position = m_bulletBody->GetPosition();CCPoint myPosition = this->getPosition();CCSize screenSize = CCDirector::sharedDirector()->getWinSize();if (position.x > screenSize.width/2.0f/PTM_RATIO) {myPosition.x = -MIN(screenSize.width*2.0f - screenSize.width,position.x*PTM_RATIO - screenSize.width/2.0f);this->setPosition(myPosition);}}    std::set<b2Body*>::iterator pos;for (pos = contactListener->contacts.begin(); pos != contactListener->contacts.end(); ++pos) {b2Body* body = *pos;for (vector<b2Body*>::iterator iter = targets->begin(); iter != targets->end(); ++iter) {if (body == *iter) {iter = targets->erase(iter);break;}}for (vector<b2Body*>::iterator iter = enemies->begin(); iter != enemies->end(); ++iter) {if (body == *iter) {iter = enemies->erase(iter);break;}}CCNode* contactNode = (CCNode*)body->GetUserData();CCPoint position = contactNode->getPosition();removeChild(contactNode, true);m_world->DestroyBody(body);CCParticleSun *explosion = CCParticleSun::create();explosion->retain();explosion->setTexture(CCTextureCache::sharedTextureCache()->addImage("fire.png"));//explosion->initWithTotalParticles(200);explosion->setAutoRemoveOnFinish(true);explosion->setStartSizeVar(10.0f);explosion->setSpeed(70.0f);explosion->setAnchorPoint(ccp(0.5f, 0.5f));explosion->setPosition(position);explosion->setDuration(1.0f);addChild(explosion, 11);explosion->release();}contactListener->contacts.clear();}void HelloWorld::ccTouchesBegan(CCSet* pTouches, CCEvent* pEvent) {if (m_mouseJoint != NULL) { return; }CCTouch* touch = (CCTouch*)pTouches->anyObject();CCPoint location = touch->getLocation();location = CCDirector::sharedDirector()->convertToGL(location);b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);if (locationWorld.x < m_armBody->GetWorldCenter().x + 150.0/PTM_RATIO) {b2MouseJointDef md;md.bodyA = m_groundBody;md.bodyB = m_armBody;md.target = locationWorld;md.maxForce = 2000;m_mouseJoint = (b2MouseJoint*)m_world->CreateJoint(&md);}}void HelloWorld::ccTouchesMoved(CCSet* pTouches, CCEvent* pEvent) {if (m_mouseJoint == NULL) { return; }CCTouch* touch = (CCTouch*)pTouches->anyObject();CCPoint location = touch->getLocation();location = CCDirector::sharedDirector()->convertToGL(location);b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);m_mouseJoint->SetTarget(locationWorld);}void HelloWorld::ccTouchesEnded(CCSet* pTouches, CCEvent* pEvent) {if (m_mouseJoint != NULL) {if (m_armJoint->GetJointAngle() >= CC_DEGREES_TO_RADIANS(5)) {m_releasingArm = true;}m_world->DestroyJoint(m_mouseJoint);m_mouseJoint = NULL;return;}}void HelloWorld::createBullets(int count) {m_currentBullet = 0;float pos = 62.0f;if (count > 0) {float delta = (count > 1) ? ((165.0f - 62.0f - 30.0f) / (count - 1)):0.0f;for (int i = 0; i < count; i++, pos += delta) {CCSprite* sprite = CCSprite::create("acorn.png");addChild(sprite, 1);b2BodyDef bulletBodyDef;bulletBodyDef.type = b2_dynamicBody;bulletBodyDef.bullet = true;bulletBodyDef.position.Set(pos/PTM_RATIO, (FLOOR_HEIGHT+15.0f)/PTM_RATIO);bulletBodyDef.userData = sprite;b2Body* bullet = m_world->CreateBody(&bulletBodyDef);bullet->SetActive(false);b2CircleShape circle;circle.m_radius = 15.0/PTM_RATIO;b2FixtureDef ballShapeDef;ballShapeDef.shape = &circle;ballShapeDef.density = 0.8f;ballShapeDef.restitution = 0.2f;ballShapeDef.friction = 0.99f;bullet->CreateFixture(&ballShapeDef);m_bullets.push_back(bullet);}}}bool HelloWorld::attachBullet() {if (m_currentBullet < m_bullets.size()) {m_bulletBody = (b2Body*)m_bullets.at(m_currentBullet++);m_bulletBody->SetTransform(b2Vec2(230.0f/PTM_RATIO, (156.0f+FLOOR_HEIGHT)/PTM_RATIO), 0.0f);m_bulletBody->SetActive(true);b2WeldJointDef weldJointDef;weldJointDef.Initialize(m_bulletBody, m_armBody, b2Vec2(230.0f/PTM_RATIO, (150.0f+FLOOR_HEIGHT)/PTM_RATIO));weldJointDef.collideConnected = false;m_bulletJoint = (b2WeldJoint*)m_world->CreateJoint(&weldJointDef);return true;}return false;}void HelloWorld::resetGame() {if (m_bullets.size() != 0) {for (vector<b2Body*>::iterator bulletPointer = m_bullets.begin(); bulletPointer != m_bullets.end(); ++bulletPointer) {b2Body* bullet = (b2Body*)*bulletPointer;CCNode* node = (CCNode*)bullet->GetUserData();m_world->DestroyBody(bullet);}m_bullets.clear();}if (targets->end() - targets->begin() != 0) {for (vector<b2Body*>::iterator targetPointer = (*targets).begin(); targetPointer != (*targets).end(); targetPointer++) {b2Body* target = (b2Body*)*targetPointer;CCNode* node = (CCNode*)target->GetUserData();removeChild(node, true);m_world->DestroyBody(target);}(*targets).clear();(*enemies).clear();}this->createBullets(3);this->createTargets();this->attachBullet();CCFiniteTimeAction *action1 = CCMoveTo::create(1.5f, ccp(-480.0f, 0.0f));//CCCallFuncN *action2 = CCCallFuncN::create(this, callfuncN_selector(HelloWorld::attachBullet));CCDelayTime *action3 = CCDelayTime::create(1.0f);CCFiniteTimeAction* action4 = CCMoveTo::create(1.5f, CCPointZero);runAction(CCSequence::create(action1,action3, action4, NULL));}HelloWorld::~HelloWorld(){delete m_world;m_world = NULL;}void HelloWorld::resetBullet() {if (enemies->size() == 0) {CCDelayTime* delayAction = CCDelayTime::create(2.0f);CCCallFunc* callSelectorAction = CCCallFunc::create(this, callfunc_selector(HelloWorld::resetGame));this->runAction(CCSequence::create(delayAction, callSelectorAction, NULL));} else if (attachBullet()) {CCAction *action = CCMoveTo::create(0.2f, CCPointZero);runAction(action);} else {CCDelayTime* delayAction = CCDelayTime::create(2.0f);CCCallFunc* callSelectorAction = CCCallFunc::create(this, callfunc_selector(HelloWorld::resetGame));this->runAction(CCSequence::create(delayAction, callSelectorAction, NULL));}}void HelloWorld::createTarget(char   *imageName,  CCPoint position,  float   rotation,  bool  isCircle,  bool    isStatic,  bool    isEnemy) {  CCSprite *sprite = CCSprite::create(imageName);     this->addChild(sprite, 1);      b2BodyDef bodyDef;     bodyDef.type = isStatic ? b2_staticBody : b2_dynamicBody;     bodyDef.position.Set((position.x+sprite->getContentSize().width/2.0f)/PTM_RATIO,                                      (position.y+sprite->getContentSize().height/2.0f)/PTM_RATIO);     bodyDef.angle = CC_DEGREES_TO_RADIANS(rotation);     bodyDef.userData = sprite;      b2Body *body = m_world->CreateBody(&bodyDef);      b2FixtureDef boxDef;     b2Fixture *fixtureTemp;          if (isCircle){         b2CircleShape circle;         boxDef.shape = &circle;         circle.m_radius = sprite->getContentSize().width/2.0f/PTM_RATIO;                  fixtureTemp = body->CreateFixture(&circle, 0.5f);         targets->push_back(body);     }     else{         b2PolygonShape box;         boxDef.shape = &box;         box.SetAsBox(sprite->getContentSize().width/2.0f/PTM_RATIO, sprite->getContentSize().height/2.0f/PTM_RATIO);         body->CreateFixture(&box, 0.5f);         targets->push_back(body);     }      if (isEnemy){         fixtureTemp->SetUserData((void*)1);     //  boxDef.userData = (void*)1;         enemies->push_back(body);     } }void HelloWorld::createTargets() {createTarget("brick_2.png", CCPointMake(675.0, FLOOR_HEIGHT), 0.0f, false, false, false);     createTarget("brick_1.png", CCPointMake(741.0, FLOOR_HEIGHT), 0.0f, false, false, false);     createTarget("brick_1.png", CCPointMake(741.0, FLOOR_HEIGHT+23.0), 0.0f, false, false, false);     createTarget("brick_3.png", CCPointMake(673.0, FLOOR_HEIGHT+46.0), 0.0f, false, false, false);     createTarget("brick_1.png", CCPointMake(707.0, FLOOR_HEIGHT+58.0), 0.0f, false, false, false);     createTarget("brick_1.png", CCPointMake(707.0, FLOOR_HEIGHT+81.0), 0.0f, false, false, false);      createTarget("head_dog.png", CCPointMake(702.0, FLOOR_HEIGHT), 0.0f, true, false, true);     createTarget("head_cat.png", CCPointMake(680.0, FLOOR_HEIGHT+58.0), 0.0f, true, false, true);     createTarget("head_dog.png", CCPointMake(740.0, FLOOR_HEIGHT+58.0), 0.0f, true, false, true);      // 2 bricks at the right of the first block     createTarget("brick_2.png", CCPointMake(770.0, FLOOR_HEIGHT), 0.0f, false, false, false);     createTarget("brick_2.png", CCPointMake(770.0, FLOOR_HEIGHT+46.0), 0.0f, false, false, false);      // The dog between the blocks     createTarget("head_dog.png", CCPointMake(830.0, FLOOR_HEIGHT), 0.0f, true, false, true);      // Second block     createTarget("brick_platform.png", CCPointMake(839.0, FLOOR_HEIGHT), 0.0f, false, true, false);     createTarget("brick_2.png", CCPointMake(854.0, FLOOR_HEIGHT+28.0), 0.0f, false, false, false);     createTarget("brick_2.png", CCPointMake(854.0, FLOOR_HEIGHT+28.0+46.0), 0.0f, false, false, false);     createTarget("head_cat.png", CCPointMake(881.0, FLOOR_HEIGHT+28.0), 0.0f, true, false, true);     createTarget("brick_2.png", CCPointMake(909.0, FLOOR_HEIGHT+28.0), 0.0f, false, false, false);     createTarget("brick_1.png", CCPointMake(909.0, FLOOR_HEIGHT+28.0+46.0), 0.0f, false, false, false);     createTarget("brick_1.png", CCPointMake(909.0, FLOOR_HEIGHT+28.0+46.0+23.0), 0.0f, false, false, false);     createTarget("brick_2.png", CCPointMake(882.0, FLOOR_HEIGHT+108.0), 90.0f, false, false, false); }

MyContactListener.h

#ifndef __MYCONTACTLISTENER_H__#define __MYCONTACTLISTENER_H__#include "Box2D/Box2D.h"#include <set>#include <algorithm>class MyContactListener: public b2ContactListener {public:std::set<b2Body*> contacts;MyContactListener();~MyContactListener();virtual void BeginContact(b2Contact* contact);virtual void EndContact(b2Contact* contact);virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse);};#endif


MyContactListener.cpp

#include "MyContactListener.h"MyContactListener::MyContactListener():contacts() {}MyContactListener::~MyContactListener() {}void MyContactListener::BeginContact(b2Contact* contact) {}void MyContactListener::EndContact(b2Contact* contact) {}void MyContactListener::PreSolve(b2Contact* contact, const b2Manifold* oldManifold) {}void MyContactListener::PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) {bool isAEnemy = (contact->GetFixtureA()->GetUserData() != NULL);bool isBEnemy = (contact->GetFixtureB()->GetUserData() != NULL);if (isAEnemy || isBEnemy) {int32 count = contact->GetManifold()->pointCount;float32 maxImpulse = 0.0f;for (int32 i = 0; i < count; ++i) {maxImpulse = b2Max(maxImpulse, impulse->normalImpulses[i]);}if (maxImpulse > 1.0f) {if (isAEnemy) contacts.insert(contact->GetFixtureA()->GetBody());if (isBEnemy) contacts.insert(contact->GetFixtureB()->GetBody());}}}


原创粉丝点击