上一篇我们讲了如何利用纹理资源生成了精灵的动画.这一篇我们讲一讲如何点击屏幕设置目的地,让小精灵走向目的地.
首先我们要在场景类中覆盖这几个函数
void Scene1::onEnter()
{
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,0,false);
CCLayer::onEnter();
}
void Scene1::onExit()
{
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
CCLayer::onExit();
}
bool Scene1::ccTouchBegan(CCTouch *pTouch,CCEvent *pEvent)
{
return true;
}
void Scene1::ccTouchMoved(CCTouch* pTouch,CCEvent* event)
{
}
void Scene1::ccTouchEnded(CCTouch* pTouch,CCEvent* event)
{
hero->move(pTouch->getLocation());
}
onEnter()函数中addTargetedDelegate(this,0,false);注册一个触屏事件委托,用来监听用户的触屏事件.以响应用户的触屏动作.
onExit()函数中removeDelegate(this);移除触屏事件的委托.
ccTouchEnded(CCTouch* pTouch,CCEvent* event);中对人物进行移动.在这个函数里响应是当用户手指离开屏幕后才做出响应,给用户的感觉是点击后人物才响应,而不是触摸上去后马上就响应.
hero的move函数详细我们见下面Hero.cpp文件
#include "Hero.h"
using namespace cocos2d;
//英雄初始化函数
bool Hero::init()
{
size = CCDirector::sharedDirector()->getWinSize();
speed = 100;
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("Haku.plist"); //获得精灵资源
//面向下方静止第一帧
downFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("Haku_01.png"); //获得站立时的第一帧
//创建4方向动作动画
downAni = createAnimate("","Haku_01.png","Haku_02.png","Haku_03.png","Haku_04.png",NULL);
downAni->retain();
upAni = createAnimate("","Haku_13.png","Haku_14.png","Haku_15.png","Haku_16.png",NULL);
upAni->retain();
leftAni = createAnimate("","Haku_05.png","Haku_06.png","Haku_07.png","Haku_08.png",NULL);
leftAni->retain();
rightAni = createAnimate("","Haku_09.png","Haku_10.png","Haku_11.png","Haku_12.png",NULL);
rightAni->retain();
//创建精灵设置位置
sprite = CCSprite::spriteWithSpriteFrame(downFrame);
sprite->setPosition(CCPointZero);
this->addChild(sprite);
return true;
}
Hero::~Hero()
{
downAni->release();
upAni->release();
leftAni->release();
rightAni->release();
}
//创建动画对象
CCAnimate* Hero::createAnimate(const char *frameName,...)
{
//保存该动画所有帧
CCArray *animateFrames = CCArray::create();
va_list argp; //可变参数的参数列表
const char *para; //保存当前取出的参数
va_start(argp,frameName); //开始获得参数
while(1)
{
para = va_arg(argp,const char *); //循环取出可变参数,从第2个参数开始
if(para==NULL) //可变参数以NULL参数作为结尾,如果遇到该参数结束循环
break;
//通过帧图片名生成精灵帧
CCSpriteFrame *frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(para);
animateFrames->addObject(frame);
}
//生成动画
CCAnimation *animation = CCAnimation::animationWithSpriteFrames(animateFrames,0.2f);
CCAnimate *animate = CCAnimate::actionWithAnimation(animation);
return animate;
}
//通过计算获得英雄移动方向
void Hero::move(const cocos2d::CCPoint& position)
{
float hx = this->getPositionX(); //英雄当前x坐标
float hy = this->getPositionY(); //英雄当前y坐标
float px = position.x; //目标x坐标
float py = position.y; //目标y坐标
float xlength = px - hx; //x方向距离
float ylength = py - hy; //y方向距离
//第一象限
if((px>hx && py>hy))
{
if(abs(xlength)>=abs(ylength))
move(position,RIGHT);
else
move(position,UP);
}
//第二象限
else if(px<hx && py>hy)
{
if(abs(xlength)>=abs(ylength))
move(position,LEFT);
else
move(position,UP);
}
//第三象限
else if(px<hx && py<hy)
{
if(abs(xlength)>=abs(ylength))
move(position,LEFT);
else
move(position,DOWN);
}
//第四象限
else if(px>py && py<hy)
{
if(abs(xlength)>=abs(ylength))
move(position,RIGHT);
else
move(position,DOWN);
}
}
//英雄移动函数
//带入目的点坐标,
void Hero::move(const cocos2d::CCPoint& position,HeroState phs)
{
this->stopAllActions(); //英雄停止动作
sprite->stopAllActions(); //停止精灵的动画
CCMoveTo *moveToAction; //移动对象
//向左
if(phs==LEFT)
{
float t = abs(position.x - this->getPositionX())/speed;
moveToAction = CCMoveTo::actionWithDuration(t,ccp(position.x,this->getPositionY()));
sprite->runAction(CCRepeatForever::actionWithAction(leftAni));
}
//向上
else if(phs==UP)
{
float t = abs(position.y - this->getPositionY())/speed;
moveToAction = CCMoveTo::actionWithDuration(t,ccp(this->getPositionX(),position.y));
sprite->runAction(CCRepeatForever::actionWithAction(upAni));
}
//向右
else if(phs==RIGHT)
{
float t = abs(position.x - this->getPositionX())/speed;
moveToAction = CCMoveTo::actionWithDuration(t,ccp(position.x,this->getPositionY()));
sprite->runAction(CCRepeatForever::actionWithAction(rightAni));
}
//向下
else if(phs==DOWN)
{
float t = abs(position.y - this->getPositionY())/speed;
moveToAction = CCMoveTo::actionWithDuration(t,ccp(this->getPositionX(),position.y));
sprite->runAction(CCRepeatForever::actionWithAction(downAni));
}
CCAction *sequneceAction = CCSequence::actions(moveToAction,CCCallFunc::actionWithTarget(this,callfunc_selector(Hero::stand)),NULL);
this->runAction(sequneceAction);
}
//战立动作
void Hero::stand()
{
sprite->stopAllActions();
}
场景类中调用的move函数是move(const cocos2d::CCPoint& position).参数为人物的目的坐标.通过传入的目的坐标与人物当前场景坐标计算出人物准备移动的方向.程序中我限制了人物只能向上下左右4个方向行走,不能以其他角度行走.
计算出方向后,把目标坐标和方向带入move(const cocos2d::CCPoint& position,HeroState phs).在这个函数中我们根据不同的方向设置人物的精灵播放不同的动画另外要注意的是函数CCMoveTo::actionWithDuration(t,ccp(position.x,this->getPositionY()));参数t是移动到目的地所需的时间.为了保持人物匀速移动,这个时间我们是通过float t = abs(position.x - this->getPositionX())/speed;计算出来的。speed是个速度常量我们在这里设置为100.
CCAction *sequneceAction = CCSequence::actions(moveToAction,CCCallFunc::actionWithTarget(this,callfunc_selector(Hero::stand)),NULL);这句对moveToAction进行了包装,包装后在执行完moveToAction动作后,会执行Hero::stand函数.这样人物在行走到目的地后会执行stand函数停止所有精灵动作.
看看我们今天的成果: