Cocos2d-X 3.4版-虚拟摇杆控制精灵上下左右《赵云要格斗》

来源:互联网 发布:制作考试软件 编辑:程序博客网 时间:2024/05/04 19:33

首先非常感谢Evankaka大神的无私奉献,传送门:Evankaka神的博客。

在学习大神开源的《赵云要格斗》demo时,为了方便和我一样的小白菜鸟,将其改写为Cocos2d-x3.3版本(根据我个人的理解

做出了一些改动),现在已经改到Evankaka教程的第三节,工作任务少点以后还会陆续更新。

Hero.h:

基于组合优与集成,以及轻量的理念,此类继承自Node即可。

在Hero类里我对SetAnimation,以及AttackAnimation进行了改写,添加了一个函数getAnimation来获取plist文件得到的动作,将其

返回给SetAnimation,AttackAnimation使用。

添加RunEnd运来对run动作结束进行监听。

////  Hero.h//  Fight////  Created by Cytzrs on 15/2/2.////#ifndef __Fight__Hero__#define __Fight__Hero__#include <iostream>#include "cocos-ext.h"using namespace cocos2d;USING_NS_CC_EXT;class Hero:public cocos2d::Node{public:    Hero(void);    ~Hero(void);    //根据图片名创建英雄    void InitHeroSprite(char *hero_name);//设置动画,num为图片数目,run_directon为精灵脸朝向,false朝右,name_each为name_png中每一小张图片的公共名称部分    void SetAnimation(const char *name_plist,const char *name_png,const char *name_each,const unsigned int num,bool run_directon);//停止动画    void StopAnimation();//判断是否在跑动画    bool IsRunning;        bool IsAttack;    //英雄运动的方向    bool HeroDirecton;    CREATE_FUNC(Hero);    //判断英雄是否运动到了窗口的中间位置,visibleSize为当前窗口的大小    bool JudgePositona(Size visibleSize);        void AttackAnimation(const char *name_plist,const char *name_png,const char *name_each,const unsigned int num,bool run_directon);        Animation* getAnimation(const char *name_plist,const char *name_png,const char *name_each,const unsigned int num,bool run_directon);    void RunEnd();    void AttackEnd();private:    Sprite* m_HeroSprite;//精灵    char *Hero_name;//用来保存初始状态的精灵图片名称};#endif /* defined(__Fight__Hero__) */

Hero.cpp

