Cocos2d-x自定义按钮类控制精灵攻击----之游戏开发《赵云要格斗》(2) cocos2dx 3.3移植版

 源码:git@github.com:baidang201/ARPG_Zhaoyun.git

/搬运

转载请注明出处http://blog.csdn.net/evankaka/article/details/42063515

本篇要讲讲怎么自定义按钮类,并通过这个按钮类的对像来控制精灵的攻击。在看本篇之前最好先看看上一篇

Cocos2d-x虚拟摇杆控制精灵上下左右运动----之游戏开发《赵云要格斗》(1),要素材和项目代码的把邮箱留下吧,因为这个项目还没弄完,我一直在改。

        精灵的攻击也是一个动画,只不过,这个动画只播放一次,相当于在界面上加一个按钮,然后你点一次按钮,精灵就播放一次动画。这里之所以自定义按钮类是为了后头方便能添加多个按钮来实现英雄不同的攻击方式。以及技能冷却等。

cocos2d-x版本:2.2.5

工程环境:windows7+VS2010

打开方式:将工程放在cocos2d-x安装目录下的project文件夹下用VS打开

目录

一、自定义按钮类

二、精灵攻击动画和结束判断

三、自定义按钮控制精灵

四、移植总结


一、自定义按钮类

按钮可以用COCOS2D-X自带的,想着方便一点,我就自己封装了一个按钮类MyControlButton,在里面添加一个//按钮控件变量ControlButton* controlBtn;并对其添加相应的回调事件即可实现我们自己封装的按钮类

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
#ifndef __ControlButton_H__
#define __ControlButton_H__
#include "cocos2d.h"
#include "cocos-ext.h"
#include "ui/UIScale9Sprite.h"
 
 
USING_NS_CC;
USING_NS_CC_EXT; 
//用于标识当前按钮的状态
typedef enum{
	touch_begin,
	touch_down,
	touch_up,
}tagForTouch;
class MyControlButton :public CCNode
{
public:
    MyControlButton();
    ~MyControlButton();
    CREATE_FUNC(MyControlButton);
	//创建按钮,其中name_png为按钮的背景图片,button_title为按钮图片上要显示的文字,num为文字的透明度0-100,0为透明
	 void CreateButton(const char* name_png,const char* button_title="0",unsigned int num=0);
	//绑写按钮事件 
	void BindButtonEven();
	/* 当鼠标处于按下并曾经点中按钮时,则触发一次 */ 
    void touchDownAction(Ref* pSender, Control::EventType event);
	/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标进入按钮范围,则触发一次 */  
    void touchDragEnter(Ref* pSender, Control::EventType event);
	/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标离开按钮范围,则触发一次 */  
    void touchDragExit(Ref* pSender, Control::EventType event);
	/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标进入按钮范围,则触发,只要达到条件,就不断触发 */  
    void touchDragInside(Ref* pSender, Control::EventType event);
	/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标离开按钮范围,则触发,只要达到条件,就不断触发 */ 
    void touchDragOutside(Ref* pSender, Control::EventType event);
	/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标松开且在按钮范围内,则触发一次 */
    void touchUpInside(Ref* pSender, Control::EventType event);
	/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标松开且在按钮范围外,则触发一次 */  
    void touchUpOutside(Ref* pSender, Control::EventType event);
	/* 暂时没有发现能用鼠标触发这个事件的操作,看了注释,应该是由其它事件中断按钮事件而触发的 */ 
    void touchCancel(Ref* pSender, Control::EventType event);
	//是否按下按钮
	bool isTouch;
private:
	//按钮控件变量
    ControlButton* controlBtn;
};
#endif 
 

