首先非常感谢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,bool run_directon); Animation* getAnimation(const char *name_plist,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,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,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",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,bool run_directon) { if(IsAttack) return; auto ani = getAnimation(name_plist,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,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,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,Point position) { Sprite *spRockerBG = Sprite::create(rockerBGImageName); spRockerBG->setPosition(position); spRockerBG->setVisible(false); addChild(spRockerBG,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~-180 if (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) { } }
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",rocker->rocketRun); hero->setPosition(Vec2(hero->getPosition().x,hero->getPosition().y+1)); break; case 3: hero->SetAnimation("run_animation.plist",rocker->rocketRun); hero->setPosition(Vec2(hero->getPosition().x-1,hero->getPosition().y)); break; case 4: hero->SetAnimation("run_animation.plist",hero->getPosition().y-1)); break; default: hero->StopAnimation(); break; } }
PS:多写博客,帮助自己,方便他人!
原文链接:https://www.f2er.com/cocos2dx/344547.html