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

本章在前面的基础上《Cocos2d-x自定义血条及其美化--之游戏开发《赵云要格斗》(4)》设计一个怪物类,并实现怪物的上方显示血条,血条跟随怪物的运动而运动。用到的血条类在上一讲中,平时我们游戏一般怪物都是头顶一个血条的,这里我们就是要实现这个功能。

Cocos2d-x版本:2.2.5

工程环境:windows7+VS2010

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

重要说明:由于TexturePacker试用期结束了,不能再用,所以接下来的动画都不合成plist和整张的PNG。同时,之前的赵云图像太动画效果不是很好,所以换了个赵云的图片。另外,将整个项目的类都分别归档,这样更加容易看懂些,所以hero.h和hero.cpp有些函数进行了更改,同时调用的地方也改了下。这里一定要注意!

这是本章的一个效果:

(下一章的效果)

一、更改英雄hero类

赵云的图片:以下中是一部分,动画就是通过读一张一张的PNG图片来实现的(没有再合成Plist和整张PNG)

更改后的英雄类Hero.h(类的函数和变量还是不变的,使用方法还是不变的,只不SetAnimation函数参数更改变了)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef __HERO_H__
#define __HERO_H__
#include "cocos2d.h"
using namespace cocos2d;
 class Hero:public cocos2d::CCNode
 {
     public:
       Hero(void);
      ~Hero(void);
     //根据图片名创建英雄
     void InitHeroSprite(char *hero_name);
     //设置动画,num为图片数目,run_directon为精灵脸朝向,false朝右,name_each为name_png中每一小张图片的公共名称部分
     void SetAnimation(const char *name_each,const unsigned int num,bool run_directon);
    //停止动画
     void StopAnimation();
     //攻击动画
     void AttackAnimation(const char *name_each,const unsigned int num,bool run_directon);
     //攻击动画结束
     void AttackEnd();
     //判断英雄是否运动到了窗口的中间位置,visibleSize为当前窗口的大小  
     bool JudgePositona(CCSize visibleSize);  
    //判断是否在跑动画
     bool IsRunning;
     //判断是否在攻击动画
     bool IsAttack;
     //英雄运动的方向
     bool HeroDirecton;
     CREATE_FUNC(Hero);
     private:
     CCSprite* m_HeroSprite;//精灵
     char *Hero_name;//用来保存初始状态的精灵图片名称
 };
#endif // __HERO_H__

更改后的英雄类Hero.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include "Hero.h"
USING_NS_CC; 
Hero::Hero(void)
{
    IsRunning=false;//没在放动画
    HeroDirecton=false;//向右运动
    Hero_name=NULL;
    IsAttack=false;
}
Hero::~Hero(void)
{
}
 void Hero::InitHeroSprite(char *hero_name)
 {
    Hero_name=hero_name;
    this->m_HeroSprite=CCSprite::create(hero_name);
    this->addChild(m_HeroSprite);
 }
 void Hero::SetAnimation(const char *name_each,unsigned int num,bool run_directon)
 {
     if(HeroDirecton!=run_directon)
     {   HeroDirecton=run_directon;
         m_HeroSprite->setFlipX(run_directon);
     }
     if(IsRunning)
         return;
     CCAnimation* animation = CCAnimation::create();  
     forint i=1;i<=num;i++)  
     {  
         char szName[100] = {0};  
         sprintf(szName,"%s%d.png",name_each,i);  
         animation->addSpriteFrameWithFileName(szName); //加载动画的帧  
     }  
     animation->setDelayPerUnit(0.1f);  
     animation->setRestoreOriginalFrame(true);  
     animation->setLoops(-1); //动画循环
     if(HeroDirecton!=run_directon)
     {   HeroDirecton=run_directon;
     }
     //将动画包装成一个动作
     CCAnimate* act=CCAnimate::create(animation);
     
     m_HeroSprite->runAction(act);
     IsRunning=true;
 }
 void Hero::StopAnimation()
 {
     if(!IsRunning)
         return;
    m_HeroSprite->stopAllActions();//当前精灵停止所有动画
    //恢复精灵原来的初始化贴图 
    this->removeChild(m_HeroSprite,TRUE);//把原来的精灵删除掉
    m_HeroSprite=CCSprite::create(Hero_name);//恢复精灵原来的贴图样子
    m_HeroSprite->setFlipX(HeroDirecton);
    this->addChild(m_HeroSprite);
    IsRunning=false;
 }
  void Hero::AttackAnimation(const char *name_each,const unsigned int num,bool run_directon)
  {
      if(IsAttack)
          return;
      IsAttack=true;
      CCAnimation* animation = CCAnimation::create();  
      forint i=1;i<=num;i++)  
      {  
          char szName[100] = {0};  
          sprintf(szName,"%s%d.png",name_each,i);  
          animation->addSpriteFrameWithFileName(szName); //加载动画的帧  
      }  
      animation->setDelayPerUnit(0.05f);  
      animation->setRestoreOriginalFrame(true);  
      animation->setLoops(1); //动画循环
      if(HeroDirecton!=run_directon)
      {   HeroDirecton=run_directon;
      }
      //将动画包装成一个动作
      CCAnimate* act=CCAnimate::create(animation);
      //创建回调动作,攻击结束后调用AttackEnd()
      CCCallFunc* callFunc=CCCallFunc::create(this,callfunc_selector(Hero::AttackEnd));
      //创建连续动作
     CCActionInterval* attackact=CCSequence::create(act,callFunc,NULL);
       
      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;
  }
  bool Hero::JudgePositona (CCSize visibleSize)
  {
      if(this->getPositionX()!=visibleSize.width/2)//精灵到达左边
          return false;
      else
          return true;//到达中间位置
  }

