制作横版游戏KillBear第8课:技能及CD实现

2015年03月22日 09:34 0 点赞 0 评论 更新于 2025-11-21 18:04

在上一节课程中,我们实现了攻击判定,使得英雄能够杀死敌人。在这一课里,我们将在控制(操作)层添加一个带有冷却时间显示的技能按钮,实现技能释放功能,为英雄添加大招。

开发环境

  • Win64 : vs2010
  • Cocos2d-x v3.4Final
  • TexturePackerGUI
  • MapEdit

代码实现

1. SkillButton类

1.1 头文件 SkillButton.h

#ifndef _SKILL_BUTTON_H_
#define _SKILL_BUTTON_H_

#include "cocos2d.h"
USING_NS_CC;
#include "Global.h"

class SkillButton : public Node {
public:
SkillButton();
~SkillButton();

// 重载create函数,实现自定义输入图片
static SkillButton* create(const char* Nomal, const char* Click, const char* Mask, float CDTime);
static SkillButton* create(const char* Nomal, const char* Mask, float CDTime) {
return SkillButton::create(Nomal, Nomal, Mask, CDTime);
}
static SkillButton* create(const char* Nomal, const char* Mask) {
return SkillButton::create(Nomal, Nomal, Mask, 1.0f);
}
static SkillButton* create(const char* Nomal, float CDTime) {
return SkillButton::create(Nomal, Nomal, Nomal, CDTime);
}
static SkillButton* create(const char* Nomal) {
return SkillButton::create(Nomal, Nomal, Nomal, 1.0f);
}

CC_SYNTHESIZE(float, _cdtime, CDTime);

void ClickCallBack(Ref* obj);
void CoolDownCallBack(Node* node);

private:
bool init(const char* Nomal, const char* Click, const char* Mask, float CDTime);

MenuItemImage* _ItemSkill; // 技能按钮
Sprite* _Mask; // 蒙板精灵,黑色半透明,用于显示冷却计时效果
ProgressTimer* _ProgressTimer; // 时间进度条精灵,360度旋转
Label* _atLabel; // 显示冷却时间
float CdTime; // 冷却时间
void CoolDownReduce(float dt); // 冷却时间显示定时器
};

#endif

通过实现 create 函数的重载,我们可以自定义输入的图片。在后续调用时,只需指定两个参数,即图片显示效果和CD时间,即可完成调用。

1.2 源文件 SkillButton.cpp

#include "SkillButton.h"

SkillButton::SkillButton() :
_ItemSkill(NULL),
_Mask(NULL),
_cdtime(1.0f),
_ProgressTimer(NULL) {
}

SkillButton::~SkillButton() {
}

SkillButton* SkillButton::create(const char* Normal, const char* Click, const char* Mask, float CDTime) {
SkillButton* skillButton = new SkillButton();
if (skillButton && skillButton->init(Normal, Click, Mask, CDTime)) {
skillButton->autorelease();
return skillButton;
} else {
CC_SAFE_DELETE(skillButton);
return nullptr;
}
}

bool SkillButton::init(const char* Normal, const char* Click, const char* Mask, float CDTime) {
bool ret = false;
do {
CC_BREAK_IF(!Node::init());

// 断言检查输入参数
CCAssert(Mask, "SkillButton::init Mask != NULL");
CCAssert(Normal, "SkillButton::init Normal != NULL");
CCAssert(Click, "SkillButton::init Click != NULL");

// 添加技能按钮
_ItemSkill = MenuItemImage::create(Normal, Click, CC_CALLBACK_1(SkillButton::ClickCallBack, this));
_ItemSkill->setPosition(Vec2::ZERO);
auto MenuSkill = Menu::create(_ItemSkill, NULL);
MenuSkill->setPosition(Vec2::ZERO);
addChild(MenuSkill, -100);

// 添加蒙版
if (Normal == Mask) {
_Mask = Sprite::create();
_Mask->setTexture(Normal);
_Mask->setColor(Color3B(0, 0, 0));
_Mask->setOpacity(100);
} else {
_Mask = Sprite::create(Mask);
}
_Mask->setPosition(Vec2::ZERO);
_Mask->setVisible(false);
addChild(_Mask, 0);

// 添加旋转进度条精灵,设置为顺时针扇形进度计时器
_ProgressTimer = ProgressTimer::create(Sprite::create(Normal));
_ProgressTimer->setType(ProgressTimer::Type::RADIAL);
_ProgressTimer->setPosition(Vec2::ZERO);
_ProgressTimer->setVisible(false);
addChild(_ProgressTimer, 100);

this->setCDTime(CDTime);
CdTime = CDTime;

_atLabel = Label::create();
_atLabel->setSystemFontSize(_Mask->getContentSize().width / 3);
_atLabel->setColor(Color3B(0, 0, 0));
_atLabel->setPosition(Vec2::ZERO);
addChild(_atLabel, 200);
_atLabel->setVisible(false);

ret = true;
} while (0);
return ret;
}

