Cocos2d-X 3.4版-怪物的AI《赵云要格斗》

引述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:多写博客,帮助自己,方便他人!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值