转发,请保持地址:http://blog.csdn.net/stalendp/article/details/8606424
游戏战斗场景中的技能也是游戏的特色之一,这篇文章将记录使用WiEngine来设计游戏中的技能及其按钮特效。
先看效果图吧:
点击技能的按钮,就会放出技能。技能有冷却事件,表现在按钮上(下图更清晰一些)。
这里的技能用到的是WiEngine粒子系统中的特效。我的理解,粒子系统是一个标准,只要给定相应的参数,就可以显示一些很炫的效果。我本来是想用ParticleDesigner来设计粒子效果的,不过试了一下,发现载入有些问题,所以改用WiEngine中内置的特效了。我这里使用的是官方例子的Meteor(位于Demo/ParticleDemon.h中;补充一下WiEngine的好处,引擎中例子特别详细,我这个demo中的大部分代码都是从例子中改过来的)。我对Meteor进行了一个改进,代码如下:
class ParticleMeteorSystem: public wyQuadParticleSystem { public: ParticleMeteorSystem() : wyQuadParticleSystem(150) { // duration setDuration(PARTICLE_DURATION_INFINITY); // gravity setParticleGravity(DP(-133.33f), DP(0.33f)); // angle setDirectionAngleVariance(90, 360); // speed of particles setSpeedVariance(DP(10), DP(3.33f)); // life of particles setLifeVariance(2, 1); // size, in pixels setStartSizeVariance(DP(40.0f), DP(6.6f)); // emits per second setEmissionRate(getMaxParticles() / getLife()); // color of particles setStartColorVariance(0.2f, 0.4f, 0.7f, 1.0f, 0.0f, 0.0f, 0.2f, 0.1f); setEndColorVariance(0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f); //set texture setTexture(wyTexture2D::makePNG(RES("R.drawable.fire"))); // additive setBlendAdditive(true); } }; class FightBullet: public wyLayer { private: ParticleMeteorSystem* data; public: FightBullet(float px, float py) { data = new ParticleMeteorSystem(); data->autoRelease(); addChildLocked(data); setScale(0.6f); setPosition(px, py); } virtual ~FightBullet() { } };这里对子弹射击,只是用于演示有些特效的,并没有处理碰撞监测相关的内容(会在接下来的介绍Box2d时讨论),这里使用动画来演示子弹飞行、击中物体,然后使其爆炸的特效。代码如下:
void Boy::shot() { wyCallFunc* sbegin = wyCallFunc::make(wyTargetSelector::make(this, SEL(Boy::shotBegin))); wyCallFunc* bulletfly = wyCallFunc::make(wyTargetSelector::make(this, SEL(Boy::letBulletFlying))); wySequence* s = wySequence::make(sbegin, bulletfly, NULL); sprite->runAction(s); } void Boy::shotBegin() { LOGI("Shot begin"); hitBullet = new FightBullet(sprite->getPositionX()-60, sprite->getPositionY()-50); addChildLocked(hitBullet); sprite->runAction(boyActions[Boy::BOY_HIT]); //让Hero进行攻击的动画 playEffect(Boy::BOY_HIT); //播放攻击时的音效 } void Boy::letBulletFlying() { LOGI("Shotting"); wyActionCallback callback = { NULL, onMoveEnd, NULL }; wyMoveBy* moveby = wyMoveBy::make(3, 235, 0); moveby->setCallback(&callback, this); hitBullet->runAction(moveby); // 子弹飞行中 } static void onMoveEnd(wyAction* action, void* data) { // 子弹飞行完,停止射击动画 Boy* b = (Boy*)data;b->shotEnd(); } void Boy::shotEnd() { LOGI("Shot end"); changeAction(Boy::BOY_RUN); //子弹飞行完之后,让Hero进行奔跑动画 removeChild(hitBullet, true); hitBullet->release(); scene->enemyKilled(); // 表明击中物体,这里应当使用碰撞监测的。 }
接下来介绍技能按钮的实现。技能按钮有个冷却的时间(常识啊),在这里我将实现这个效果。相同的技能要准备两张图片,一张明亮一点的,表明技能可以使用,一张暗一点的,表示技能需要冷却。技能冷却时,吧暗一点的图片覆盖在亮一点的图片上, 播放一个动画时暗图片逐渐消失,就达到冷却效果了(效果在上面的第二张图片上很清晰。技能冷却的效果,对于玩过魔兽世界的同学来说,这是理所当然了)。
OK,附上代码:
class Button2: public wyNode { public: MyScene* scene; wyButton* button; wySprite* enable; wyProgressTimer* disable; wyCallFunc* action; int type; public: Button2(MyScene* scene, const char* ne, const char* ndis, int type) { this->scene = scene; this->type = type; wyZwoptexManager* zm = wyZwoptexManager::getInstance(); // create sprites enable = zm->makeSprite(ne); disable = wyProgressTimer::make(zm->makeSprite(ndis)); disable->setStyle(RADIAL_CCW); //设置进度条的改变方式 disable->setScale(0.9f); // create atlas button button = new wyButton(enable, enable, enable, NULL, NULL, wyTargetSelector::make(this, SEL(Button2::onButtonClicked))); addChildLocked(button); disable->setPosition(button->getPositionX(), button->getPositionY()); disable->setVisible(false); addChildLocked(disable); } virtual ~Button2() { } void onButtonClick() { switch(type) { case Boy::BOY_JUMP: scene->jump(); break; case Boy::BOY_HIT: scene->shot(); break; } } void onButtonClickedEnd() { disable->setVisible(false); button->setEnabled(true); } void onButtonClicked(wyTargetSelector* ts) { button->setEnabled(false); disable->setVisible(true); wyCallFunc* onaction = wyCallFunc::make(wyTargetSelector::make(this, SEL(Button2::onButtonClick))); wyCallFunc* setenable = wyCallFunc::make(wyTargetSelector::make(this, SEL(Button2::onButtonClickedEnd))); wySequence* s = wySequence::make(onaction, wyProgressTo::make(3, 100, 0), setenable, NULL); disable->runAction(s); } };