////  Hero.cpp//  Fight////  Created by Cytzrs on 15/2/2.////#include "Hero.h"#include <String.h>USING_NS_CC;USING_NS_CC_EXT;Hero::Hero(void){IsRunning=false;//没在放动画    IsAttack = false;HeroDirecton=false;//向右运动Hero_name=NULL;}Hero::~Hero(void){    }void Hero::InitHeroSprite(char *hero_name){Hero_name=hero_name;this->m_HeroSprite=Sprite::create(hero_name);this->addChild(m_HeroSprite);}//动画播放,可以是跑、攻击、死亡、受伤等void Hero::SetAnimation(const char *name_plist,const char *name_png,const char *name_each,unsigned int num,bool run_directon){    if(HeroDirecton!=run_directon)    {   HeroDirecton=run_directon;        m_HeroSprite->setFlippedX(run_directon);    }    if(IsRunning)        return;    auto ani = getAnimation(name_plist,name_png,name_each,num,run_directon);    auto action = Animate::create(ani);    auto ccback = CallFunc::create(CC_CALLBACK_0(Hero::RunEnd, this));    auto act = Sequence::create(action, ccback, NULL);    m_HeroSprite->runAction(act);        IsRunning=true;}void Hero::RunEnd(){    IsRunning=false;}Animation* Hero::getAnimation(const char *name_plist,const char *name_png,const char *name_each,const unsigned int num,bool run_directon){    auto cache = SpriteFrameCache::getInstance();    cache->addSpriteFramesWithFile(name_plist, name_png);    //    auto sprite = Sprite::createWithSpriteFrameName(String::createWithFormat("%s1.png", name_each)->getCString());        m_HeroSprite->setTexture(CCString::createWithFormat("%s1.png", name_each)->getCString());        auto spriteBatch = SpriteBatchNode::create(name_png);    //    spriteBatch->addChild(sprite);    addChild(spriteBatch);        Vector<SpriteFrame*> animFrames(num);    for(int i = 1; i < num; i++)    {        // Obtain frames by alias name        auto frame = cache->getSpriteFrameByName(String::createWithFormat("%s%d.png", name_each, i)->getCString());        animFrames.pushBack(frame);    }        auto animation = Animation::createWithSpriteFrames(animFrames, 0.3f);        return animation;}void Hero::StopAnimation(){    if(!IsRunning)        return;m_HeroSprite->stopAllActions();//当前精灵停止所有动画    ////恢复精灵原来的初始化贴图//this->removeChild(m_HeroSprite);//把原来的精灵删除掉//m_HeroSprite=Sprite::create(Hero_name);//恢复精灵原来的贴图样子//m_HeroSprite->setFlippedX(HeroDirecton);//this->addChild(m_HeroSprite);IsRunning=false;}bool Hero::JudgePositona (Size visibleSize){    if(this->getPositionX()!=visibleSize.width/2)//精灵到达左边        return false;    else        return true;//到达中间位置}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;        auto ani = getAnimation(name_plist,name_png,name_each,num,run_directon);    auto action = Animate::create(ani);//    auto ccback = CallFunc::create(this,callfunc_selector(Hero::AttackEnd));    auto ccback = CallFunc::create( CC_CALLBACK_0(Hero::AttackEnd,this));    auto act = Sequence::create(action, ccback, NULL);    // 14 frames * 1sec = 14 seconds    m_HeroSprite->runAction(act);    IsAttack=true;    }void Hero::AttackEnd(){    //恢复精灵原来的初始化贴图//    this->removeChild(m_HeroSprite);//把原来的精灵删除掉//    m_HeroSprite=Sprite::create(Hero_name);//恢复精灵原来的贴图样子//    m_HeroSprite->setFlippedX(HeroDirecton);//    this->addChild(m_HeroSprite);    IsAttack=false;}
摇杆类HRocker.h
////  HRocker.h//  Fight////  Created by Cytzrs on 15/2/2.////#ifndef __Fight__HRocker__#define __Fight__HRocker__#include <iostream>#include "cocos2d.h"using namespace cocos2d;//用于标识摇杆与摇杆的背景typedef enum{tag_rocker,tag_rockerBG,}tagForHRocker;//用于标识摇杆方向typedef enum{rocker_stay,rocker_right,rocker_up,rocker_left,rocker_down,}tagDirecton;class HRocker:public Layer{public:HRocker(void);~HRocker(void);    //创建摇杆(摇杆的操作题图片资源名,摇杆背景图片资源名,起始坐标)static HRocker* createHRocker(const char *rockerImageName,const char *rockerBGImageName,Point position);//启动摇杆(显示摇杆、监听摇杆触屏事件)void startRocker(bool _isStopOther);//停止摇杆(隐藏摇杆,取消摇杆的触屏监听)void stopRocker();//判断控制杆方向,用来判断精灵上、下、左、右运动int rocketDirection;//当前人物行走方向,用来判断精灵的朝向,精灵脸朝右还是朝左bool rocketRun;CREATE_FUNC(HRocker);        void update(float dt);private://自定义初始化函数void rockerInit(const char* rockerImageName,const char* rockerBGImageName,Point position);//是否可操作摇杆bool isCanMove;//获取当前摇杆与用户触屏点的角度float getRad(Point pos1,Point pos2);//摇杆背景的坐标Point rockerBGPosition;//摇杆背景的半径float rockerBGR;//触屏事件virtual bool onTouchBegan(Touch *pTouch, Event *pEvent);virtual void onTouchMoved(Touch *pTouch, Event *pEvent);virtual void onTouchEnded(Touch *pTouch, Event *pEvent);    };#endif /* defined(__Fight__HRocker__) */
HRocker.cpp
////  HRocker.cpp//  Fight////  Created by Cytzrs on 15/2/2.////#include "HRocker.h"const double PI=3.1415;HRocker::HRocker(void){rocketRun=false;}HRocker::~HRocker(void){}//创建摇杆(摇杆的操作题图片资源名,摇杆背景图片资源名,起始坐标)HRocker* HRocker::createHRocker(const char *rockerImageName,const char *rockerBGImageName,Point position){HRocker *layer = HRocker::create();if (layer){layer->rockerInit(rockerImageName,rockerBGImageName,position);return layer;}CC_SAFE_DELETE(layer);return NULL;}//自定义初始化函数void HRocker::rockerInit(const char* rockerImageName,const char* rockerBGImageName,Point position){Sprite *spRockerBG = Sprite::create(rockerBGImageName);spRockerBG->setPosition(position);spRockerBG->setVisible(false);addChild(spRockerBG,0,tag_rockerBG);    Sprite *spRocker = Sprite::create(rockerImageName);spRocker->setPosition(position);spRocker->setVisible(false);addChild(spRocker,1,tag_rocker);    rockerBGPosition = position;rockerBGR = spRockerBG->getContentSize().width*0.5;//rocketDirection=-1;//表示摇杆方向不变}//启动摇杆(显示摇杆、监听摇杆触屏事件)void HRocker::startRocker(bool _isStopOther){Sprite *rocker = (Sprite*)this->getChildByTag(tag_rocker);rocker->setVisible(true);    Sprite *rockerBG = (Sprite *)this->getChildByTag(tag_rockerBG);rockerBG->setVisible(true);        auto listener = EventListenerTouchOneByOne::create();    listener->onTouchBegan = CC_CALLBACK_2(HRocker::onTouchBegan, this);    listener->onTouchMoved = CC_CALLBACK_2(HRocker::onTouchMoved, this);    listener->onTouchEnded = CC_CALLBACK_2(HRocker::onTouchEnded, this);    Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);}//停止摇杆(隐藏摇杆,取消摇杆的触屏监听)void HRocker::stopRocker(){Sprite *rocker = (Sprite *)this->getChildByTag(tag_rocker);rocker->setVisible(false);    Sprite * rockerBG = (Sprite *)this->getChildByTag(tag_rockerBG);rockerBG->setVisible(false);        Director::getInstance()->getEventDispatcher()->removeAllEventListeners();}//获取当前摇杆与用户触屏点的角度float HRocker::getRad(Point pos1,Point pos2){float px1 = pos1.x;float py1 = pos1.y;float px2 = pos2.x;float py2 = pos2.y;    //得到两点x的距离float x = px2 - px1;//得到两点y的距离float y = py1 - py2;//算出斜边长度float xie = sqrt(pow(x,2) + pow(y,2));//得到这个角度的余弦值(通过三角函数中的店里:角度余弦值=斜边/斜边)float cosAngle = x / xie;//通过反余弦定理获取到期角度的弧度float rad = acos(cosAngle);//注意:当触屏的位置Y坐标<摇杆的Y坐标,我们要去反值-0~-180if (py2 < py1){rad = -rad;}return rad;}Vec2 getAngelePosition(float r,float angle){return Vec2(r*cos(angle),r*sin(angle));}//抬起事件bool HRocker::onTouchBegan(Touch *pTouch, Event *pEvent){Point point = pTouch->getLocation();Sprite *rocker = (Sprite *)this->getChildByTag(tag_rocker);if (rocker->boundingBox().containsPoint(point)){isCanMove = true;log("begin");}return true;}//移动事件void HRocker::onTouchMoved(Touch *pTouch, Event *pEvent){if (!isCanMove){return;}Point point = pTouch->getLocation();Sprite *rocker = (Sprite *)this->getChildByTag(tag_rocker);//得到摇杆与触屏点所形成的角度float angle = getRad(rockerBGPosition,point);//判断两个圆的圆心距是否大于摇杆背景的半径if (sqrt(pow((rockerBGPosition.x - point.x),2) + pow((rockerBGPosition.y - point.y),2)) >= rockerBGR){        //保证内部小圆运动的长度限制rocker->setPosition(getAngelePosition(rockerBGR,angle) + Vec2(rockerBGPosition.x,rockerBGPosition.y));        //log("touch");}else{//当没有超过,让摇杆跟随用户触屏点移动即可rocker->setPosition(point);//log("touch");}    //判断方向if(angle>=-PI/4&&angle<PI/4){rocketDirection=rocker_right;rocketRun=false;log("%d",rocketDirection);}else if(angle>=PI/4&&angle<3*PI/4){rocketDirection=rocker_up;log("%d",rocketDirection);}else if((angle>=3*PI/4&&angle<=PI)||(angle>=-PI&&angle<-3*PI/4)){rocketDirection=rocker_left;rocketRun=true;log("%d",rocketDirection);}else if(angle>=-3*PI/4&&angle<-PI/4){rocketDirection=rocker_down;log("%d",rocketDirection);}}//离开事件void HRocker::onTouchEnded(Touch *pTouch, Event *pEvent){if (!isCanMove){return;}Sprite *rockerBG = (Sprite*)this->getChildByTag(tag_rockerBG);Sprite *rocker = (Sprite*)this->getChildByTag(tag_rocker);rocker->stopAllActions();rocker->runAction(CCMoveTo::create(0.08f,rockerBG->getPosition()));isCanMove = false;rocketDirection=rocker_stay;log("%d",rocketDirection);log("end");}void HRocker::update(float dt){if(isCanMove){}}

最后一步在Scene中添加update函数:

void HelloWorld::update(float delta){switch(rocker->rocketDirection){        case 1:            hero->SetAnimation("run_animation.plist","run_animation.png",8,rocker->rocketRun);            hero->setPosition(Vec2(hero->getPosition().x+1,hero->getPosition().y));            break;        case  2:            hero->SetAnimation("run_animation.plist","run_animation.png",8,rocker->rocketRun);            hero->setPosition(Vec2(hero->getPosition().x, hero->getPosition().y+1));            break;        case 3:            hero->SetAnimation("run_animation.plist","run_animation.png",8,rocker->rocketRun);            hero->setPosition(Vec2(hero->getPosition().x-1,hero->getPosition().y));            break;        case 4:            hero->SetAnimation("run_animation.plist","run_animation.png",8,rocker->rocketRun);            hero->setPosition(Vec2(hero->getPosition().x,hero->getPosition().y-1));            break;        default:            hero->StopAnimation();            break;            }}


PS:多写博客,帮助自己,方便他人!






2 0
原创粉丝点击