您的位置:首页 > 其它

基于WiEngine游戏引擎--战斗场景之boss

2013-02-23 13:23 302 查看
转发,请保持地址:/article/7718234.html
动作类游戏,战斗类场景很常见,接下来几篇文章,我将记录用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;
}


boss的Health bar的实现了运用了WiEngine中的wyProgressTimer类来实现,其实这个类也是一个sprite,它只是是对Sprite的一个封装,赋予sprite进度条的功能,创建的代码如下:

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%


boss抖动爆炸效果的实现。
抖动要用到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_ */
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: