cocos2d-x 实现 愤怒的小鸟 橡皮筋


经过摸索, 终于实现了angry birds中的橡皮筋.

首先要知道它用Weld Joint(焊接关节), Mouse Joint(鼠标关节)和Distance Joint(距离关节).

Weld Joint: 把小鸟固定在弹弓上.

Mouse Joint: 用来拖拽小鸟.这个好理解.

Distance Joint: 用来保持小鸟和弹弓之间的距离. 但是用的时候得有技巧.

步骤:

1. init:先用weldJoing把小鸟固定在弹弓中间位置. 可以是地面, 固定点在弹弓上, 这样Box2D可以少处理弹弓这个Body.

2. TouchBegan: 把weldJoint摧毁, 创建一个MouseJoint, 让小鸟跟随手指移动.

3. TouchMove: 如果小鸟被拖出弹弓一定距离, 创建一个Distance Joint, 让小鸟跟弹弓保持一定距离不变. 相当于给了一个弹弓最大拉伸度. 同时画两条线模仿皮筋.

4. TouchEnd: 手放开, 小鸟要飞了.这时要摧毁Distance Joint 和 Weld Joint, 让小鸟不再受限制, 同时给小鸟一个直线速度朝着弹弓中间飞出去.


上代码:

#import "cocos2d.h"
#import "box2d.h"
#import "PauseLayer.h"
#import "LevelScene.h"
#import "EKSprite.h"


USING_NS_CC;

class Level1Layer : public LevelScene {
public:
    Level1Layer();

    ~Level1Layer();

    CC_SYNTHESIZE(PauseLayer*, _pauseLayer, PauseLayer);
    CREATE_FUNC(Level1Layer);

    virtual void levelInit();

    virtual void ccTouchesBegan(cocos2d::CCSet *touches, cocos2d::CCEvent *event);

    virtual void ccTouchesMoved(cocos2d::CCSet *touches, cocos2d::CCEvent *event);

    virtual void ccTouchesEnded(cocos2d::CCSet *touches, cocos2d::CCEvent *event);

    virtual void ccTouchesCancelled(cocos2d::CCSet *touches, cocos2d::CCEvent *event);

    virtual void update(float dt);

private:
    EKSprite *_currBird;
    CCSprite *_slingshot;
    CCSpriteBatchNode *_parent;
    b2World *_world;
    b2Body *_groundBody;
    b2MouseJoint *_mouseJoint;
    b2DistanceJoint *_disJoint;
    b2WeldJoint *_weldJoint;
    bool _isPulling;

};

#import "Level1Layer.h"
#include "EKShapeCache.h"
#include "EKHelper.h"
#include "LineLayer.h"

#define FLOOR_HEIGHT 49.0f
#define FACTOR 20.0f

Level1Layer::Level1Layer() {
    CCLOG("Level1Layer");
}

Level1Layer::~Level1Layer() {
    CCLOG("~Level1Layer");
    EKEngine::sharedInstance()->deleteAllObjects();
    CCTextureCache::sharedTextureCache()->purgeSharedTextureCache();
}

void Level1Layer::levelInit() {
    setTouchMode(kCCTouchesAllAtOnce);
    setTouchEnabled(true);

    _mouseJoint = NULL;
    _disJoint = NULL;
    _isPulling = false;
    CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("level1.plist");
    EKShapeCache::sharedEKShapeCache()->addShapesWithFile("level1-shape.plist");

    CCSize s = CCDirector::sharedDirector()->getWinSize();

    _world = EKEngine::sharedInstance()->getworld();
    _groundBody = EKEngine::sharedInstance()->setEdge(ccp(0, FLOOR_HEIGHT), 960, 480);

    CCSprite *bg = CCSprite::createWithSpriteFrameName("bg-1.png");
    bg->setScale(1.34);
    bg->setAnchorPoint(CCPointZero);
    bg->setPosition(CCPointZero);
    addChild(bg);

    _slingshot = CCSprite::createWithSpriteFrameName("slingshot.png");
    float y = _slingshot->boundingBox().size.height / 2.0f;
    _slingshot->setPosition(ccp(78.0f, FLOOR_HEIGHT + y));
    addChild(_slingshot);

    _currBird = EKSprite::createWithFrameName("bird-1.png", "bird", true);
    _currBird->setPosition(ccp(78.0f, FLOOR_HEIGHT + _slingshot->getContentSize().height * 0.81f));
    _currBird->getBody()->SetBullet(true);
    addChild(_currBird);

    b2WeldJointDef wjd;
    wjd.Initialize(_groundBody, _currBird->getBody(), _currBird->getBody()->GetWorldCenter());
    wjd.collideConnected = false;

    CCLOG("create _weldJoint");
    _weldJoint = (b2WeldJoint *) _world->CreateJoint(&wjd);

    scheduleUpdate();
}


