【cocos2d-x 手游研發----怪物智能AI】

>>>  技術話題—商業文明的嶄新時代  >>> 簡體     傳統

原創文章,轉載請注明出處:http://www.cnblogs.com/zisou/p/cocos2d-xARPG4.html

 

談到怪物AI,我覺得就比較話多了,首先理解一下(Artificial Intelligence人工智能),人工智能是計算機科學的一個分支,人工智能是計算機科學技術的前沿科技領域。人工智能與計算機軟件有密切的關系。各種人工智能應用系統都要用計算機軟件去實現,許多聰明的計算機軟件也應用了人工智能的理論方法和技術。

總而言之,言而總之,我理解的AI就是:用人類自己的思考模式去賦予游戲中角色判斷的能力,來進行某些特定的行為!

下面具體圖文介紹一下,我在游戲中一些實用的AI制作思路;

 

 

這是這個思路就可以讓怪物捕獲玩家,并且追蹤玩家攻擊的一個圖示!這個思路是基本,最終決策怪物是否去執行這個行為的操作算法又是一個AI智能,所以咱們又可以分為:

決策AI:可以根據怪物等級,怪物的類型(BOSS),怪物技能類型等很多決策和根本屬性相連所起作用的操作,都可以做成決策AI;

行為AI:追蹤玩家,攻擊玩家,給玩家加血(如同伴),逃跑等這些行為動作操作;

OK,下面大家應該了解AI的基本思路了,那我們直接貼代碼了;

我直接把AI寫在了地圖層里面了,因為之前我框架的設計,是有一個地圖base,而所有的怪物,主角色,NPC都屬于地圖層,因為要做很多遍歷操作,所以在地圖base中寫上智能AI算法,然后再繼承拓展下來。

首先先制造一群怪物!并且讓怪物在設置的Rect內隨機移動!

復制代碼
/********************************************
注釋:
makenum 最大怪物數量
monsteridtags 怪物起始標簽
randomrange 配置怪圈大小(只能填正整數)
monster_model 怪物數據
yinzihigth 影子的距離
fristpoint 怪物初始設定的怪圈點
*********************************************/
void Maps_Diyu::makemonster(int makenum,int monsteridtags,CCPoint randomrange,MainRoledata monster_model,int yinzihigth,CCPoint fristpoint)
{
    for (int i = 0; i < makenum; i++)
    {
        int add_x = (int)(CCRANDOM_MINUS1_1()*randomrange.x);
        int add_y =(int)(CCRANDOM_MINUS1_1()*randomrange.y);
        monster_model.tags=monsteridtags+i;
        monster_model.nowpoint= CCPointMake(nowmap->getContentSize().width/2+fristpoint.x+add_x,nowmap->getContentSize().height/2+fristpoint.y+add_y);
        SpiritsMonster* newmonster = new SpiritsMonster(monster_model,1,yinzihigth);
        nowmap->addChild(newmonster->monster, 1,monsteridtags+i);
    }
}
復制代碼

然后處理怪物的行為AI:

