转发,请保持地址:http://blog.csdn.net/stalendp/article/details/8605053
动作类游戏,战斗类场景很常见,接下来几篇文章,我将记录用WiEngine编写游戏的战斗场景。本文介绍boss相关的内容,包括boss动画,boss的health bar等。先看几个效果图:
初始化时,boss为满血。
攻击两次之后,boss的血剩余1/3。
最后的致命一击,boss颤抖几下,然后爆炸了。
战斗场景的序列基本这样,接下来就是实现了。这篇文章主要使用到的技术有:1)动画的切换;2)health bar的实现;3)Action的序列化运行。其实还是比较简单的。
=======
使用Texture Packer进行动画文件的创建。TexturePacker的操作界面如下:
导出的文件名为:enemy.plist和enemy.png,在scene中载入贴图集:
zm->addZwoptex("enemy", RES("R.raw.enemy"), wyTexture2D::makePNG(RES("R.drawable.enemy")));
使用贴图集创建sprite的代码如下:
boss = zm->makeSprite("enemy_01.png");在enemy类中,初始化动画,代码如下:
enum EnemyActionsTag { EMY_RUN = 0, EMY_DIED, EMY_HIT } ; 。。。。 actions[EMY_RUN] = makeAction("enemy", zm, 4); actions[EMY_HIT] = makeAction("enemy", zm, 4); actions[EMY_DIED] = makeAction("explode", zm, 16); 。。。。 wyAction* makeAction(const char* an, wyZwoptexManager* zm, int num) { char buf[128]; wyAnimation* anim = wyAnimation::make(0); for (int i = 1; i < num+1; i++) { sprintf(buf, "%s_%02d.png", an, i); LOGI(buf); wySpriteFrame* f = zm->getSpriteFrame(buf); f->setDuration(0.15f); anim->addFrame(f); } wyRepeatForever* rp = wyRepeatForever::make(wyAnimate::make(anim)); rp->retain(); return rp; }
blood = wyProgressTimer::make(zm->makeSprite("blood.png")); blood->setStyle(HORIZONTAL_BAR_LR); //设置进度条的改变方式 blood->setPosition(blood->getPositionX(), blood->getPositionY()+50); blood->setScale(0.5f); addChildLocked(blood);改变进度的方法:
1)直接改变
blood->setPercentage(60);2)动画渐变
blood->runAction(wyProgressBy::make(2, 60)); //在2秒内,改变进度到60%
抖动要用到wyShake实现的动画,爆炸就是使用帧动画来实现,然后把两个动画序列化起来,成为一个组合动画,代码如下:
void die() { wyCallFunc* explode = wyCallFunc::make(wyTargetSelector::make(this, SEL(Enemy::explode))); wySequence* s = wySequence::make(wyShake::make(1, 5), explode, NULL); boss->runAction(s); blood->setPercentage(0); } void explode() { changeAction(Enemy::EMY_DIED); }
ok,把Enemy.h完整的代码贴上:
#ifndef ENEMY_H_ #define ENEMY_H_ class Enemy: public wyNode { public: enum EnemyActionsTag { EMY_RUN = 0, EMY_DIED, EMY_HIT } ; public: MyScene* scene; wyAction* actions[3]; wySprite* boss; wyProgressTimer* blood; const char* soundEffect; float health; public: Enemy(MyScene* scene) { health = 100; soundEffect = NULL; wyZwoptexManager* zm = wyZwoptexManager::getInstance(); // add sprite boss = zm->makeSprite("enemy_01.png"); addChildLocked(boss); // ADD BLOOD blood = wyProgressTimer::make(zm->makeSprite("blood.png")); blood->setStyle(HORIZONTAL_BAR_LR); blood->setPosition(blood->getPositionX(), blood->getPositionY()+50); blood->setScale(0.5f); addChildLocked(blood); // create animation actions[EMY_RUN] = makeAction("enemy", zm, 4); actions[EMY_HIT] = makeAction("enemy", zm, 4); actions[EMY_DIED] = makeAction("explode", zm, 16); // init the animation renew(); this->setPosition(400, 35); wyAudioManager::getInstance()->preloadEffect(RES("R.raw.explore"), FORMAT_MP3); wyAudioManager::getInstance()->preloadEffect(RES("R.raw.damage"), FORMAT_OGG); } virtual ~Enemy() { } void renew() { health = 100; blood->runAction(wyProgressBy::make(2, health)); changeAction(EMY_RUN); } void die() { wyCallFunc* explode = wyCallFunc::make(wyTargetSelector::make(this, SEL(Enemy::explode))); wySequence* s = wySequence::make(wyShake::make(1, 5), explode, NULL); boss->runAction(s); blood->setPercentage(0); } void explode() { changeAction(Enemy::EMY_DIED); } void shot() { health -= 33; if(health<10) { health = 0; die(); } else { changeAction(Enemy::EMY_HIT); } blood->setPercentage(health); } void changeAction(EnemyActionsTag bat) { boss->stopAllActions(true); boss->runAction(actions[bat]); playEffect(bat); } wyAction* makeAction(const char* an, wyZwoptexManager* zm, int num) { char buf[128]; wyAnimation* anim = wyAnimation::make(0); for (int i = 1; i < num+1; i++) { sprintf(buf, "%s_%02d.png", an, i); LOGI(buf); wySpriteFrame* f = zm->getSpriteFrame(buf); f->setDuration(0.15f); anim->addFrame(f); } wyRepeatForever* rp = wyRepeatForever::make(wyAnimate::make(anim)); rp->retain(); return rp; } void playEffect(EnemyActionsTag tag) { const char* preEffect = soundEffect; switch (tag) { case EMY_RUN: soundEffect = NULL; break; case EMY_DIED: soundEffect = "R.raw.explore"; _playEffect(preEffect, soundEffect, FORMAT_MP3); break; case EMY_HIT: soundEffect = "R.raw.damage"; _playEffect(preEffect, soundEffect, FORMAT_OGG); break; } } void _playEffect(const char* preEffect, const char* curEffect, int type) { if (curEffect != NULL) { if (preEffect != NULL) wyAudioManager::getInstance()->stopEffect(RES(preEffect)); wyAudioManager::getInstance()->playEffect(RES(curEffect), type); } } }; #endif /* ENEMY_H_ */