记得在用的地方要改下SetAnimation,其它地方都不变,只不SetAnimation函数参数更改变了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
void HelloWorld::update(float delta)
{
     
    //判断是否按下摇杆及其类型
    CCSize visibleSize1 = CCDirector::sharedDirector()->getVisibleSize();//得到窗口大小
    switch(rocker->rocketDirection)
    {
    case  1:
        hero->SetAnimation("hero_run",8,rocker->rocketRun);
        if(hero->getPositionX()<=visibleSize1.width-8)//不让精灵超出右边,8可以改成你喜欢的
        {
            if(!hero->JudgePositona(visibleSize1)||mymap->JudgeMap(hero,visibleSize1))//精灵没到达窗口中间位置或者地图已经移动到边缘了,精灵才可以移动,否则只播放动画
                hero->setPosition(ccp(hero->getPosition().x+1,hero->getPosition().y)); //向右走
            //下面是移动地图
            mymap->MoveMap(hero,visibleSize1);
        }
        break;
    case  2:
        hero->SetAnimation("hero_run",8,rocker->rocketRun);
        hero->setPosition(ccp(hero->getPosition().x, hero->getPosition().y+1));   //向上走
        break;
    case 3:
        hero->SetAnimation("hero_run",8,rocker->rocketRun);
        if(hero->getPositionX()>=8)//不让精灵超出左边,8可以改成你喜欢的
            hero->setPosition(ccp(hero->getPosition().x-1,hero->getPosition().y));   //向左走
        break;
    case 4:
        hero->SetAnimation("hero_run",8,rocker->rocketRun);
        hero->setPosition(ccp(hero->getPosition().x,hero->getPosition().y-1));   //向下走
        break;
    case 0:
        hero->StopAnimation();//停止所有动画和运动
        break;
    }
    //判断是否出动攻击
    if(btn->isTouch)
    {
        if(hero->IsAttack)//英雄没在攻击
            return;
        hero->AttackAnimation("hero_attack",20,rocker->rocketRun);
        m_pProgressView->setCurrentProgress(m_pProgressView->getCurrentProgress()-10); //更改血量
    }
}

效果:和以前相比,赵云的图片更加清楚了些,而且攻击的图片也比较顺了一点(20张图片啊!)

二、自定义带血条的怪物

这里的血条用到了前面的自定义血条,思路就是把上篇自定义的血条类ProgressView应用在Monster中,得到Monster类中怪物的位置,然后根据这个位置来设置血条成员变量的位置(一般在上方),最后把怪物精灵和血条类都addchild()进来就行了。

下面这是怪物的资源:(一部分,动画也是通过一张一张的播放的)

