此技能按钮主要有一下几个功能
- 技能冷却效果
- 技能蓄力
效果图:
技能按钮效果图
代码如下:
SkillButton.h
#ifndef SkillButton_h
#define SkillButton_h
#include <stdio.h>
#include "cocos2d.h"
USING_NS_CC;
class SkillButton:public Node
{
public:
typedef std::function<void(float pressTime)> alSkillClickCallback;
typedef std::function<void(float pressTime)> alSkillTouchCallback;
typedef std::function<void(void)> alSkillCDEndCallback;
public:
static SkillButton* create(const std::string normalImage,const std::string coolImage = "",float skillTime = 0);
SkillButton();
virtual ~SkillButton();
/**
技能是否处于冷却中
*/
virtual const bool& isSkillCD() const { return _isSkillCD;}
/**
* 设置正常状态下的Image
*/
virtual void setupNormalImage(const std::string normalImage);
/**
* 设置冷却状态下的Image
*/
virtual void setupCoolImage(const std::string coolImage);
/**
技能的点击回调
注意:如果不开启按压更新的话 按压时间一直为0
*/
virtual void addClickCallback(const alSkillClickCallback& callback);
/**
技能按压开始的回调 按压时间为 0
*/
virtual void addTouchBeginCallback(const alSkillTouchCallback& callback);
/**
技能按压结束的回调
注意:如果不开启按压更新的话 按压时间一直为0
*/
virtual void addTouchEndCallback(const alSkillTouchCallback& callback);
/**
技能按压更新回调 (每隔一段时间 进行更新)
注意:如果不开启按压更新的话,此回调函数不会调用
@param callback 回调函数
@param interval 时间间隔应该大于等于0.1且是0.1的倍数 如果时间间隔为0 则表示不会启用更新函数
*/
virtual void addTouchUpdateCallback(const alSkillTouchCallback& callback,float interval);
/**
添加技能CD结束后的回调
*/
virtual void addSkillCDEndCallback(const alSkillCDEndCallback& callback);
protected:
virtual bool init() override;
virtual bool init(const std::string normalImage,const std::string coolImage,float skillTime);
/**
添加触摸事件
*/
virtual void addTouchListener();
/**
执行技能按钮触摸开始操作
*/
virtual bool doSkillTouchBegin(const Point& touchPoint);
/**
执行技能按钮触摸移动操作
*/
virtual void doSkillTouchMoved(const Point& touchPoint);
/**
执行技能按钮触摸结束操作
*/
virtual void doSkillTouchEnd(const Point& touchPoint);
/**
开始技能冷却
*/
virtual void startSkillCDAction();
/**
重置技能冷却
*/
virtual void resetSkillCDAction();
/**
减少冷却时间
*/
virtual void reduceSkillCDTimeAction(float time);
protected:
Sprite* _pSkill;
ProgressTimer* _pProgressCD;
//** 技能是否可用 *//
CC_PROPERTY_PASS_BY_REF(bool, _skillEnable, SkillEnable);
//** 技能是否处于冷却时间 *//
bool _isSkillCD = false;
//** 技能冷却时间 *//
CC_SYNTHESIZE_PASS_BY_REF(float, _skillCoolTime, SkillCoolTime);
//** 技能按压计时更新是否可用 *//
CC_SYNTHESIZE_PASS_BY_REF(bool, _updateEnable, UpdateEnable);
//** 按压时间 *//
CC_SYNTHESIZE_READONLY_PASS_BY_REF(float, _pressTime, PressTime);
//** *//
float _tUpdateInerval = 0;
std::string _normalImageName;
std::string _coolImageName;
alSkillClickCallback _clickCallback;
alSkillTouchCallback _touchBeginCallback;
alSkillTouchCallback _touchEndCallback;
alSkillClickCallback _touchUpdateCallback;
alSkillCDEndCallback _skillCDEndCallback;
private:
//** 是否技能触摸结束 *//
bool _isSkillTouchEnd = true;
//** 更新时间增量数,主要用于 *//
float _deltaSum = 0;
};
#endif /* SkillButton_h */
SkillButton.cpp
#include "SkillButton.h"
#define SCHEDULE_SKILL_UPDATE_TIME "SCHEDULE_SKILL_UPDATE_TIME"
#define SKILL_UPDATE_INTERVAL 0.1
SkillButton::SkillButton()
{
_pSkill = nullptr;
_pProgressCD = nullptr;
_skillEnable = true;
_skillCoolTime = 0;
_isSkillCD = false;
_updateEnable = false;
_pressTime = 0;
_tUpdateInerval = 0;
_normalImageName = "";
_coolImageName ="";
_clickCallback = nullptr;
_touchBeginCallback = nullptr;
_touchEndCallback = nullptr;
_touchUpdateCallback = nullptr;
_skillCDEndCallback = nullptr;
_deltaSum = 0;
}
SkillButton::~SkillButton()
{
}
SkillButton* SkillButton::create(const std::string normalImage,const std::string coolImage,float skillTime)
{
SkillButton* skillBtn = new (std::nothrow) SkillButton();
if (skillBtn && skillBtn->init(normalImage, coolImage, skillTime)) {
return skillBtn;
}else{
CC_SAFE_DELETE(skillBtn);
return nullptr;
}
}
bool SkillButton::init()
{
if (Node::init()) {
return true;
}
return false;
}
bool SkillButton::init(const std::string normalImage, const std::string coolImage, float skillTime)
{
if (init()) {
_skillCoolTime = skillTime;
setupNormalImage(normalImage);
setupCoolImage(coolImage);
addTouchListener();
return true;
}
return false;
}
void SkillButton::addTouchListener()
{
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(false);
listener->onTouchBegan = [this](Touch* touch, Event* evnt)->bool
{
return this->doSkillTouchBegin(touch->getLocation());
};
listener->onTouchMoved = [this](Touch* touch, Event* evnt)
{
this->doSkillTouchMoved(touch->getLocation());
};
auto touchEndedCallback = [this](Touch* touch, Event* evnt)
{
this->doSkillTouchEnd(touch->getLocation());
};
listener->onTouchCancelled = touchEndedCallback;
listener->onTouchEnded = touchEndedCallback;
Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
}
bool SkillButton::doSkillTouchBegin(const Point& touchPoint)
{
// 判断点击区域
Size contentSize = _pSkill->getContentSize();
Rect btnRect = Rect(this->getPositionX() - contentSize.width/2, this->getPositionY()- contentSize.height/2, contentSize.width, contentSize.height);
if (btnRect.containsPoint(touchPoint)) {
if (_skillEnable && !_isSkillCD) {
// 开启计时器
if (_updateEnable) {
unschedule(SCHEDULE_SKILL_UPDATE_TIME);
_pressTime = 0;
_deltaSum = 0;
schedule([this](float delta){
_pressTime += delta;
_pressTime = (float)((int)(_pressTime * 1000 + 0.5f))/1000;//保留小数点后三位
if (_tUpdateInerval>= delta && _touchUpdateCallback)
{
_deltaSum+= delta;
_deltaSum = (float)((int)(_deltaSum * 1000 + 0.5f))/1000;// 保留小数点后三位
if (_deltaSum >= _tUpdateInerval) {
_touchUpdateCallback(_pressTime);
_deltaSum = 0;
}
}
}, SKILL_UPDATE_INTERVAL, SCHEDULE_SKILL_UPDATE_TIME);
}
// 调用开始回调
if (_touchBeginCallback) {
_touchBeginCallback(0);
}
_isSkillTouchEnd = false;
return true;
}
}
_isSkillTouchEnd = true;
return false;
}
void SkillButton::doSkillTouchMoved(const cocos2d::Point &touchPoint)
{
if (!_isSkillTouchEnd) {
Size touchSize = Size(_pSkill->getContentSize().width*1.2, _pSkill->getContentSize().height*1.2);
Rect touchRect = Rect(this->getPositionX() - touchSize.width/2, this->getPositionY()- touchSize.height/2, touchSize.width, touchSize.height);
if (!touchRect.containsPoint(touchPoint)) {
this->doSkillTouchEnd(touchPoint);
}
}
}
void SkillButton::doSkillTouchEnd(const Point& touchPoint)
{
if (!_isSkillTouchEnd)
{
// 停止计时器
unschedule(SCHEDULE_SKILL_UPDATE_TIME);
float pressTime = _pressTime;
_pressTime = 0;
_deltaSum = 0;
if (_touchEndCallback) {
_touchEndCallback(pressTime);
}
if (_clickCallback) {
_clickCallback(pressTime);
}
// 开始读冷却
this->startSkillCDAction();
_isSkillTouchEnd = true;
}
}
void SkillButton::startSkillCDAction()
{
if (_skillCoolTime > 0) {
_isSkillCD = true;
_pProgressCD->setPercentage(100);
_pProgressCD->stopAllActions();
_pProgressCD->runAction(Sequence::create(ProgressTo::create(_skillCoolTime, 0),CallFunc::create([this]{
// 技能冷却结束
_isSkillCD = false;
// 技能冷却完成后的回调
if (_skillCDEndCallback) {
_skillCDEndCallback();
}
}), NULL));
}else{
_pProgressCD->stopAllActions();
_pProgressCD->setPercentage(0);
_isSkillCD = false;
// 技能冷却完成后的回调
if (_skillCDEndCallback) {
_skillCDEndCallback();
}
}
}
void SkillButton::resetSkillCDAction()
{
if (_isSkillCD) {
_pProgressCD->stopAllActions();
_pProgressCD->setPercentage(0);
_isSkillCD = false;
// 技能冷却完成后的回调
if (_skillCDEndCallback) {
_skillCDEndCallback();
}
}
}
void SkillButton::reduceSkillCDTimeAction(float time)
{
if (_isSkillCD) {
_pProgressCD->stopAllActions();
float percent = _pProgressCD->getPercentage();
float remainingTime = MIN(0, percent*_skillCoolTime - time);
if (remainingTime > 0) {
float nowPercent = 100.f / _skillCoolTime * remainingTime;
_pProgressCD->setPercentage(nowPercent);
_pProgressCD->runAction(Sequence::create(ProgressTo::create(remainingTime, 0),CallFunc::create([this]{
// 技能冷却结束
_isSkillCD = false;
// 技能冷却完成后的回调
if (_skillCDEndCallback) {
_skillCDEndCallback();
}
}), NULL));
}else{
resetSkillCDAction();
}
}
}
//============================
// !!!: public
//============================
void SkillButton::setSkillEnable(const bool &enable)
{
if (_skillEnable != enable) {
_skillEnable = enable;
if (!_skillEnable) {
_pProgressCD->stopAllActions();
_pProgressCD->setPercentage(100);
_isSkillCD = true;
}
}
}
const bool& SkillButton::getSkillEnable() const
{
return _skillEnable;
}
void SkillButton::setupNormalImage(const std::string normalImage)
{
_normalImageName = normalImage;
CCASSERT(!normalImage.empty(), "SkillButton : normalImage is empty");
auto frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(normalImage);
if (_pSkill) {
(frame ? _pSkill->setSpriteFrame(frame) : _pSkill->setSpriteFrame(normalImage));
}else{
_pSkill = frame ? Sprite::createWithSpriteFrame(frame) : Sprite::create(normalImage);
this->addChild(_pSkill,0);
}
setContentSize(_pSkill->getContentSize());
if (_coolImageName.empty()) {
setupCoolImage("");
}
}
void SkillButton::setupCoolImage(const std::string coolImage)
{
_coolImageName = coolImage;
Sprite* coolSprite = nullptr;
if (coolImage.empty()) {
auto frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(_normalImageName);
coolSprite = frame ? Sprite::createWithSpriteFrame(frame) : Sprite::create(_normalImageName);
coolSprite->setColor(Color3B(64, 64, 64));
}else{
auto frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(coolImage);
coolSprite = frame ? Sprite::createWithSpriteFrame(frame) : Sprite::create(coolImage);
}
if (_pProgressCD) {
_pProgressCD->setSprite(coolSprite);
}else{
_pProgressCD = ProgressTimer::create(coolSprite);
_pProgressCD->setType(ProgressTimer::Type::RADIAL);
_pProgressCD->setReverseProgress(true);
_pProgressCD->setPercentage(0);
this->addChild(_pProgressCD,1);
}
}
void SkillButton::addClickCallback(const SkillButton::alSkillClickCallback &callback)
{
_clickCallback = callback;
}
void SkillButton::addTouchBeginCallback(const SkillButton::alSkillTouchCallback &callback)
{
_touchBeginCallback = callback;
}
void SkillButton::addTouchEndCallback(const SkillButton::alSkillTouchCallback &callback)
{
_touchEndCallback = callback;
}
void SkillButton::addTouchUpdateCallback(const SkillButton::alSkillTouchCallback &callback, float interval)
{
if (interval >= SKILL_UPDATE_INTERVAL) {
_touchUpdateCallback = callback;
_tUpdateInerval = interval;
}
}
void SkillButton::addSkillCDEndCallback(const alSkillCDEndCallback& callback)
{
_skillCDEndCallback = callback;
}
网友评论