復制代碼
/********************************************
注釋:
monsternum 最大怪物數量
monsteridtags 怪物起始標簽
monster_model 怪物數據
reatR 怪物仇恨視角的范圍值(通常200左右)
attck_reatR 怪物可攻擊范圍值(遠程怪和物理怪物)
playerpoint 主角坐標
randomrange 怪物默認隨機移動范圍
fristpoint 怪物初始設定的怪圈點
*********************************************/
void Maps_Diyu::attact_todo(int monsternum,int monsteridtags ,MainRoledata monster_model,int reatR,int attck_reatR,CCPoint playerpoint,CCPoint randomrange,CCPoint fristpoint)
{
    for (int i = 0; i < monsternum; i++)
    {
        CCRect* attck_rect = new CCRectMake(this->getChildByTag(monsteridtags+i)->getPosition().x-attck_reatR/2,this->getChildByTag(monsteridtags+i)->getPosition().y-attck_reatR/2,attck_reatR,attck_reatR);
        if(attck_rect->containsPoint(playerpoint)==true)
        {
            //執行怪物攻擊主角
            CCLog(FontChina::G2U("進入怪物可攻擊范圍"));
            //攻擊時改變方向
            SpiritsMonster::attackTomainRole_dir(ccp((int)playerpoint.x,(int)playerpoint.y),(CCSprite*)(this->getChildByTag(monsteridtags+i)),monster_model);
            //釋放技能動畫
            int add_x = (int)(CCRANDOM_MINUS1_1()*8);
            int add_y =(int)(CCRANDOM_MINUS1_1()*8);
            SkillEffects* skill = new SkillEffects(ccp((int)playerpoint.x+add_x,(int)playerpoint.y+add_y),monster_model,(0.2f+CCRANDOM_0_1()),8,3,1000);
            this->addChild(skill->effects_main,1000,50);
        }
        else
        {
            CCRect* track_rect = new CCRectMake(this->getChildByTag(monsteridtags+i)->getPosition().x-reatR/2,this->getChildByTag(monsteridtags+i)->getPosition().y-reatR/2,reatR,reatR);
            if(track_rect->containsPoint(playerpoint)==true)
            {
                //執行移動,不停追殺主角
                CCLog(FontChina::G2U("進入怪物仇恨視野區域"));
                //防止靠近主角,保持一定距離!主要為了好看和處理被攻擊效果。
                int add_x = (int)(CCRANDOM_MINUS1_1()*25);
                int add_y =(int)(CCRANDOM_MINUS1_1()*25);
                //移動時改變方向
                SpiritsMonster::moveTomap_dir(ccp((int)playerpoint.x,(int)playerpoint.y),(CCSprite*)(this->getChildByTag(monsteridtags+i)),monster_model);
                CCArray* callbackArray = CCArray::create();
                int nowtags = monsteridtags+i;
                char strs[64];
                sprintf(strs,"%d",nowtags);
                CCString* ccnowtags = CCString::create(strs);
                callbackArray->addObject(ccnowtags);
                callbackArray->addObject(monster_model.spiritname);
                char dir_x[64];
                sprintf(dir_x,"%d",(int)this->getChildByTag(nowtags)->getPositionX());
                char dir_y[64];
                sprintf(dir_y,"%d",(int)this->getChildByTag(nowtags)->getPositionY());
                CCString* d_x = CCString::create(dir_x);
                CCString* d_y = CCString::create(dir_y);
                callbackArray->addObject(d_x);
                callbackArray->addObject(d_y);
                CCFiniteTimeAction *actbackfun = CCCallFuncO::create(this, callfuncO_selector(Maps_Diyu::moveoverCallBack),callbackArray);
                CCActionInterval* act_movexixue = CCMoveTo::create(3+CCRANDOM_MINUS1_1(),ccp((int)playerpoint.x+add_x,(int)playerpoint.y+add_y));
                this->getChildByTag(nowtags)->runAction(CCSequence::create(act_movexixue,actbackfun,NULL));
            }
            else
            {
                //脫離仇恨時,隨機定點周圍移動
                int stopandrun = (int)(CCRANDOM_MINUS1_1()*10);
                if(stopandrun>=1)
                {
                    //脫離仇恨
                    int add_x = (int)(CCRANDOM_MINUS1_1()*randomrange.x);
                    int add_y =(int)(CCRANDOM_MINUS1_1()*randomrange.y);
                    CCPoint move_dir = ccp(this->getContentSize().width/2+fristpoint.x+add_x,this->getContentSize().height/2+fristpoint.y+add_y);

                    SpiritsMonster::moveTomap_dir(ccp((int)move_dir.x,(int)move_dir.y),(CCSprite*)(this->getChildByTag(monsteridtags+i)),monster_model);
                    CCArray* callbackArray = CCArray::create();
                    int nowtags = monsteridtags+i;
                    char strs[64];
                    sprintf(strs,"%d",nowtags);
                    CCString* ccnowtags = CCString::create(strs);
                    callbackArray->addObject(ccnowtags);
                    callbackArray->addObject(monster_model.spiritname);
                    char dir_x[64];
                    sprintf(dir_x,"%d",(int)this->getChildByTag(nowtags)->getPositionX());
                    char dir_y[64];
                    sprintf(dir_y,"%d",(int)this->getChildByTag(nowtags)->getPositionY());
                    CCString* d_x = CCString::create(dir_x);
                    CCString* d_y = CCString::create(dir_y);
                    callbackArray->addObject(d_x);
                    callbackArray->addObject(d_y);
                    CCFiniteTimeAction *actbackfun = CCCallFuncO::create(this, callfuncO_selector(Maps_Diyu::moveoverCallBack),callbackArray);
                    CCActionInterval* act_movexixue = CCMoveTo::create(3+CCRANDOM_MINUS1_1(),ccp(move_dir.x,move_dir.y));
                    this->getChildByTag(nowtags)->runAction(CCSequence::create(act_movexixue,actbackfun,NULL));

                }
            }
        }
    }
}
復制代碼

這段邏輯包括了,如果玩家進入怪物的仇恨區域,那么怪物會先移動到玩家附近的點(此時玩家移動開,怪物會根據定時器去判斷下一步如何操作:如1,玩家移動后還在仇恨區域,那么繼續追蹤玩家;2,如果玩家脫離仇恨,那么怪物執行回到初始坐標點的操作,然后繼續原地巡邏!),如果此時玩家已經在怪物的攻擊范圍內了,那么怪物會直接選擇攻擊!這樣怪物就會變得貌似有了思想一樣,他會去考慮判斷各種行為,那個區域我該做什么?不該做什么?

有了這個邏輯,我們還要賦予怪物循環思考的能力!

//啟動所有怪物智能AI監聽器
    nowmap->schedule(schedule_selector(Maps_Diyu::makemonsterAttack), (3.0f)); 

我們根據定時器去每隔3秒內去監控行為AI!

整個行為AI已經完畢!就可以實現比較智能的怪物追殺主角了!這也就牽扯到了游戲難度怪物難度的問題了,往往好玩的游戲智能AI都占用了程序一半以上時間去處理;怪物并不是血多,防御高他就是一個BOSS,如果BOSS他會滿地圖追著玩家打,會自己加血,逃跑,那這樣的BOSS我們作為玩家來說,打起來也比較刺激有意思,有挑戰!

這篇就寫這么多了,下回分解一下游戲界面UI交互的一些東西,充分運用定時器去管理一些玩家對屏幕基本操作的邏輯;

PS:COCOS2DQQ群 ,和大家一起分享cocos2dx開發經驗【41131516】


網載 2014-07-10 11:34:27

[新一篇] Windows Phone中In-App Purchase應用內購買

[舊一篇] 如何成為一名擁有思想作品集的產品經理
回頂部
寫評論


評論集


暫無評論。

稱謂:

内容:

驗證:


返回列表