Monster.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#ifndef __Monster_H__
#define __Monster_H__
#include "cocos2d.h"
#include "ProgressView.h"
USING_NS_CC;
class Monster:public cocos2d::CCNode
{
    public:
    Monster(void);
    ~Monster(void);
    //根据图片名创建怪物,不带血条
    void InitMonsterSprite(char *name);
    //带血条的怪物 
    void InitMonsterSprite(char *name,char *xue_back,char* xue_fore);
    //设置动画,num为图片数目,run_directon为精灵脸朝向,false朝右,name_each为name_png中每一小张图片的公共名称部分
    void SetAnimation(const char *name_each,const unsigned int num,bool run_directon);
    //停止动画
    void StopAnimation();
    //攻击动画
    void AttackAnimation(const char *name_each,const unsigned int num,bool run_directon);
    //攻击动画结束
    void AttackEnd();
    //返回英雄
    CCSprite* GetSprite();
    //判断是否在跑动画
    bool IsRunning;
    //判断是否在攻击动画
    bool IsAttack;
    //英雄运动的方向
    bool MonsterDirecton;
    CREATE_FUNC(Monster);
    private:
    CCSprite* m_MonsterSprite;//怪物精灵
    char *Monster_name;//用来保存初始状态的精灵图片名称
    ProgressView*  Monster_xue;//怪物血条
     
};
#endif // __HERO_H__

Monster.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include "Monster.h"
USING_NS_CC; 
Monster::Monster(void)
{
    IsRunning=false;//没在放动画
    MonsterDirecton=TRUE;//向右运动
    Monster_name=NULL;
    IsAttack=false;
    Monster_xue=NULL;
}
Monster::~ Monster(void)
{
}
CCSprite* Monster::GetSprite()
{
    return m_MonsterSprite;
}
void  Monster::InitMonsterSprite(char *name)
{
    Monster_name=name;
    this->m_MonsterSprite=CCSprite::create(name);
        m_MonsterSprite->setFlipX(MonsterDirecton);
    this->addChild(m_MonsterSprite);
}
void Monster::InitMonsterSprite(char *name,char *xue_back,char* xue_fore)
{
    InitMonsterSprite(name);
    //设置怪物的血条 
    Monster_xue = new ProgressView();  
    Monster_xue->setPosition(ccp(m_MonsterSprite->getPositionX()+25, m_MonsterSprite->getPositionY()+50));//设置在怪物上头  
    //Monster_xue->setScale(2.2f);  
    Monster_xue->setBackgroundTexture(xue_back);  
    Monster_xue->setForegroundTexture(xue_fore);  
    Monster_xue->setTotalProgress(300.0f);  
    Monster_xue->setCurrentProgress(300.0f); 
    this->addChild(Monster_xue);
}
void  Monster::SetAnimation(const char *name_each,unsigned int num,bool run_directon)
{
    if(MonsterDirecton!=run_directon)
    {   MonsterDirecton=run_directon;
    m_MonsterSprite->setFlipX(run_directon);
    }
    if(IsRunning||IsAttack)
        return;
    CCAnimation* animation = CCAnimation::create();  
    forint i=1;i<=num;i++)  
    {  
        char szName[100] = {0};  
        sprintf(szName,"%s%d.png",name_each,i);  
        animation->addSpriteFrameWithFileName(szName); //加载动画的帧  
    }  
    animation->setDelayPerUnit(2.8f / 14.0f);  
    animation->setRestoreOriginalFrame(true);  
    animation->setLoops(-1); //动画循环
    //将动画包装成一个动作
    CCAnimate* act=CCAnimate::create(animation);
    m_MonsterSprite->runAction(act);
    IsRunning=true;
}
void  Monster::StopAnimation()
{
    if(!IsRunning)
        return;
    m_MonsterSprite->stopAllActions();//当前精灵停止所有动画
    //恢复精灵原来的初始化贴图 
    this->removeChild(m_MonsterSprite,TRUE);//把原来的精灵删除掉
    m_MonsterSprite=CCSprite::create(Monster_name);//恢复精灵原来的贴图样子
    m_MonsterSprite->setFlipX(MonsterDirecton);
    this->addChild(m_MonsterSprite);
    IsRunning=false;
}
void  Monster::AttackAnimation(const char *name_each,const unsigned int num,bool run_directon)
{
    if(IsAttack||IsRunning)
        return;
    CCAnimation* animation = CCAnimation::create();  
    forint i=1;i<=num;i++)  
    {  
        char szName[100] = {0};  
        sprintf(szName,"%s%d.png",name_each,i);  
        animation->addSpriteFrameWithFileName(szName); //加载动画的帧  
    }  
    animation->setDelayPerUnit(2.8f / 14.0f);  
    animation->setRestoreOriginalFrame(true);  
    animation->setLoops(1); //动画循环1次  
    //将动画包装成一个动作
    CCAnimate* act=CCAnimate::create(animation);
    //创建回调动作,攻击结束后调用AttackEnd()
    CCCallFunc* callFunc=CCCallFunc::create(this,callfunc_selector(Monster::AttackEnd));
    //创建连续动作
    CCActionInterval* attackact=CCSequence::create(act,callFunc,NULL);
    m_MonsterSprite->runAction(attackact);  
    IsAttack=true;
}
void Monster::AttackEnd()
{
    //恢复精灵原来的初始化贴图 
    this->removeChild(m_MonsterSprite,TRUE);//把原来的精灵删除掉
    m_MonsterSprite=CCSprite::create(Monster_name);//恢复精灵原来的贴图样子
    m_MonsterSprite->setFlipX(MonsterDirecton);
    this->addChild(m_MonsterSprite);
    IsAttack=false;
}

