Cocos2d-x游戏开发实例详解2:开始菜单续
本系列通过实际演练,详细解说Cocos2d-x引擎的各个模块。上一篇文章已经实现了MoonWarriors开始菜单的大部分元素,还差一个运动的飞船、一个点击newGame的特效和音效未实现,下面将详细介绍这些功能的实现。
1. 飞船
飞船的创建与基本设置
以下是创建飞船的代码:
// ships
CCTexture2D *textCache = CCTextureCache::sharedTextureCache()->addImage(s_ship01);
m_ship = CCSprite::createWithTexture(textCache, CCRectMake(0, 45, 60, 38));
this->addChild(m_ship, 0, 4);
CCPoint position = ccp(CCRANDOM_0_1() * winSize.width, 0);
m_ship->setPosition(position);
m_ship->runAction(CCMoveBy::create(2, ccp(CCRANDOM_0_1() * winSize.width, position.y + winSize.height + 100)));
这里创建的飞船是一个简单的CCSprite
对象。后续会创建一个飞船类,但目前仅使用CCSprite
。代码的主要步骤为:首先缓存飞船图片,接着创建飞船对象,将其添加到当前节点,设置飞船的初始位置,最后执行移动动作。
在设置飞船位置时,使用了CCRANDOM_0_1()
函数,该函数是Cocos2d-x引擎封装的随机函数,用于生成一个0到1之间的float
类型随机数,从而使每次飞船出现的位置具有随机性。同样,移动的目标点也有一定的随机性,通过CCMoveBy
动作实现飞船的移动。
让飞船持续飞行
需要注意的是,上述代码都在init()
函数中完成,即使执行了runAction
,飞船的移动动作也仅会执行一次。为了实现不断有飞船在屏幕上飞行的效果,需要使用schedule()
函数进行任务调度。该函数会每隔指定的时间dt
调用一次回调函数,这里设置为每0.1秒执行一次update
函数:
this->schedule(schedule_selector(StartMenu::update), 0.1);
以下是update
函数的实现:
if (m_ship->getPosition().y > 480) {
CCPoint pos = ccp(CCRANDOM_0_1() * winSize.width, 10);
m_ship->setPosition(pos);
m_ship->runAction(CCMoveBy::create(floor(5 * CCRANDOM_0_1()), ccp(CCRANDOM_0_1() * winSize.width, pos.y + 480)));
}
当飞船飞出屏幕(y
坐标大于480)后,会重新设置其位置并执行新的移动动作。
2. 音效
音效的实现非常简单,直接使用了Cocos2d-x的声音引擎:
SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(0.7);
SimpleAudioEngine::sharedEngine()->playBackgroundMusic(s_mainMainMusic, true);
上述代码设置了背景音乐的音量为0.7,并循环播放指定的背景音乐。
3. 点击特效
在HTML5版中,点击特效可以通过一个匿名函数轻松实现,但在Cocos2d-x中,为了实现点击特效,创建了一个特效类。
记得前面有个flareEffect
函数,就是在这里处理点击特效的:
void StartMenu::flareEffect(CCNode *node)
{
onButtonEffect();
Effect* flareEffect = Effect::create();
CCCallFunc *callback = CCCallFunc::create(this, callfunc_selector(StartMenu::newGame));
flareEffect->flareEffect(this, callback);
}
onButtonEffect
是声音特效函数,Effect
类用于实现动画特效,关键在于其flareEffect
函数。以下是Effect::flareEffect
函数的实现:
void Effect::flareEffect(CCNode *parent, CCCallFunc *callback)
{
// 特效图片
CCSprite *flare = CCSprite::create(s_flare);
// 设置混合模式
ccBlendFunc cbl = {GL_SRC_ALPHA, GL_ONE};
flare->setBlendFunc(cbl);
// 添加到父节点
parent->addChild(flare, 10);
// 设置初始透明度
flare->setOpacity(0);
// 设置初始位置
flare->setPosition(ccp(-30, 297));
// 设置初始角度
flare->setRotation(-120);
// 设置初始放大系数
flare->setScale(0.2);
// 透明度渐变
CCActionInterval *opacityAnim = CCFadeTo::create(0.5, 255);
CCActionInterval *opacDim = CCFadeTo::create(1, 0);
// 大小渐变
CCActionInterval *bigAnim = CCScaleBy::create(0.7, 1.2, 1.2);
// 渐变速率,正玄变化,由快到慢
CCEaseSineOut *biggerEase = CCEaseSineOut::create(bigAnim);
CCActionInterval *moveAnim = CCMoveBy::create(0.5, ccp(328, 0));
CCEaseSineOut *moveEase = CCEaseSineOut::create(moveAnim);
// 角度旋转
CCActionInterval *roteAnim = CCRotateBy::create(2.5, 90);
// 角度旋转速度,指数变化
CCEaseExponentialOut * rotateEase = CCEaseExponentialOut::create(roteAnim);
// 放大到原大小
CCScaleTo *bigger = CCScaleTo::create(0.5, 1);
// 动画完成后回调函数
CCCallFuncN *onComplete = CCCallFuncN::create(flare, callfuncN_selector(Effect::killFlare));
// 执行动画和回调函数
flare->runAction(CCSequence::create(opacityAnim, biggerEase, opacDim, onComplete, callback, NULL));
flare->runAction(moveEase);
flare->runAction(rotateEase);
flare->runAction(bigger);
}
该函数的主要步骤为:创建特效精灵对象,设置其混合模式、初始透明度、位置、角度和放大系数,然后创建各种动画动作,如透明度渐变、大小渐变、位置移动和角度旋转等,最后将这些动作组合并执行。动画完成后,会调用killFlare
函数,该函数用于移除特效精灵,避免其一直存在。
到这里,开始菜单的基本功能就已实现,不过还缺少一些回调和状态控制等功能,后续会继续完善。