制作横版游戏KillBear第7课:攻击判定 伤害飘血

游戏有了地图、英雄以及有一定AI判定的敌人,那么接下来战斗是必须要有的。这一课将在前面的基础上让攻击有效,创建攻击判定,当Hero攻击敌人时会出现伤害值显示。

开发环境

Win64 : vs2010

Cocos2d-x v3.4Final

TexturePackerGUI

MapEdit

代码

Role

Hero

我们直接在.cpp和.h中加入返回判定:

.h

void Hero::attackCallBackAction(Node* pSender);//普通攻击回调

void Hero::FontsCallBackAction(Node* pSender);//数字淡出回调

void Hero::damageDisplay(int number,Vec2 point);//产生伤害数字动画

.cpp

void Hero::attackCallBackAction(Node* pSender)

{//普通攻击回调

__Array* pEnemies = global->enemies ;

Ref *enemyObj = NULL;

//遍历所有怪物

CCARRAY_FOREACH(pEnemies, enemyObj)

{

Enemy *pEnemy = (Enemy*)enemyObj;

if(fabsf(this->getPosition().y - pEnemy->getPosition().y) < 20)

{

Rect attackReck = m_hitBox.actual;//英雄攻击区域

Rect hurtReck = pEnemy->getBodyBox().actual;;//怪物受伤区域

if(attackReck.intersectsRect(hurtReck))

{

pEnemy->setAllowMove(false);

pEnemy->runHurtAction();

int damage = random(this->getDamageStrenth()*0.7,this->getDamageStrenth()*1.3);

pEnemy->setCurtLifeValue(pEnemy->getCurtLifeValue() - damage);

if(pEnemy->getCurtLifeValue() <= 0)

{

pEnemy->runDeadAction();

pEnemy->setBodyBox(createBoundingBox(Vec2::ZERO, Size::ZERO));

}

}

}

}

//this->runIdleAction();

}

然后不要忘了在上方攻击序列创建的时候加入判定:

//普通攻击A,分出招和收招,期间夹杂攻击判定.自己可以通过调节fps控制出招速度之类的

Animation *attackAnima1 = this->createAttackAnimation("boy_attack_00_d.png", 0, 4, 10);

Animation *attackAnima2 = this->createAttackAnimation("boy_attack_00_d.png", 4, 8, 15);

this->setNomalAttackA(Sequence::create(

Animate::create(attackAnima1),

CallFuncN::create(CC_CALLBACK_1(Hero::attackCallBackAction,this)),

Animate::create(attackAnima2),

Role::createIdleCallbackFunc(),NULL));

效果

 

20150210111748867.gif

 

20150210111758195.gif

Enemy

同样在敌人加入攻击判定。

就不贴.h了,同样注意在动作创建的时候加入攻击判定:

void Enemy::attackCallBackAction(Node* pSender)

{

Hero* t_hero = global->hero;

Rect attackReck = m_hitBox.actual;//怪物攻击区域

Rect hurtReck = t_hero->getBodyBox().actual;//英雄受伤区域

if(attackReck.intersectsRect(hurtReck))

{

t_hero->setAllowMove(false);

int damage = this->getDamageStrenth();

t_hero->runHurtAction();

t_hero->setCurtLifeValue(t_hero->getCurtLifeValue() - damage);

}

if(t_hero->getCurtLifeValue() <= 0)

{

t_hero->runDeadAction();

t_hero->setBodyBox(createBoundingBox(Vec2::ZERO, Size::ZERO));

}

}

效果

 

20150210112153054.gif

我们在Hero攻击回调一个伤害显示函数,显示伤害值,过会儿自己消失掉:

void Hero::FontsCallBackAction(Node* pSender)

{

//数字淡出回调

global->gameLayer->removeChild(pSender);

}

void Hero::damageDisplay(int number,Vec2 point)

{

//产生数字动画

auto atLabel = Label::create();

//char ch[100]={0};

//sprintf(ch,"-%d",number);

atLabel->setString(__String::createWithFormat("-%d",number)->getCString());

atLabel->setSystemFontSize(18);

atLabel->setColor(Color3B(0,0,128));

atLabel->setPosition(point);

global->gameLayer->addChild(atLabel,200);

FiniteTimeAction * callFuncN = CallFuncN::create(atLabel, callfuncN_selector(Hero::FontsCallBackAction));

FiniteTimeAction *sequence = Sequence::create(

//FadeIn::create(1.5f),

ScaleTo::create(0.2f,1.3f),

MoveBy::create(0.2f,Vec2(0,20)),

FadeOut::create(0.5f),

callFuncN,

NULL);

atLabel->runAction(sequence);

}

被忘了在上面的attackCallBackAction中加入

1damageDisplay(damage , pEnemy->getBodyBox().actual.origin);

效果

 

20150210112635726.gif

结语

攻击判定框在前面在刚创建的时候已经设定了。对于此类游戏来说,最复杂也是最困难的就是各种判定了。

本Demo只是一个演示效果,所以全部的攻击判定只用了一个判定框

最好的方式是,单独给每一种动作,创建受击和攻击判定.。是一个相当繁琐的工作。

对于攻击动作来说,在动作进行当中添加判定比刚开始或者是结束后添加更加的真实。

每一个动作也可以放多个攻击判定实现多段攻击,效果如击飞(据攻击方向相反出移动一定距离),上挑(Y轴移动一定距离)。

下一篇,将添加一个有冷却的按钮实现Hero技能攻击。