Cocos2d-x 怪物智能AI怪物也有智商----之遊戲開發《趙雲要格鬥》(6),怪物彈珠趙雲
這裡是Evankaka的部落格,歡迎大家前面討論與交流~~~~~~
轉載請註明出處http://write.blog.csdn.net/postedit/42611031
這幾天一直在研究怪物的AI,部落格都沒怎麼更新。本文將主要來講講遊戲開發中的怪物智能,一個好的遊戲一般怪物都要分等級,這樣我們遊戲玩起來才有意思,怪物如果智商太高,遊戲難度大。怪物如果智商太低,遊戲玩起來又沒有意思。一般好的遊戲低級怪物和中級怪物佔大部分,進階怪物一般是BOSS級怪物。下面我來講講自己對怪物AI的一些見解吧。本文接上Cocos2d-x 血條跟隨怪物運動----之遊戲開發《趙雲要格鬥》(5)
cocos2d-x版本:2.2.5
工程環境:windows7+VS2010
開啟檔案:將工程放在cocos2d-x安裝目錄下的project檔案夾下用VS開啟
目錄
一、怪物智能AI思路講解
二、Monster類增加函數
三、總結與分析
先看看效果:
一、怪物智能AI思路講解
低級怪物---一般是不能動的怪物,固定在原處,不斷的發動攻擊,然後根據英雄的方位,不斷改變子彈的朝左還是朝向,如遊戲中的炮台等。
中級怪物----初步有一些智商了,主要表現在當英雄在它的攻擊範圍內,能夠知道英雄的位置,就以一定的比例判斷是否進行攻擊。如若不然,平時都是自己按照一定的路線進行行走,又或者是隨機走動。然後攻擊隨機出動,只有當英雄在它的攻擊範圍內,它才會不再走動,原地以機率判斷是否要進行攻擊
進階怪物-----BOSS級怪物,它有自己的可視範圍區,當英雄陷入它的可視範圍區時,它就追著英雄跑。可視範圍區內,還有個攻擊範圍區,當英雄陷入攻擊範圍區內時,怪物就按一定的機率出動攻擊,這個機率一般比較大。然後,如果英雄不在怪物的可視範圍區內時,怪物它有自己的巡邏路線,它按照這個路線不斷的走,總會發現到英雄,英雄你再怎麼跑,它都會跟著你。
當然,上面說的都是比較簡單的了,實際遊戲中怪物還會分得更細,比如有的怪物能自動加血,有的怪物還能召喚等,這裡就不再詳細講下去了,若有興趣,自己再去百度下等,怪物智能這個涉及到人工智慧,深入下去就是演算法的問題了。
(這是我用PS自己弄的,哈哈,還可以吧,程式員PS真應該也稍微學點!)
本文主要是要設定一個進階怪物AI的一個演算法,下面是它的流程圖:
(唉。最煩流程圖了,畫了好一會兒)
下面是本文的一個效果:
二、Monster類增加函數
在上一講的Monster類的增加函數,3秒計算要怎麼來實現呢?其實很簡單,就開一個3秒的計數器事件不就完了嗎?
this->schedule(schedule_selector(Monster::updateMonster),3.0f);//每隔3秒計算距離
然後就是計算怪物和英雄的距離了,這中間涉及到很多判斷,具體可以看上面的演算法流程圖,然後再參考下代碼,注意,
StartListen(CCNode* m_hero,CCNode* m_map)
這是開始啟動怪物監聽英雄的函數。
首先是在Monster.h中添加:
public:
//在可視範圍內,怪物跟隨英雄運動void FollowRun(CCNode* m_hero,CCNode* m_map);//判斷是否攻擊void JudegeAttack();//怪物巡邏路線void MonsterSeeRun();//怪物啟動監聽英雄void StartListen(CCNode* m_hero,CCNode* m_map);//監聽函數,每隔3秒檢測下,計算英雄與怪物的距離void updateMonster(float delta);//更新函數,如果英雄在可視範圍內,不斷觸發void update(float delta);
private:
CCNode* my_hero;//當前英雄CCNode* my_map;//當前地圖float dis;//當前怪物和英雄的距離
然後這是它的實現Monster.cpp:
void Monster::FollowRun(CCNode* m_hero,CCNode* 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)//當怪物與英雄距離超過300return;if(dis<=100)//在怪物攻擊範圍內,怪物停止移動{this->StopAnimation();//停止跑動JudegeAttack();//以一定的機率判斷是是否出動攻擊return;}if(x<-100)//判斷怪物橫座標和英雄的距離{MonsterDirecton=true;m_MonsterSprite->setFlipX(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->setFlipX(MonsterDirecton);//設定方向if(IsAttack)return;this->setPosition(this->getPositionX()+1,this->getPositionY()); this->SetAnimation("monster_run",6,MonsterDirecton);//播放動畫 }else if(x<=100)//怪物橫坐標和英雄相差在100以內時,開始移動怪物縱座標{if(m_hero->getPositionY()>this->getPositionY()){m_MonsterSprite->setFlipX(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->setFlipX(MonsterDirecton);//設定方向if(IsAttack)return;this->setPosition(this->getPositionX(),this->getPositionY()-1);this->SetAnimation("monster_run",6,MonsterDirecton);//播放動畫}}}void Monster::JudegeAttack(){srand((UINT)GetCurrentTime());int x = rand()%100;if(x>98){this->AttackAnimation("monster_attack",5,MonsterDirecton);}}void Monster::MonsterSeeRun(){if(dis<300)return; this->SetAnimation("monster_run",6,MonsterDirecton);//播放動畫 CCMoveBy *moveby1; if(MonsterDirecton==true) moveby1=CCMoveBy::create(2,ccp(-100,0)); else moveby1=CCMoveBy::create(2,ccp(100,0));//建立回調動作,巡邏路線完後CCCallFunc* callFunc=CCCallFunc::create(this,callfunc_selector(Monster::StopAnimation));//建立連續動作CCActionInterval* xunluo=CCSequence::create(moveby1,callFunc,NULL);this->runAction(xunluo);}//啟動監聽void Monster::StartListen(CCNode* m_hero,CCNode* 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);}
這裡要注意一個地方,上一講中:
//添加怪物monster1=Monster::create();//monster1->InitMonsterSprite("monster.png");monster1->InitMonsterSprite("monster.png","xue_back.png","xue_fore.png");monster1->setPosition(ccp(visibleSize.width-50,visibleSize.height/2));this->addChild(monster1,1);改成:
//添加怪物monster1=Monster::create();//monster1->InitMonsterSprite("monster.png");monster1->InitMonsterSprite("monster.png","xue_back.png","xue_fore.png");monster1->setPosition(ccp(visibleSize.width-50,visibleSize.height/2));mymap->addChild(monster1);//將怪物添加到地圖中,這樣怪物才能隨地圖移動monster1->StartListen(hero,mymap);//非常重要,這是這一講用到的
總算完成了,下面看看效果:
1.怪物初始距離和英雄相差300.走巡邏路線
2.英雄在怪物可視範圍內並且在攻擊範圍內
3.怪物跟隨英雄
4.怪物跟隨英雄
三、總結與分析
這裡的怪物只能說一個簡單的進階怪物吧,因為巡邏路線都沒怎麼弄好,我只是讓它左右運動100,好一點的巡邏路線不是這樣的,這裡為了省事,直接弄成簡單了點。另外,這裡還沒弄碰撞檢測,所以你看到英雄從怪物中間穿過,不要驚訝,碰撞檢測我打算後頭現來弄的。另外,怪物跟隨英雄運動的過程中,應該設定一個暫停運動的。這樣英雄就有可能脫離怪物的可視範圍區。如果不這樣做的話,一旦英雄落入怪物的可視範圍區,怪物就會一直追著英雄,這樣,遊戲玩起來難度大了點。這是兩點不足,後頭有時間再來想想怎麼改吧。今天就到這兒了~~
後記:
為了弄這個怪物智能,想了好久,原來只是想弄個簡單的低級怪物,後又想這多沒意思啊。就弄了個進階的(雖說還不算進階),幸好自還了PS,要不好多圖片都搞不定啊!另外,網上百度怪物AI,會出現很多資源的,有興趣的自己去找去吧。有需要的,把郵箱留個哈,我會把工程發給你的~