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;

}

//射中小鸟后,小鸟落地,得分;



Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