首页 > 代码库 > Cocos2d-x 血条跟随怪物运动----之游戏开发《赵云要格斗》(5)

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

      本章在前面的基础上,设计一个怪物类,并实现怪物的上方显示血条,血条跟随怪物的运动而运动。

重要说明:由于TexturePacker试用期结束了,不能再用,所以接下来的动画都不合成plist和整张的PNG。同时,之前的赵云图像太动画效果不是很好,所以换了个赵云的图片。另外,将整个项目的类都分别归档,这样更加容易看懂些。

技术分享

这是本章的一个效果:

技术分享

技术分享(下一章的效果)


一、更改英雄类

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

技术分享

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

#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
#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函数参数更改变了

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); //更改血量
	}


}

技术分享

技术分享

二、自定义带血条的怪物 

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

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

技术分享

Monster.h:

#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:

#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()函数进行初始化:

这是不带血条的怪物:

	//添加怪物
	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);

技术分享


这是带血条的怪物:

	//添加怪物
	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);

技术分享

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

下面是血条跟随怪物移动的效果(下一章的效果)

技术分享技术分享




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