ControlButton.cpp文件

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include "ControlButton.h"
    MyControlButton::MyControlButton():controlBtn(NULL),isTouch(false)
    {
    }
    MyControlButton::~MyControlButton()
    {
     
    }
    void MyControlButton::CreateButton(const char* name_png,const char* button_title,unsigned int num)
    {
    	//得到按钮图片的大小 
        Scale9Sprite* btn = Scale9Sprite::create(name_png);
        CCLOG("%f",btn->getContentSize().width);
        CCLOG("%f",btn->getContentSize().height);
        int  png_height=static_cast<int>(btn->getContentSize().height);
        int  png_width=static_cast<int>( btn->getContentSize().width);
    //  btn->autorelease();
     
        //要显示的图片大小
        CCRect rect = CCRectMake(0,0,png_width,png_height);   //图片的大小
        CCRect rectInsets = CCRectMake(1,1,1,1); //left,right,width,height
     
        //按钮标题,Marker Felt为字体类型,png_height为字体高度
        CCLabelTTF *title = CCLabelTTF::create(button_title, "Marker Felt",png_height-10);
        title->setOpacity(num);//设置可见度
     
        //正常状态下的按钮图片
        Scale9Sprite *btnNormal = Scale9Sprite::create(name_png,rect,rectInsets);
    	
        //创建按钮
        controlBtn = ControlButton::create(title, btnNormal);
        this->addChild(controlBtn);
        //绑定事件
        BindButtonEven();
    	
    	
    }
    void MyControlButton::BindButtonEven()
    {
    	if(!controlBtn)
    		return;
        controlBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(MyControlButton::touchDownAction),Control::EventType::TOUCH_DOWN);
        controlBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(MyControlButton::touchDragEnter),Control::EventType::DRAG_ENTER);
        controlBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(MyControlButton::touchDragExit),Control::EventType::DRAG_EXIT);
        controlBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(MyControlButton::touchDragInside),Control::EventType::DRAG_INSIDE);
        controlBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(MyControlButton::touchDragOutside),Control::EventType::DRAG_OUTSIDE);
        controlBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(MyControlButton::touchUpInside),Control::EventType::TOUCH_UP_INSIDE);
        controlBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(MyControlButton::touchUpOutside),Control::EventType::TOUCH_UP_OUTSIDE);
        controlBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(MyControlButton::touchCancel),Control::EventType::TOUCH_CANCEL);
    }
    /* 当鼠标处于按下并曾经点中按钮时,则触发一次 */  
    void MyControlButton::touchDownAction(Ref* pSender, Control::EventType event)
    {
    	isTouch=true;
     
    }
    /* 当鼠标处于按下并曾经点中按钮的状态下,鼠标进入按钮范围,则触发一次 */  
    void MyControlButton::touchDragEnter(Ref* pSender, Control::EventType event)
    {
    	
    }
    /* 当鼠标处于按下并曾经点中按钮的状态下,鼠标离开按钮范围,则触发一次 */  
    void MyControlButton::touchDragExit(Ref* pSender, Control::EventType event)
    {
    	
    }
    /* 当鼠标处于按下并曾经点中按钮的状态下,鼠标进入按钮范围,则触发,只要达到条件,就不断触发 */  
    void MyControlButton::touchDragInside(Ref* pSender, Control::EventType event)
    {
     
    }
    /* 当鼠标处于按下并曾经点中按钮的状态下,鼠标离开按钮范围,则触发,只要达到条件,就不断触发 */  
    void MyControlButton::touchDragOutside(Ref* pSender, Control::EventType event)
    {
     
    }
    /* 当鼠标处于按下并曾经点中按钮的状态下,鼠标松开且在按钮范围内,则触发一次 */  
    void MyControlButton::touchUpInside(Ref* pSender, Control::EventType event)
    {
    	isTouch=false;
     
    }
     
    /* 当鼠标处于按下并曾经点中按钮的状态下,鼠标松开且在按钮范围外,则触发一次 */  
    void MyControlButton::touchUpOutside(Ref* pSender, Control::EventType event)
    {
    	
     
    }
    /* 暂时没有发现能用鼠标触发这个事件的操作,看了注释,应该是由其它事件中断按钮事件而触发的 */ 
    void MyControlButton::touchCancel(Ref* pSender, Control::EventType event)
    {
     
    }
     

.cpp中保留了一些按钮的事件,如果后头有需要或者你有什么需要可以直接拿去改,十分方便。

使用方法:

在要用到的地方加头文件#include "ControlButton.h"

定义成员变量: ControlButton* btn;//按钮控件变量

在bool HelloWorld::init()函数里添加:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //添加攻击按钮  
  2.     btn=ControlButton::create();  
  3.     btn->CreateButton("bt.png");  
  4.     btn->setPosition(ccp(visibleSize.width-50,50));  
  5.     this->addChild(btn,2);  
我们来看看效果



二、精灵攻击动画和结束判断

