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
- Cocos2d-X 3.4版-虚拟摇杆控制精灵上下左右《赵云要格斗》
- Cocos2d-x虚拟摇杆控制精灵上下左右运动----之游戏开发《赵云要格斗》(1)
- Cocos2d-x虚拟摇杆控制精灵上下左右运动----之游戏开发《赵云要格斗》(1) cocos2dx 3.3移植版
- Cocos2d-x虚拟摇杆控制精灵上下左右运动
- Cocos2d-X 3.4版-按钮控制精灵攻击《赵云要格斗》
- 【Cocos2d-x】新手自学(三)虚拟屏幕摇杆,控制精灵移动
- Cocos2d-x自定义按钮类控制精灵攻击----之游戏开发《赵云要格斗》(2) cocos2dx 3.3移植版
- Cocos2d-x自定义按钮类控制精灵攻击----之游戏开发《赵云要格斗》(2)
- Cocos2d-X 3.4版-扣血飘字 《赵云要格斗》
- Cocos2d-X 3.4版-自定义血量条《赵云要格斗》
- Cocos2d-X 3.4版-怪物的AI《赵云要格斗》
- Cocos2d-X 3.4版-碰撞检测原理《赵云要格斗》
- Cocos2d-X 3.4版-技能冷却按钮《赵云要格斗》
- 【cocos2d-x】之添加虚拟摇杆
- Cocos2d-x格斗小游戏(二) 晃动的玩家精灵
- Cocos2d-x格斗小游戏(四) 移动玩家精灵
- Cocos2d-x格斗小游戏(六) 敌方精灵Robot
- cocos2d-X:RPG摇杆控制英雄
- 字符串模式匹配算法之一:朴素模式匹配算法
- Codeforces Round #290 (Div. 2)
- HDU--2566统计硬币【水题】
- 注册DLL文件命令
- img里的align属性能保证图文的混排效果以及vspace和hspace
- Cocos2d-X 3.4版-虚拟摇杆控制精灵上下左右《赵云要格斗》
- 能做事务的JdbcUtils工具
- QQ空间自动评论自动点赞 微博自动点赞自动转发神器带源码(超简单)
- python中安装cx_Oracle过程中遇到的问题及解决方法
- vijos-1003等价表达式
- Oracle Solaris 11 11/11 新增功能
- 外挂辅助技术-分析任务等级需求并测试
- Linux中变量$#,$@,$0,$1,$2,$*,$$,$?的含义
- Maven部署过程中的ClassCastException问题