使用方法:

  • HelloWorldScene.h添加头文件 #include "Monster.h"

  • HelloWorldScene.h添加成员变量: Monster *monster1;//怪物种类1

  • HelloWorldScene.cpp的Init()函数进行初始化:

这是不带血条的怪物:

1
2
3
4
5
6
//添加怪物
monster1=Monster::create();
monster1->InitMonsterSprite("monster.png");
//monster1->InitMonsterSprite("monster.png","xue_back.png","xue_fore.png");
monster1->setPosition(ccp(visibleSize.width-150,visibleSize.height/2));
this->addChild(monster1,1);

这是带血条的怪物:

1
2
3
4
5
6
//添加怪物
monster1=Monster::create();
//monster1->InitMonsterSprite("monster.png");
monster1->InitMonsterSprite("monster.png","xue_back.png","xue_fore.png");
monster1->setPosition(ccp(visibleSize.width-150,visibleSize.height/2));
this->addChild(monster1,1);

好了,这一篇就结束了,下一篇我们将会来讲讲智能怪物,让怪物动起来并能出动攻击!

下面是血条跟随怪物移动的效果。

源码下载:血条跟随怪物运动

//

总结下TexturePacker纹理的调用和多个图片调用的区别。

1  压缩纹理的调用

将压缩纹理图片载入全局纹理缓存CCSpriteFrameCache-》获取精灵框帧CCSpriteFrame,将特定序列的精灵框帧增加到列表-》使用列表初始化动画Animation-》使用动画包装成动作CCAnimate

2 多个图片的调用

使用创建动画对象Animation->动画增加每一帧的图片->动画包装成动作CCAnimate

:如下是示例代码:

《1  压缩纹理
    CCSpriteFrameCache *m_frameCache=CCSpriteFrameCache::sharedSpriteFrameCache();
     m_frameCache->addSpriteFramesWithFile(name_plist,name_png);
     //用一个列表保存所有的CCSpriteFrameCache
     Vector<CCSpriteFrame*>  frameArray = Vector<CCSpriteFrame*>();
     unsigned int i;
     for(i=startIndex;i<=num;i++)
     {
         CCSpriteFrame* frame=m_frameCache->spriteFrameByName(CCString::createWithFormat("%s%d.png", actNameInNamePng, i)->getCString());
         frameArray.pushBack(frame);
     }
     //使用列表创建动画对象
     Animation* animation=Animation::createWithSpriteFrames(frameArray);
     animation->setLoops(-1);//表示无限循环播放
     animation->setDelayPerUnit(0.1f);//每两张图片的时间隔,图片数目越少,间隔最小就越小
     //将动画包装成一个动作
     CCAnimate* act=CCAnimate::create(animation);
     m_HeroSprite->runAction(act);
《2 多个图片的调用
CCAnimation* animation = CCAnimation::create();  
for( int i=1;i<=num;i++)  
{  
char szName[100] = {0};  
sprintf(szName,"%s%d.png",name_each,i);  
animation->addSpriteFrameWithFileName(szName); //加载动画的帧  
}  
animation->setDelayPerUnit(2.8f / 14.0f);  
animation->setRestoreOriginalFrame(true); //动画播放结束后,回到初始帧 
animation->setLoops(-1); //动画循环
//将动画包装成一个动作
CCAnimate* act=CCAnimate::create(animation);
m_MonsterSprite->runAction(act);

