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

精灵的攻击也是一个动画,只不过,这个动画只播放一次,相当于在界面上加一个按钮,然后你点一次按钮,精灵就播放一次动画。

cocos2d-x版本:2.2.5

工程环境:windows7+VS2010

目录

一、自定义按钮类

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

三、自定义按钮控制精灵

一、自定义按钮类

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

#ifndef __ControlButton_H__

#define __ControlButton_H__

#include “cocos2d.h”

#include “cocos-ext.h”

USING_NS_CC;

USING_NS_CC_EXT;

//用于标识当前按钮的状态

typedef enum{

touch_begin,

touch_down,

touch_up,

}tagForTouch;

class ControlButton :public CCNode

{

public:

ControlButton();

~ControlButton();

CREATE_FUNC(ControlButton);

//创建按钮,其中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(CCObject* pSender, CCControlEvent event);

/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标进入按钮范围,则触发一次 */

void touchDragEnter(CCObject* pSender, CCControlEvent event);

/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标离开按钮范围,则触发一次 */

void touchDragExit(CCObject* pSender, CCControlEvent event);

/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标进入按钮范围,则触发,只要达到条件,就不断触发 */

void touchDragInside(CCObject* pSender, CCControlEvent event);

/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标离开按钮范围,则触发,只要达到条件,就不断触发 */

void touchDragOutside(CCObject* pSender, CCControlEvent event);

/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标松开且在按钮范围内,则触发一次 */

void touchUpInside(CCObject* pSender, CCControlEvent event);

/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标松开且在按钮范围外,则触发一次 */

void touchUpOutside(CCObject* pSender, CCControlEvent event);

/* 暂时没有发现能用鼠标触发这个事件的操作,看了注释,应该是由其它事件中断按钮事件而触发的 */

void touchCancel(CCObject* pSender, CCControlEvent event);

//是否按下按钮

bool isTouch;

private:

//按钮控件变量

CCControlButton* controlBtn;

};

#endif

ControlButton.cpp文件

#include “ControlButton.h”

ControlButton::ControlButton():controlBtn(NULL),isTouch(false)

{

}

ControlButton::~ControlButton()

{

}

void ControlButton::CreateButton(const char* name_png,const char* button_title,unsigned int num)

{

//得到按钮图片的大小

CCScale9Sprite* btn = CCScale9Sprite::create(name_png);

CCLOG(“%f”,btn->getContentSize().width);

CCLOG(“%f”,btn->getContentSize().height);

intpng_height=static_cast<int>(btn->getContentSize().height);

intpng_width=static_cast<int>( btn->getContentSize().width);

btn->release();

//要显示的图片大小

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);//设置可见度

//正常状态下的按钮图片

CCScale9Sprite *btnNormal = CCScale9Sprite::create(name_png,rect,rectInsets);

//创建按钮

controlBtn = CCControlButton::create(title,btnNormal);

this->addChild(controlBtn);

//绑定事件

BindButtonEven();

}

void ControlButton::BindButtonEven()

{

if(!controlBtn)

return;

controlBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(ControlButton::touchDownAction),CCControlEventTouchDown);

controlBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(ControlButton::touchDragEnter),CCControlEventTouchDragEnter);

controlBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(ControlButton::touchDragExit),CCControlEventTouchDragExit);

controlBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(ControlButton::touchDragInside),CCControlEventTouchDragInside);

controlBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(ControlButton::touchDragOutside),CCControlEventTouchDragOutside);

controlBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(ControlButton::touchUpInside),CCControlEventTouchUpInside);

controlBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(ControlButton::touchUpOutside),CCControlEventTouchUpOutside);

controlBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(ControlButton::touchCancel),CCControlEventTouchCancel);

}

/* 当鼠标处于按下并曾经点中按钮时,则触发一次 */

void ControlButton::touchDownAction(CCObject* pSender, CCControlEvent event)

{

isTouch=true;

}

/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标进入按钮范围,则触发一次 */

void ControlButton::touchDragEnter(CCObject* pSender, CCControlEvent event)

{

}

/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标离开按钮范围,则触发一次 */

void ControlButton::touchDragExit(CCObject* pSender, CCControlEvent event)

{

}

/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标进入按钮范围,则触发,只要达到条件,就不断触发 */

void ControlButton::touchDragInside(CCObject* pSender, CCControlEvent event)

{

}

/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标离开按钮范围,则触发,只要达到条件,就不断触发 */

void ControlButton::touchDragOutside(CCObject* pSender, CCControlEvent event)

{

}

/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标松开且在按钮范围内,则触发一次 */

void ControlButton::touchUpInside(CCObject* pSender, CCControlEvent event)

{

isTouch=false;

}

/* 当鼠标处于按下并曾经点中按钮的状态下,鼠标松开且在按钮范围外,则触发一次 */

void ControlButton::touchUpOutside(CCObject* pSender, CCControlEvent event)

{

}

/* 暂时没有发现能用鼠标触发这个事件的操作,看了注释,应该是由其它事件中断按钮事件而触发的 */

void ControlButton::touchCancel(CCObject* pSender, CCControlEvent event)

{

}

使用方法:

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

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

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

//添加攻击按钮

btn=ControlButton::create();

btn->CreateButton(“bt.png”);

btn->setPosition(ccp(visibleSize.width-50,50));

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();

然后相应的实现

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 =CCArray::createWithCapacity(num);

unsigned int i;

for(i=1;i<=num;i++)

{

CCSpriteFrame* frame=m_frameCache->spriteFrameByName(CCString::createWithFormat(“%s%d.png”,name_each,i)->getCString());

frameArray->addObject(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

下来我们来看看效果吧~


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