天天看點

結合實體引擎的cocos2dx遊戲(保衛果樹)

physic是coco2dx3.0自帶的實體引擎,應付一般的需求已經足夠啦。

項目位址:

https://github.com/frank1982/Fruits

核心代碼:

_arrowArray=Array::create();

    _arrowArray->retain();

    _birdArray=Array::create();

    _birdArray->retain();

設定小鳥和弓箭的存貯array;

 auto layer = GameScene::create();

    layer->setPhyWorld(scene->getPhysicsWorld());

設定實體世界;

    auto listener = EventListenerTouchOneByOne::create();

    listener->setSwallowTouches(true);

    auto contactListener=EventListenerPhysicsContact::create();

    //設定監聽器的碰撞開始函數

    contactListener->onContactBegin = CC_CALLBACK_1(GameScene::onContactBegin, this);

    //添加到事件分發器中

    _eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);

設定實體碰撞(小鳥和弓箭)和觸摸檢測;

auto str=String::createWithFormat("SCORE: %d",SCORE);

    _scoreLabel=LabelTTF::create(str->getCString(), "Arial", 40);

    _scoreLabel->setPosition(visibleSize.width/2,visibleSize.height-_scoreLabel->getContentSize().height);

    _scoreLabel->setColor(Color3B::GREEN);

    addChild(_scoreLabel,2);

//計算得分;

 auto str2=String::createWithFormat("X %d",FRUITS_NUM);

    _fruitNum=LabelTTF::create(str2->getCString(), "Arial", 40);

    _fruitNum->setPosition(fruit->getPosition()+Point(50,0));

    _fruitNum->setColor(Color3B::RED);

    addChild(_fruitNum,2);

//計算剩餘果實的數量;

    listener->onTouchBegan=[&](Touch* touch, Event* event){

        struct  timeval tv;

        gettimeofday(&tv,NULL);

        _curTouchTime=tv.tv_sec * 1000 + tv.tv_usec / 1000;

        if(_curTouchTime-_preTouchTime>=500){

            _pointTouch=touch->getLocation();

            Point shootVector = _pointTouch-_bowl->getPosition();

            Point normalizedVector = ccpNormalize(shootVector) ;

            float radians = atan2(normalizedVector.y, - normalizedVector.x);

            float degree = CC_RADIANS_TO_DEGREES(radians);

            _bowl->setRotation(degree);

            _preTouchTime=_curTouchTime;

            return true;

        }else{

            CCLOG("too much touch");

            return false;

        }

    };

//當檢測到觸摸時,旋轉弓箭的角度,并且500毫秒内隻允許點選一次;

listener->onTouchEnded=[&](Touch* touch, Event* event){

        //shoot the arrow

        SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();

        SimpleAudioEngine::sharedEngine()->playEffect("music/shoot.mp3");

//播放射擊音效;

        Point shootVector = _pointTouch-_bowl->getPosition();

        Point normalizedVector = ccpNormalize(shootVector) ;

        CCLog("x speed is: %f, y speed is: %f",shootVector.x,shootVector.y);

        _arrow=Sprite::create("Arrow.png");

        _arrow->setTag(1);

        addChild(_arrow);

        //加載弓箭精靈;

        _arrow->setPosition(_bowl->getPosition());

        _arrow->setScale(arrow_scale);

        _arrow->setRotation(_bowl->getRotation());

        auto body=PhysicsBody::createBox(_arrow->getContentSize()*arrow_scale);

        body->setMass(1.0f);

        body->setCategoryBitmask(0x00000010);

        body->setContactTestBitmask(0x00000001);

        body->setCollisionBitmask(0x00000001);

//設定實體檢測參數,弓箭和小鳥會發生碰撞;

        _arrow->setPhysicsBody(body);

        _arrow->getPhysicsBody()->setVelocity(Vect(normalizedVector.x*_arrowSpeed,normalizedVector.y*_arrowSpeed));

        _arrow->getPhysicsBody()->setGravityEnable(true);

        //設定初速度,和弓箭的旋轉方向一緻;

        //_arrowArray=Array::create();

        _arrowArray->addObject(_arrow);

        CCLog("_arrowArray length is %zd",_arrowArray->count());

     };

    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);

