引述Evankaka博客关于怪物AI的描述,如下:
低级怪物---一般是不能动的怪物,固定在原处,不断的发动攻击,然后根据英雄的方位,不断改变子弹的朝左还是朝向,如游戏中的炮台等。
中级怪物----初步有一些智商了,主要表现在当英雄在它的攻击范围内,能够知道英雄的位置,就以一定的比例判断是否进行攻击。如若不然,平时都是自己按照一定的路线进行行走,又或者是随机走动。然后攻击随机出动,只有当英雄在它的攻击范围内,它才会不再走动,原地以概率判断是否要进行攻击
高级怪物-----BOSS级怪物,它有自己的可视范围区,当英雄陷入它的可视范围区时,它就追着英雄跑。可视范围区内,还有个攻击范围区,当英雄陷入攻击范围区内时,怪物就按一定的概率出动攻击,这个概率一般比较大。然后,如果英雄不在怪物的可视范围区内时,怪物它有自己的巡逻路线,它按照这个路线不断的走,总会发现到英雄,英雄你再怎么跑,它都会跟着你。
主要是通过怪物与玩家的位置关系才去不同的策略,主要功能通过以下的方法实现:
//在可视范围内,怪物跟随英雄运动
void FollowRun(Node* m_hero,Node* m_map);
//判断是否攻击
void JudegeAttack();
//怪物巡逻路线
void MonsterSeeRun();
//怪物启动监听英雄
void StartListen(Node* m_hero,Node* m_map);
//监听函数,每隔3秒检测下,计算英雄与怪物的距离
void updateMonster(float delta);
//更新函数,如果英雄在可视范围内,不断触发
void update(float delta);
Node* my_hero;//当前英雄
Node* my_map;//当前地图
float dis;//当前怪物和英雄的距离
函数实现部分:
void Monster::FollowRun(Node* m_hero,Node* m_map)
{
//得到两点x的距离,记得怪物的坐标要加上地图的
float x = m_hero->getPositionX()-(this->getPositionX()+m_map->getPositionX());
//得到两点y的距离,记得怪物的坐标要加上地图的
float y = m_hero->getPositionY()-(this->getPositionY()+m_map->getPositionY());
//先计算怪物和英雄的距离
dis = sqrt(pow(x,2) + pow(y,2));
if(dis>=300)//当怪物与英雄距离超过300
return;
if(dis<=100)//在怪物攻击范围内,怪物停止移动
{
this->StopAnimation();//停止跑动
JudegeAttack();//以一定的概率判断是是否出动攻击
return;
}
if(x<-100)//判断怪物横坐标和英雄的距离
{
MonsterDirecton=true;
m_MonsterSprite->setFlippedX(MonsterDirecton);//设置方向
if(IsAttack)
return;
this->setPosition(this->getPositionX()-1,this->getPositionY());//怪物向英雄移动
this->SetAnimation("monster_run",6,MonsterDirecton);//播放动画
}
else if(x>100)
{
MonsterDirecton=false;
m_MonsterSprite->setFlippedX(MonsterDirecton);//设置方向
if(IsAttack)
return;
this->setPosition(this->getPositionX()+1,this->getPositionY());
this->SetAnimation("monster_run",6,MonsterDirecton);//播放动画
}
else if(x<=100 || x >-100)//怪物橫坐標和英雄相差在100以内时,开始移动怪物纵坐标
{
if(m_hero->getPositionY()>this->getPositionY())
{
m_MonsterSprite->setFlippedX(MonsterDirecton);//设置方向
if(IsAttack)
return;
this->setPosition(this->getPositionX(),this->getPositionY()+1);
this->SetAnimation("monster_run",6,MonsterDirecton);//播放动画
}
else if(m_hero->getPositionY()<this->getPositionY())
{
m_MonsterSprite->setFlippedX(MonsterDirecton);//设置方向
if(IsAttack)
return;
this->setPosition(this->getPositionX(),this->getPositionY()-1);
this->SetAnimation("monster_run",6,MonsterDirecton);//播放动画
}
}
}
void Monster::JudegeAttack()
{
//srand(time(NULL));
int x = random(0, 100);
log("-------%d", x);
if(x>50)
{
this->AttackAnimation("monster_attack",5,MonsterDirecton);
}
}
void Monster::MonsterSeeRun()
{
if(dis<300)
return;
this->SetAnimation("monster_run",6,MonsterDirecton);//播放动画
MoveBy *moveby1;
if(MonsterDirecton==true)
moveby1=MoveBy::create(1,Vec2(-70,0));
else
moveby1=MoveBy::create(1,Vec2(70,0));
//创建回调动作,巡逻路线完后
// auto callFunc=CallFunc::create(this,callfunc_selector(Monster::StopAnimation));
auto callFunc = CallFunc::create( CC_CALLBACK_0(Monster::StopAnimation,this));
//创建连续动作
auto xunluo=Sequence::create(moveby1,callFunc,NULL);
this->runAction(xunluo);
}
//启动监听
void Monster::StartListen(Node* m_hero,Node* m_map)
{
my_hero=m_hero;
my_map=m_map;
this->schedule(schedule_selector(Monster::updateMonster),3.0f);//每隔3秒计算距离
this->scheduleUpdate();//英雄一旦进入可视范围,怪物追着英雄打
}
//监听函数,每隔3秒检测下
void Monster::updateMonster(float delta)
{
//得到两点x的距离,记得怪物的坐标要加上地图的
float x = my_hero->getPositionX()-(this->getPositionX()+my_map->getPositionX());
//得到两点y的距离,记得怪物的坐标要加上地图的
float y = my_hero->getPositionY()-(this->getPositionY()+my_map->getPositionY());
//先计算怪物和英雄的距离
dis = sqrt(pow(x,2) + pow(y,2));
if(dis>=300)
{
if(!IsRunning)
MonsterSeeRun();
}
}
void Monster::update(float delta)
{
if(dis<300)///当英雄在它的可视范围内,不断追着英雄
FollowRun(my_hero,my_map);
}
对于这一块的讲解Evakaka已经讲的非常明白的了,只不过我第一次看见这句的时候也有点小小的疑惑
//得到两点x的距离,记得怪物的坐标要加上地图的
float x = m_hero->getPositionX()-(this->getPositionX()+m_map->getPositionX());
//得到两点y的距离,记得怪物的坐标要加上地图的
float y = m_hero->getPositionY()-(this->getPositionY()+m_map->getPositionY());
//先计算怪物和英雄的距离
dis = sqrt(pow(x,2) + pow(y,2));
为什么要加上地图的坐标呢,我想表达式要是写成这样会更清晰一些:
//得到两点x的距离,记得怪物的坐标要加上地图的
float x = (m_hero->getPositionX()+m_map->getPositionX())-this->getPositionX();
//得到两点y的距离,记得怪物的坐标要加上地图的
float y = (m_hero->getPositionY()+m_map->getPositionY())-(this->getPositionY());
//先计算怪物和英雄的距离
dis = sqrt(pow(x,2) + pow(y,2));
当hero移动的屏幕一般的时候,hero就只是做移动的动作,而真正移动的是map,所以如果仅仅比较hero和monster的
距离,肯定是要出错的。
工程下载...
PS:多写博客,帮助自己,方便他人!