您的位置:首页 > 移动开发 > Cocos引擎

Cocos2d-x格斗小游戏(四) 移动玩家精灵

2014-08-21 05:43 281 查看
1、前一篇文章,已经打好了方向控制的基础,现在只要将相应的动作实现就能使玩家精灵动起来。

2、首先是Walk(行走)的动作,与Normal状态的左右晃动一样,也需要下加载动作的图片。在SpritePlayer中添加一个函数loadWalkAnimation用于加载Walk动作:

(1)SpritePlayer.h中添加声明:

// 加载Normal动作的图片
bool loadNormalAnimation();
// 加载Walk动作图片
bool loadWalkAnimation();


(2)SpritePlayer.cpp中实现,并在init函数中调用该函数:

bool SpritePlayer::loadWalkAnimation()
{
bool bRct = false;

do
{
CCArray *pWalkFrames = NULL;
pWalkFrames = CCArray::createWithCapacity(8);
CC_BREAK_IF(! pWalkFrames);
for (int i = 0; i < 8; i++)
{
CCSpriteFrame *pSpriteFrame = NULL;
pSpriteFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->
spriteFrameByName(CCString::createWithFormat("hero_walk_%02d.png", i)->
getCString());
pWalkFrames->addObject(pSpriteFrame); // 别忘了添加到数组中
CC_BREAK_IF(! pSpriteFrame);
}
CCAnimation *pWalkAnimation = NULL;
pWalkAnimation = CCAnimation::createWithSpriteFrames(pWalkFrames, 1.0 / 12.0);
CC_BREAK_IF(! pWalkAnimation);
this->setWalkAction(CCRepeatForever::create(CCAnimate::create(pWalkAnimation)));

bRct = true;
} while (0);

return bRct;
}


bool SpritePlayer::init()
{
bool bRct = false;

do
{
CC_BREAK_IF(! SpriteActions::initWithSpriteFrameName("hero_idle_00.png"));
CC_BREAK_IF(! loadNormalAnimation());
CC_BREAK_IF(! loadWalkAnimation());

bRct = true;
} while (0);

return bRct;
}


3、加载了Walk动作后,早SpriteActions中添加几个成员变量及函数,包括当前的人物状态(五种状态之一),移动的方向和速度:

(1)SpriteActions.h中添加以下内容:

// 当前的精灵状态
CC_SYNTHESIZE(SpriteState, _spriteState, SpriteState);

// 移动方向
CC_SYNTHESIZE(cocos2d::CCPoint, _velocity, Velocity);
CC_SYNTHESIZE(cocos2d::CCPoint, _desireMovePos, DesireMovePos);

// 属性
CC_SYNTHESIZE(float, _walkSpeed, WalkSpeed);  // 速度


4、接下出,处理SpritePlayer中的Walk_WithDirection函数(这个函数原来就添加了,但是未实现),此时主要用到的是this->runAction(_walkAction);这一句,执行Walk动作:

void SpriteActions::Walk_WithDirection(cocos2d::CCPoint direction)
{
if (_spriteState == STATE_NORMAL)
{
this->stopAllActions();
this->runAction(_walkAction);
_spriteState = STATE_WALK;
}

if (_spriteState == STATE_WALK)
{
_velocity = ccp(direction.x * _walkSpeed, direction.y * _walkSpeed);
if(_velocity.x >= 0)
{
this->setScaleX(1.0);  // 翻转精灵
}
else
{
this->setScaleX(-1.0);
}
}
}


5、然后,处理GameBasicLayer中未实现的方法:

void GameBasicLayer::ChangeDirection(TouchResponseSprite *touchRsSprite, cocos2d::CCPoint direction)
{
_spritePlayer->Walk_WithDirection(direction);
}

void GameBasicLayer::HoldDirection(TouchResponseSprite *touchRsSprite, cocos2d::CCPoint direction)
{
_spritePlayer->Walk_WithDirection(direction);
}

void GameBasicLayer::TouchEnded(TouchResponseSprite *touchRsSprite)
{
if (_spritePlayer->getSpriteState() == STATE_WALK)
{
_spritePlayer->Normal();
}
}


6、OK,现在玩家精灵已经有一个Walk的动作了,并且能响应虚拟方向键,但是现在玩家精灵只是双腿不断交替,但是相对于背景的位置并未改变,相当于原地踏步,如下图:



7、下面实现任务移动,主要通过计时器函数来不断检测方向,不断移动。现在SpriteActions类中实现update函数:

void SpriteActions::update(float dt)
{
if (_spriteState == STATE_WALK)
{
_desireMovePos = ccpAdd(this->getPosition(), ccpMult(_velocity, dt));
}
}


8、接着,在GameBasicLayer中启动一个计时器:

this->scheduleUpdate();


实现两个函数:

void update(float dt);
void updatePosition();


void GameBasicLayer::update(float dt)
{
_spritePlayer->update(dt);
this->updatePosition();
}

void GameBasicLayer::updatePosition()
{
float actWidth = _tileMap->getMapSize().width * _tileMap->getTileSize().width - _spritePlayer->getSpriteSize().width / 2;
float actHeight = 3 * _tileMap->getTileSize().height + _spritePlayer->getSpriteSize().height / 2;

CCPoint ptActualMovePos;
ptActualMovePos.x = _spritePlayer->getDesireMovePos().x > actWidth ? actWidth : _spritePlayer->getDesireMovePos().x;
ptActualMovePos.y = _spritePlayer->getDesireMovePos().y > actHeight ? actHeight : _spritePlayer->getDesireMovePos().y;

ptActualMovePos.x = MAX(ptActualMovePos.x, _spritePlayer->getSpriteSize().width / 2);
ptActualMovePos.y = MAX(ptActualMovePos.y, _spritePlayer->getSpriteSize().height / 2);

_spritePlayer->setPosition(ptActualMovePos);

}


9、为使精灵不走出地图,或者不走上墙壁,需要对将要移动的位置进行判断。另外,注意一点:精灵调用setPosition设置位置时传入的参数是精灵中点的坐标位置。实际上传入参数需要限制在下图的白色矩形框内:



10、OK,现在可以移动了,但是地图还不会移动:



11、在update函数中调用一个函数来实现滚动地图(基于玩家精灵的位置):

this->setViewToCenter(_spritePlayer->getPosition());


函数实现:

void GameBasicLayer::setViewToCenter(cocos2d::CCPoint ptSpritePlayer)
{
// 得到窗口尺寸
CCSize sz = CCDirector::sharedDirector()->getWinSize();
// 防止窗口移出地图边界
int x = MAX(ptSpritePlayer.x, sz.width/2);  // 左边
int y = MAX(ptSpritePlayer.y, sz.height/2); // 下边
x = MIN(x, _tileMap->getTileSize().width * _tileMap->getMapSize().width - sz.width/2);     // 右边
y = MIN(y, _tileMap->getTileSize().height * _tileMap->getMapSize().height - sz.height/2);  // 上边

CCPoint ptDesire = ccp(x, y);
CCPoint centerOfView = CCPointMake(sz.width/2, sz.height/2);  // 中间点
CCPoint ptActual = ccpSub(centerOfView, ptDesire);

this->setPosition(ptActual);  // 移背景
}


12、地图滚动效果如下:



13、待续
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: