Cocos2d-x血条跟随怪物运动--之游戏开发《赵云要格斗》(5)cocos2dx 3.3移植版
本章在前面的基础上《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();
for ( int 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();
for ( int 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();
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);
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();
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); //动画循环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
:如下是示例代码:
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);
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移植版相关推荐
- Cocos2d-x血条跟随怪物运动----之游戏开发《赵云要格斗》(5)
这里是Evankaka的博客,欢迎大家前面讨论与交流------ 转载请注明出处http://blog.csdn.net/evankaka/article/details/4249474 ...
- Cocos2d-X 3.4版-血条跟随怪物运动《赵云要格斗》
血条跟随怪物运动,当然非常容易想到的就是通过组合的方式将一个怪物精灵和 以前我们制作的ProgressView放在一起,然后通过就像他头像放在血量条旁边一样, 通过位置的一些计算让怪物们在头顶,顶上一 ...
- Cocos2d-x怪物智能AI怪物也有智商--之游戏开发《赵云要格斗》(6) cocos2dx 3.3移植版
源码:git@github.com:baidang201/ARPG_Zhaoyun.git 本文将主要来讲讲游戏开发中的怪物智能,一个好的游戏一般怪物都要分等级,这样我们游戏玩起来才有意思,怪物如果智 ...
- cocos creator屏幕适配fitHeight / fitWidth,手机端竖屏,pc端浏览器适配,pc分辨率全屏适配,血条跟随的适配
一,使用creator3.3.2 分别实现手机端和浏览器的适配效果如下 打包web-mobile(居然会有这种需求 /流汗!) pc浏览器显示 手机端显示 1.首先在项目中设置分辨率 和默认适配 这里 ...
- slider unity 头顶血条_Unity开发者教程:人物血条跟随的功能开发(一)
相信各位菜鸟用UGUI做人物血条跟随时都会遇到大坑,今天就来说说如何用UGUI来做人物血条跟随. 第一种: 把Canvas画布作为Player的子物体. 首先:布置一下场景,简单的地面和一个胶囊人物. ...
- unity 血条跟随
2020.2版本以后移除了2D Sprite 添加2D Sprite 1.unity血条跟随...............-C#文档类资源-CSDN下载 2.找到Square复制到UISprite文件 ...
- 【javascript】运动与游戏开发
[javascript]运动与游戏开发 一.学习运动框架作用 二.运动原理 三.定时器 3.1. **倒计定时器:timer=setTimeout(函数名,delaytime);** 3.2. **循 ...
- 简单利用HUDText插件实现血条和怪物伤害减血效果
以前没接触这个插件时,做的小demo中实现怪物血条使用GUI绘制的 (就是雨松大大的方法,很经典 在这里先谢过大大) 用这个插件实现怪物血条只需简单的几部 方法直接封装好的 直接用就好 该插件必须是在 ...
- NGUI血条制作及血条跟随角色目标
首先建2个Sprite一个做背景一个做前景: 给背景添加一个脚本如图progress bar Script.然后拖到对应的位置.然后就就ok了... 接下来就开始设置目标跟随.首先建立一个Cube作为 ...
最新文章
- 企业shell编程基础问题解决实践-是骡子是马溜溜!
- 删除Windows 系统快捷方式箭头 Delete Windows Shortcuct Arrows
- 命令行 笔记本键盘禁用_宏碁发布Enduro系列三防笔记本电脑和平板电脑
- 《PostgreSQL服务器编程》一一1.8 程序设计最佳实践
- update关联其他表批量更新数据-跨数据库-跨服务器Update时关联表条件更新
- 报错:/BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3512.29.5/UITableView.m:7943解决方法
- 基于GPU的大规模图计算系统与应用
- .NET(WinCE、WM)开发转Android开发 ——Xamarin和Smobiler对比...
- vue移动端实现word在线预览
- python内置函数用来返回序列中所有元素之和_Python内置函数——compile
- 总结一些pr的快捷键,让你的剪辑速度翻倍~
- 深度解析volatile关键字,就是这么简单
- 22_多点电容触摸屏驱动
- 上海亚商投顾:沪指高开低走 钠离子电池、储能概念崛起
- win10 cmd窗口中文乱码,永久解决方法
- fedora14安装出错
- 1、第一次亲密接触Linux
- python--计算两个中文字符串的编辑距离
- GameMei 简网APP工场
- 【周鸿祎】给创业者的三个建议:融…