按钮有了,接下来要想想怎么来控制精灵攻击的动画呢?
精灵攻击的动画应该是我们按下按钮,他就播放一次动画,这里为小心,如果我们连着按按钮很快呢?这时精灵就会动得很不真实,我们应该每次按下前要先判断上次的动画是否结束,如果结束,而且又按下按钮,那么就就放攻击的动画,如果上次的动画还没结束,那就不再播放攻击的动画。
这时,我想起了,在Hero.h(上篇中的)定义 bool I sAttack成员变量,默认为false;。在攻击就是true,然后在攻击动画结束后把它设为false,
同时增加两个函数
 //攻击动画
void AttackAnimation(const char *name_plist,const char *name_png,const char *name_each,const unsigned int num,bool run_directon);
//攻击动画结束
void AttackEnd();

然后相应的实现
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void Hero::AttackAnimation(const char *name_plist,const char *name_png,const char *name_each,const unsigned int num,bool run_directon)
      {
    	  if(IsAttack)
    		  return;
    	  //将图片加载到精灵帧缓存池
    	 m_frameCache=CCSpriteFrameCache::sharedSpriteFrameCache();
         m_frameCache->addSpriteFramesWithFile(name_plist,name_png);
         frameArray = Vector<CCSpriteFrame*>();
    	  unsigned int i;
    	  for(i=1;i<=num;i++)
    	  {
    		  CCSpriteFrame* frame=m_frameCache->spriteFrameByName(CCString::createWithFormat("%s%d.png",name_each,i)->getCString());
              frameArray.pushBack(frame);
    	  }
    	  //使用列表创建动画对象
    	  CCAnimation* animation=CCAnimation::createWithSpriteFrames(frameArray);
    	  if(HeroDirecton!=run_directon)
    	  {   HeroDirecton=run_directon;
     
    	  }
    	  animation->setLoops(1);//表示循环播放次
    	  animation->setDelayPerUnit(0.1f);//每两张图片的时间隔,图片数目越少,间隔最小就越小
     
    	  //将动画包装成一个动作
    	  CCAnimate* act=CCAnimate::create(animation);
    	  //创建回调动作,攻击结束后调用AttackEnd()
    	  CCCallFunc* callFunc=CCCallFunc::create(this,callfunc_selector(Hero::AttackEnd));
    	  //创建连续动作
    	 CCActionInterval* attackact=CCSequence::create(act,callFunc,NULL);
    	  IsAttack=true;
    	  m_HeroSprite->runAction(attackact); 
     
      }
      void Hero::AttackEnd()
      {
    	  //恢复精灵原来的初始化贴图 
          this->removeChild(m_HeroSprite,true);//把原来的精灵删除掉
    	  m_HeroSprite=CCSprite::create(Hero_name);//恢复精灵原来的贴图样子
    	  m_HeroSprite->setFlipX(HeroDirecton);
    	  this->addChild(m_HeroSprite);
    	   IsAttack=false;
      }
     

上面的创建连续动作是本次的关键点,在每次攻击动画AttackAnimation(...)结束后,它就会调用AttackEnd(),从而我们就可以知道是否在攻击动画了。

三、自定义按钮控制精灵


在最前面我们已添加了ControlButton* btn;//按钮控件变量。。
只需要在void HelloWorld::update(float delta)(这可以看上一篇)增加即可
if(btn->isTouch)
hero->AttackAnimation("attack1_animation.plist","attack1_animation.png","attack_",6,rocker->rocketRun);
这里的attack_表示图片中的公共名称部分,即attack1_animation.png中有6张图片,命名为attack_1.png,attack_2png.....attack_6.png

下来我们来看看效果吧~
看到了没。效果就是这样的,因为攻击动画的图片不是每张都一样大小,所以精灵攻击时的位置和原来的位置有点儿移动,这里只要改改图片就行了,因为图片实在不好弄,所以将就下吧,以后找到好的图片再来换了

四 移植总结

1 类型移植

CCObject*  =》Ref* 

CCControlEvent =》 Control::EventType 

 CCControlEventTouchDown=> Control::EventType::TOUCH_DOWN
 CCControlEventTouchDragEnter=> Control::EventType::DRAG_ENTER
 CCControlEventTouchDragExit=> Control::EventType::DRAG_EXIT
 CCControlEventTouchDragInside=> Control::EventType::DRAG_INSIDE
 CCControlEventTouchDragOutside=> Control::EventType::DRAG_OUTSIDE
 CCControlEventTouchUpInside=> Control::EventType::TOUCH_UP_INSIDE
 CCControlEventTouchUpOutside=> Control::EventType::TOUCH_UP_OUTSIDE
 CCControlEventTouchCancel=> Control::EventType::TOUCH_CANCEL



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值