void Level1Layer::ccTouchesBegan(cocos2d::CCSet *touches, cocos2d::CCEvent *event) {
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    if (touches->count() == 1) {
        if (_mouseJoint != NULL) {
            return;
        }
        CCTouch *touch = (CCTouch *) touches->anyObject();
        CCPoint location = touch->getLocationInView();
        location = CCDirector::sharedDirector()->convertToGL(location);
        if (location.x > _currBird->getPositionX() - 50.0f && location.x < _currBird->getPositionX() + 50.0f && location.y > _currBird->getPositionY() - 50.0f && location.y < _currBird->getPositionY() + 50.0f) {
            b2MouseJointDef mjd;

            mjd.bodyA = _groundBody;
            mjd.bodyB = _currBird->getBody();
            mjd.target = b2Vec2FromCCPoint(location);
            mjd.collideConnected = true; //
            mjd.maxForce = 1000.0f * _currBird->getBody()->GetMass(); //给一个拖动的力
            CCLOG("create _mouseJoint");
            _mouseJoint = (b2MouseJoint *) _world->CreateJoint(&mjd);

            _currBird->getBody()->SetFixedRotation(true);
            if (_weldJoint != NULL) {
                CCLOG("destroy _weldJoint");
                _world->DestroyJoint(_weldJoint);
                _weldJoint = NULL;
            }
            _isPulling = true;

        }
    }
    stopActionByTag(1);
}

void Level1Layer::ccTouchesMoved(cocos2d::CCSet *touches, cocos2d::CCEvent *event) {

    CCSize s = CCDirector::sharedDirector()->getWinSize();
    CCTouch *touch = (CCTouch *) touches->anyObject();
    CCPoint location = touch->getLocationInView();
    location = CCDirector::sharedDirector()->convertToGL(location);

    if (_isPulling) {
        if (ccpDistance(ccp(_slingshot->getPosition().x, _slingshot->getContentSize().height * 0.81f + FLOOR_HEIGHT), location) > 80.0f) {
            if (_disJoint == NULL) {
                b2DistanceJointDef djd;
                djd.Initialize(_groundBody, _currBird->getBody(), b2Vec2FromCCPoint(ccp(_slingshot->getPositionX(), FLOOR_HEIGHT + _slingshot->getPositionY() * 0.81f)), _currBird->getBody()->GetWorldCenter());
                djd.collideConnected = true;
                djd.frequencyHz = 4.0f;
                djd.dampingRatio = 0.5f;
                CCLOG("create _disJoint");
                _disJoint = (b2DistanceJoint *) _world->CreateJoint(&djd);
                _disJoint->SetLength(80.0f / 32.0f);
            }
        } else if (_disJoint != NULL) {
            CCLOG("destroy _disJoint");
            _world->DestroyJoint(_disJoint);
            _disJoint = NULL;
        }
        visit();

        removeChildByTag(77);
        CCLayer *line = LineLayer::createWithPoints(_currBird->getPosition(), ccp(_slingshot->getPositionX() - 10, FLOOR_HEIGHT + _slingshot->getPositionY() * 0.81f), ccp(_slingshot->getPositionX() + 10, FLOOR_HEIGHT + _slingshot->getPositionY() * 0.81f));
        addChild(line, 1000, 77);
        _mouseJoint->SetTarget(b2Vec2FromCCPoint(location));

    }
}

void Level1Layer::ccTouchesEnded(cocos2d::CCSet *touches, cocos2d::CCEvent *event) {

    if (_isPulling && _mouseJoint != NULL ) {
        CCLOG("destroy _mouseJoint");
        EKEngine::sharedInstance()->getworld()->DestroyJoint(_mouseJoint);
        _mouseJoint = NULL;
        _isPulling = false;

        if (_disJoint != NULL) {
            CCLOG("destroy _disJoint");
            EKEngine::sharedInstance()->getworld()->DestroyJoint(_disJoint);
            _disJoint = NULL;
        }

        _currBird->getBody()->SetFixedRotation(false);

        CCPoint point = ccpSub(ccp(_slingshot->getPositionX(), FLOOR_HEIGHT + _slingshot->getPositionY()), _currBird->getPosition());
        b2Vec2 direct = b2Vec2FromCCPoint(point);
        b2Vec2 dd(direct.x * FACTOR, direct.y * FACTOR);
        CCLOG("%f, %f", point.x, point.y);
        CCLOG("%f, %f", direct.x, direct.y);
        _currBird->getBody()->ApplyLinearImpulse(dd, _currBird->getBody()->GetWorldCenter());

        removeChildByTag(77);
    }

}

void Level1Layer::ccTouchesCancelled(cocos2d::CCSet *touches, cocos2d::CCEvent *event) {
    CCLOG("ccTouchesCancelled");
    ccTouchesEnded(touches, event);
}


void Level1Layer::update(float dt) {
    EKEngine::sharedInstance()->update(dt);

}



上图.


cocos2d-x 实现 愤怒的小鸟 橡皮筋_第1张图片cocos2d-x 实现 愤怒的小鸟 橡皮筋_第2张图片cocos2d-x 实现 愤怒的小鸟 橡皮筋_第3张图片

你可能感兴趣的:(cocos2d-x)