Cocos2d-x血条跟随怪物运动--之游戏开发《赵云要格斗》(5)cocos2dx 3.3移植版相关推荐

  1. Cocos2d-x血条跟随怪物运动----之游戏开发《赵云要格斗》(5)

      这里是Evankaka的博客,欢迎大家前面讨论与交流------      转载请注明出处http://blog.csdn.net/evankaka/article/details/4249474 ...

  2. Cocos2d-X 3.4版-血条跟随怪物运动《赵云要格斗》

    血条跟随怪物运动,当然非常容易想到的就是通过组合的方式将一个怪物精灵和 以前我们制作的ProgressView放在一起,然后通过就像他头像放在血量条旁边一样, 通过位置的一些计算让怪物们在头顶,顶上一 ...

  3. Cocos2d-x怪物智能AI怪物也有智商--之游戏开发《赵云要格斗》(6) cocos2dx 3.3移植版

    源码:git@github.com:baidang201/ARPG_Zhaoyun.git 本文将主要来讲讲游戏开发中的怪物智能,一个好的游戏一般怪物都要分等级,这样我们游戏玩起来才有意思,怪物如果智 ...

  4. cocos creator屏幕适配fitHeight / fitWidth,手机端竖屏,pc端浏览器适配,pc分辨率全屏适配,血条跟随的适配

    一,使用creator3.3.2 分别实现手机端和浏览器的适配效果如下 打包web-mobile(居然会有这种需求 /流汗!) pc浏览器显示 手机端显示 1.首先在项目中设置分辨率 和默认适配 这里 ...

  5. slider unity 头顶血条_Unity开发者教程:人物血条跟随的功能开发(一)

    相信各位菜鸟用UGUI做人物血条跟随时都会遇到大坑,今天就来说说如何用UGUI来做人物血条跟随. 第一种: 把Canvas画布作为Player的子物体. 首先:布置一下场景,简单的地面和一个胶囊人物. ...

  6. unity 血条跟随

    2020.2版本以后移除了2D Sprite 添加2D Sprite 1.unity血条跟随...............-C#文档类资源-CSDN下载 2.找到Square复制到UISprite文件 ...

  7. 【javascript】运动与游戏开发

    [javascript]运动与游戏开发 一.学习运动框架作用 二.运动原理 三.定时器 3.1. **倒计定时器:timer=setTimeout(函数名,delaytime);** 3.2. **循 ...

  8. 简单利用HUDText插件实现血条和怪物伤害减血效果

    以前没接触这个插件时,做的小demo中实现怪物血条使用GUI绘制的 (就是雨松大大的方法,很经典 在这里先谢过大大) 用这个插件实现怪物血条只需简单的几部 方法直接封装好的 直接用就好 该插件必须是在 ...

  9. NGUI血条制作及血条跟随角色目标

    首先建2个Sprite一个做背景一个做前景: 给背景添加一个脚本如图progress bar Script.然后拖到对应的位置.然后就就ok了... 接下来就开始设置目标跟随.首先建立一个Cube作为 ...

最新文章

  1. 企业shell编程基础问题解决实践-是骡子是马溜溜!
  2. 删除Windows 系统快捷方式箭头 Delete Windows Shortcuct Arrows
  3. 命令行 笔记本键盘禁用_宏碁发布Enduro系列三防笔记本电脑和平板电脑
  4. 《PostgreSQL服务器编程》一一1.8 程序设计最佳实践
  5. update关联其他表批量更新数据-跨数据库-跨服务器Update时关联表条件更新
  6. 报错:/BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3512.29.5/UITableView.m:7943解决方法
  7. 基于GPU的大规模图计算系统与应用
  8. .NET(WinCE、WM)开发转Android开发 ——Xamarin和Smobiler对比...
  9. vue移动端实现word在线预览
  10. python内置函数用来返回序列中所有元素之和_Python内置函数——compile
  11. 总结一些pr的快捷键,让你的剪辑速度翻倍~
  12. 深度解析volatile关键字,就是这么简单
  13. 22_多点电容触摸屏驱动
  14. 上海亚商投顾:沪指高开低走 钠离子电池、储能概念崛起
  15. win10 cmd窗口中文乱码,永久解决方法
  16. fedora14安装出错
  17. 1、第一次亲密接触Linux
  18. python--计算两个中文字符串的编辑距离
  19. GameMei 简网APP工场
  20. 【周鸿祎】给创业者的三个建议:融…

热门文章

  1. 水墨风格小程序/小程序云开发/小程序练手
  2. docker+kubernets-蔡超-专题视频课程
  3. 对于游戏动漫有非常浓厚的兴趣进来看看,干货满满哦
  4. 地理行业的dom、dsm dtm分别是什么?
  5. 移动软件开发五——仿微信发现界面
  6. 信用社考试计算机知识点,2010年农村信用社计算机知识点考题
  7. Ericsson1876
  8. Sqlalchemy with_entities函数用法
  9. 如何用注册表删除Win10桌面上的顽固IE图标
  10. 利用do……while语句,计算1!+2!+3!+……+100!