void GameScene::loadBirds(float dt){

    Size visibleSize = Director::getInstance()->getVisibleSize();

    enum birdType type[7]={Blue,Yellow,Green,Grey,Red,Orange,Coffee};

    int index=(int)(CCRANDOM_0_1()*7);

    auto birdSp=Bird::createBird(type[index]);

    //random enter position;

    float PY=(float)(CCRANDOM_0_1()*visibleSize.height);

    birdSp->setPosition(0,PY);

    addChild(birdSp,1);

    _birdArray->addObject(birdSp);

    auto fruit=this->getChildByTag(21);

    //random speed;

    float Speed=(float)(CCRANDOM_0_1()*2.5+3);

    auto seq=Sequence::create(MoveTo::create(Speed, fruit->getPosition()), DelayTime::create(1.2),CallFunc::create(CC_CALLBACK_0(GameScene::eatApple, this)),

                              MoveTo::create(2, Point(visibleSize.width,fruit->getPosition().y)),NULL);

    birdSp->runAction(seq);

    CCLOG("bird number is %zd",_birdArray->count());

}

//這裡随機會出現一隻小鳥,速度和位置都不确定,小鳥會飛到樹上停留一下,吃掉蘋果;

void GameScene::update(float dt){

    Size visibleSize = Director::getInstance()->getVisibleSize();

    auto rectWin=CCRectMake(0, 0, visibleSize.width, visibleSize.height);

    for(int i=0;i<_arrowArray->count();i++){

        auto sp=dynamic_cast<Sprite *>(_arrowArray->getObjectAtIndex(i));

        //check if out of window;

        if(sp->getPosition().x<=0||sp->getPosition().y>=visibleSize.height||sp->getPosition().x>=visibleSize.width||sp->getPosition().y<=0){

            //sp->setVisible(false);

            sp->removeAllChildren();

            this->removeChild(sp);

            _arrowArray->removeObjectAtIndex(i);

            CCLog("_arrowArray length is %zd",_arrowArray->count());

        }

    }

    for(int j=0;j<_birdArray->count();j++){

        auto sp2=dynamic_cast<Sprite *>(_birdArray->getObjectAtIndex(j));

        //check if out of window;

        if(sp2->getPosition().x>=visibleSize.width||sp2->getPosition().y<=0){

            sp2->removeAllChildren();

            this->removeChild(sp2);

            _birdArray->removeObjectAtIndex(j);

            CCLog("_birdArray length is %zd",_birdArray->count());

        }

    }

}

//檢測小鳥和弓箭是否越出邊界;

bool GameScene::onContactBegin(const PhysicsContact& contact){

    CCLOG("get bound");

    auto cnt = const_cast<PhysicsContact*>(&contact);

    auto spA = cnt->getShapeA()->getBody()->getNode();

    auto spB = cnt->getShapeB()->getBody()->getNode();

    int tagA = spA->getTag();

    int tagB = spB->getTag();

    if(tagA == 2) {

        spA->getPhysicsBody()->setGravityEnable(true);

        spA->getPhysicsBody()->setVelocity(Point(0,-300));

        spB->removeAllChildren();

        this->removeChild(spB);

        _arrowArray->removeObject(spB);

        CCLog("_arrowArray length is %zd",_arrowArray->count());

    }else if(tagB == 2){

        spB->getPhysicsBody()->setGravityEnable(true);

        spB->getPhysicsBody()->setVelocity(Point(0,-300));

        this->removeChild(spA);

        _arrowArray->removeObject(spA);

        CCLog("_arrowArray length is %zd",_arrowArray->count());

    }

    SCORE+=5;

    auto str=String::createWithFormat("SCORE: %d",SCORE)->getCString();

    _scoreLabel->setString(str);

    return true;

}

//射中小鳥後,小鳥落地,得分;