***************************************转载请注明出处:http://blog.csdn.net/lttree********************************************
满满的泪啊,
从5月22日写的第一篇,于6月6日结束。
中间各种课程、上机、大作业穿插,焦头烂额的,
最后终于做出来差不多的样子了。。。
PS:写博客这几天,宿舍一直停电状态。。。真是醉了。。
本篇实现的功能:
> 粒子特效
> 音乐音效
> 漂浮文字
> combo特效 及 每关结束后星星的消除(小于等于10个的一个个消除,剩余的一齐消除)
> 最高分存储、场景的简单存储
> 消除星星的Hint
一、粒子特效
粒子特效,主要是星星消除后的爆炸效果。
这里主要用了两个函数:
▪ 产生爆炸粒子特效
▪ 获取点击星星的颜色
void starSpecialEffect(Star* sta,Point position,Node* node,int staNum) { // 创建爆炸粒子效果,粒子数量为 staNum 个 ParticleExplosion* effect = ParticleExplosion::createWithTotalParticles(staNum); // 设置此粒子特效的纹理图片 effect->setTexture(Director::getInstance()->getTextureCache()->addImage("star.png")); // 设置开始时候的粒子颜色 effect->setStartColor(getColor4F(sta->getImgIndex())); effect->setStartColorVar(Color4F(0,1)); effect->setEndColor(getColor4F(sta->getImgIndex())); effect->setEndColorVar(Color4F(0,1)); // 设置开始时的粒子大小 effect->setStartSize(20.0f); effect->setGravity(Point(0,-300)); // 设置粒子生命周期 effect->setLife(2.0f); // 设置粒子速度 effect->setSpeed(200); effect->setSpeedVar(10); // 设置粒子位置 effect->setPosition(position); node->addChild(effect,2); } Color4F getColor4F(int imgIndex) { switch(imgIndex){ case 0: //red return Color4F::RED; case 1: //blue return Color4F::BLUE; case 2: //green return Color4F::GREEN; case 3: //purple return Color4F(128.0f,128.0f,1.0f); case 4: //yellow return Color4F::YELLOW; } return Color4F(1,1,0); }
具体粒子特效的应用,等有时间做一个单独的博文发出来。。
二、音乐音效
这里用了UserDefault进行存储,音乐音效的开关,
音乐和音效同一开关,没有分开。
主要就是 Android对于 ogg 格式的音乐支持是最好的,
但是在Windows平台不好测试,因为Windows自带的WMP(Windows Media Player)不支持这个格式的音乐播放,即使没有路,我们自己创造路来走,有大牛就开发了一款解码软件—— K-Lite Codec Pack,
我的WMP是可以播放ogg了,cocos2d-x 还是需要改动一下,暂时没改好,
于是。。。阉割了。。
我是在Windows用 mp3格式 测试,然后在Android用ogg格式的,效果挺好
之前的三消游戏中,很多人就说音乐播放不出来,没有效果,
但是我自己试的是没问题的,偶尔还真有一两个音效不好用,我觉得还是格式问题,
各个音效部分,我就不多说了,在相应位置插入就行,
背景音乐,需要 重载虚函数
virtual void onEnterTransitionDidFinish(); virtual void cleanup();
onEnterTransitionDidFinish是在场景加载完成后进行,
不同于onEnter,onEnter是场景开始加载就进行,
cleanup 函数,是在场景被消除时的动作,
我们的背景音乐就是要在这两个函数中加入:
void WelcomeScene::onEnterTransitionDidFinish() { Layer::onEnterTransitionDidFinish(); if ( userDefault->getBoolForKey("MusicKey") ) { SimpleAudioEngine::getInstance()->playBackgroundMusic("Music/music.ogg",true); } } void WelcomeScene::cleanup() { Layer::cleanup(); SimpleAudioEngine::getInstance()->stopBackgroundMusic(); }
对于音乐音效说的也就这么多了
三、漂浮文字
主要的创建函数:
FloatWord* FloatWord::create( const std::string& word,const int fontSize,Vec2 begin ) { FloatWord* fw = new FloatWord(); if( !fw->init(word,fontSize,begin) ) { return NULL; } fw->autorelease(); return fw; }
几个主要的工具函数:
void FloatWord::floatInOut(const float speed,const float delayTime,std::function<void()> callback){ MoveTo* moveIn = MoveTo::create(speed,Vec2(GAME_SCREEN_WIDTH/2,fw_begin.y)); MoveTo* moveOut = MoveTo::create(speed,Vec2(-fw_label->getContentSize().width,fw_begin.y)); CallFunc* call = CallFunc::create(callback); Sequence* action = Sequence::create(moveIn,DelayTime::create(delayTime),moveOut,call,NULL); fw_label->runAction(action); } void FloatWord::floatIn(const float speed){ MoveTo* moveIn = MoveTo::create(speed,fw_begin.y)); Sequence* action = Sequence::create(moveIn,NULL); fw_label->runAction(action); } void FloatWord::floatOut(const float speed,const float delayTime){ MoveTo* moveOut = MoveTo::create(speed,fw_begin.y)); Sequence* action = Sequence::create(DelayTime::create(delayTime),NULL); fw_label->runAction(action); }
就是将动作 Sequence起来了,按顺序播放就行了
四、combo特效 及每关结束后星星的消除
首先是 combo 特效,做一个函数,然后每次消除的时候,判断消除的个数是否满足combo特效触发条件即可。
void comboEffect(int num,Node* node){ if( num < 5 ) return; Sprite* comboSprite; if( num >= 10 ){ comboSprite = Sprite::create("combo_3.png"); }else if( num >= 7 ){ comboSprite = Sprite::create("combo_2.png"); }else{ comboSprite = Sprite::create("combo_1.png"); } comboSprite->setPosition(Vec2(GAME_SCREEN_WIDTH/2,GAME_SCREEN_HEIGHT/2)); node->addChild(comboSprite,4); Blink* blink = Blink::create(1.0f,5); CallFunc* remove = CallFunc::create([=](){comboSprite->removeFromParentAndCleanup(true);}); Sequence* action = Sequence::create(blink,remove,nullptr); comboSprite->runAction(action); }
最后星星的消除,这里我的处理比较麻烦:
1.判断此关卡结束(没有可以消除的星星),然后将 全局的 关卡结束 变量 设置为 true,获得剩余星星的数量,如果剩余星星数量大于10 则 设置为10(因为一个一个消除的效果,最多10个)
2.在 update函数中(每一帧都会调用的函数),会判断关卡是否结束,若结束,会调用 消除函数,10个以内,每消除一个都会返回,不会继续消除,而且记录消除时间,消除一次后一定时间间隔再进行下一次消除
3.消除完10个(或者小于10个)以后,不会再返回,会一次性将剩余星星消除完毕,将 关卡结束 变量设置为false。
这里的: 关卡结束一系列操作:
if( isFinish() ) { isLevelFinish = true; int temp = totalStarNum(); if( temp <= 10 ) { needDelOneByOne = temp; } } else { needDelOneByOne = 10; }
update函数:
void GameScene::update( float dt ) { // 分数变化 Label *labelscore = (Label *)this -> getChildByTag(6); labelscore -> setString( StringUtils::format("score: %d ",_score)); // 如果当前关卡结束 星星一个个消除的实现 if( isLevelFinish ) { deleteTime += dt; if( deleteTime > DELSTAR_ONEBYONE_TIME ) { popFinishStar(needDelOneByOne); needDelOneByOne--; deleteTime = 0; } } }
消除结束星星函数:
void GameScene::popFinishStar( int n ) { int r,c; Star* sta; for( r = ROWS-1 ; r >= 0 ; r-- ) { for( c = 0 ; c < COLS ; c++ ) { sta = map[r][c]; if( sta ) { starSpecialEffect(sta,sta->getPosition(),this,5); map[r][c]=NULL; sta->removeFromParentAndCleanup(true); return; } else { starSpecialEffect(sta,totalStarNum()*4); map[r][c]=NULL; sta->removeFromParentAndCleanup(true); } } } } isLevelFinish = false; scheduleOnce(schedule_selector(GameScene::levelOver),2.0f); }
五、最高分的存储,场景的简单存储
最高分的存储,还是用了userdefault,
就是在游戏结束的时候,判断一下是否破纪录:
if( userDefault->getIntegerForKey("Hightscore") < _score ) userDefault->setIntegerForKey("Hightscore",_score);
场景的存储,用了 push 和 pop,
在主界面定义一个变量,来判断是否可以继续,
刚进入主界面时,场景栈是没有场景存储的,此时点击 继续游戏 就会退出游戏,
所以要在场景栈没有场景时,不允许点击 继续游戏 按钮。
这个变量,在从游戏界面跳转到主界面(通过返回函数跳转)时,会设置为true,就是可以点击。
六、消除星星Hint
当消除几个星星,我们都要有提示,加了几分。
游戏结束,如果剩余星星数量小于10个,都要有额外分数的增加。
星星消除函数是这样的:
一个等差数列,第一个星星 5分,第二个15分,第三个25分(首项为5,公差为10的等差数列)
所以,如果消除n个星星,就是用到等差数列的求和公式了:
n*5+n*(n-1)*10/2
剩余星星数量,所获得的额外分数则建立了一个数组,放在GameDefine头文件,
// 剩余星星所奖励的分数 static const int rewardscore[11] = { 2000,1980,1920,1820,1680,1500,1280,1020,720,380,0 };
到这里,消灭星星系列完美结束啦~~~
撒花。。。
接下来把历史遗留下的问题——别踩白块 剩下部分搞定,
然后要做第一款自己想的游戏了,
敬请期待呀~~~
本文源码: > 这里 <
最终APK: > here <
********************************************