void SkillButton::ClickCallBack(Ref* obj) {
// 设置技能按钮不可点击
_ItemSkill->setEnabled(false);
// 设置蒙版可见
_Mask->setVisible(true);
// 设置进度条可见
_ProgressTimer->setVisible(true);
// 设置剩余时间可见
_atLabel->setVisible(true);
// 开启定时器
this->schedule(schedule_selector(SkillButton::CoolDownReduce), 0.1f);
// Hero释放技能A
global->hero->runChangeAttack();

// 准备一个持续时间为CDTime秒,旋转360度*100% 的动画,实现计时冷却动画和时间控制
ActionInterval* action_progress_to = Sequence::create(
ProgressTo::create(this->getCDTime(), 100),
NULL
);
CallFunc* action_callback = CallFuncN::create(CC_CALLBACK_1(SkillButton::CoolDownCallBack, this));
_ProgressTimer->runAction(Sequence::create(action_progress_to, action_callback, NULL));
}

void SkillButton::CoolDownReduce(float dt) {
_atLabel->setString(__String::createWithFormat("%.1f", CdTime -= 0.1f)->getCString());
}

void SkillButton::CoolDownCallBack(Node* node) {
// 按钮置为可用
_ItemSkill->setEnabled(true);
// 设置蒙板不可见
_Mask->setVisible(false);
// 进度条技能不可见
_ProgressTimer->setVisible(false);
_ProgressTimer->setPercentage(0);
// 设置剩余时间不可见
_atLabel->setVisible(false);
CdTime = this->getCDTime();
// 取消定时器
this->unschedule(schedule_selector(SkillButton::CoolDownReduce));
}

2. 技能按钮功能说明

  • 蒙版:当技能处于CD状态时显示,可自行指定显示图片。
  • 技能释放:按下技能按钮后,按钮变为不可点击状态,同时显示一个持续时间为CD的进度条,该进度条从0%顺时针旋转到100%。
  • 冷却完毕:技能冷却完毕后,按钮恢复可点击状态,隐藏蒙版和进度条。
  • 剩余时间显示:通过定时器实现剩余时间的显示,冷却完毕后取消定时器。

3. 将 SkillButton 添加到控制层

Operate.cpp 中添加以下代码:

auto skillA = SkillButton::create("SkillButton.png", 3.0f);
skillA->setPosition(attackItem->getPosition() - Vec2(50, 0));
this->addChild(skillA);

效果展示

按照上述步骤实现后,技能按钮将具备冷却时间显示和技能释放功能。

结语

我们新建了一个 SkillButton 类,实现了技能攻击效果。如果技能动画速度过快,可以调整其帧数。由于受素材限制,目前的效果可能不太理想,你可以对代码进行适当修改,从外部改善显示效果。作者更希望直接使用原来的技能图片,通过改变图片的纹理(如灰度、可见度)来实现冷却展示,而不是使用新的图片。

本篇展示结束,下一篇我们将添加一个暂停按钮,实现暂停功能。

作者信息

boke

boke

共发布了 3994 篇文章