• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 72,  comments - 4,  trackbacks - 0
             
            由于想在游戲中(非mfc程序)調(diào)用一個(gè)dll用來(lái)監(jiān)控游戲中一些數(shù)據(jù)變化,而這些數(shù)據(jù)可以觸發(fā)式變動(dòng),所以想到用mfc來(lái)弄,
            但網(wǎng)上查的
            “非mfc程序調(diào)用mfc擴(kuò)展dll”似乎有點(diǎn)麻煩,也沒(méi)有什么成樣的例子。
            后來(lái)還是自己對(duì)比正常的mfc程序加載方式修改出來(lái)了,步驟如下:
            1.  
            exe工程要設(shè)置成Use Standard Windows Libraries或者Use MFC in a Shared DLL(因?yàn)槲覀儾挥胢fc,所以設(shè)置成前者)
            2. 
            dll工程用vc向?qū)?chuàng)建mfc擴(kuò)展dll
            3. 在dll工程中拷貝相關(guān)的app,mainfrm和view以及doc框架(可以用vc向?qū)?chuàng)建一個(gè)正常mfc框架程序用來(lái)拷貝)
            然后在dllmain的attach中加入如下語(yǔ)句即可:
            //----------------------------------------
            // AFX internal initialization
            if (!AfxWinInit(hInstance, 0, "", 1))
            return 0;
            // Register the doc templates we provide to the app
            CWinApp* pApp = AfxGetApp();
            ENSURE(pApp != NULL);
            pApp->InitApplication();
            pApp->InitInstance();
            //----------------------------------------
            4. 如果是隱式調(diào)用的話,在exe中加入:
            #define AFX_EXT_API  __declspec(dllexport)
            #include "..\mfcdll\mfcdll.h"  // 這個(gè)是dll要導(dǎo)出的東西
            這樣就可以了

            5.顯式調(diào)用的話,用LoadLibrary先裝載,再獲取對(duì)應(yīng)導(dǎo)出函數(shù)調(diào)用就應(yīng)該也可以了(這個(gè)沒(méi)試)

            6.上述處理后只能顯示,但按鍵接收還不行,因?yàn)橄⒀h(huán)沒(méi)有地方調(diào)用。。。它原來(lái)是系統(tǒng)調(diào)用app->run(),在其中循環(huán)處理的。
            如果直接在dll中調(diào)用app的run()的話,mainfrm的PreTranslateMessage就能收到按鍵消息了。但這樣由于是主線程中調(diào)用app->run(),而run()中
            是消息死循環(huán),所會(huì)exe會(huì)沒(méi)機(jī)會(huì)響應(yīng)。。。所以解決辦法是模擬app->run()寫(xiě)一個(gè)runoneframe()函數(shù),然后每次刷新一下(或者創(chuàng)建新線程來(lái)刷新, 臨時(shí)試了一下會(huì)crash,我沒(méi)用這種辦法,先不查了,不過(guò)理論上應(yīng)該可以的)
            這樣就ok了(view中按鍵自己再處理吧,這里不提了)
            posted @ 2012-09-14 15:56 flipcode 閱讀(1333) | 評(píng)論 (0)編輯 收藏
            火矩之光中的導(dǎo)航圖:
            火矩之光 中已經(jīng)拋棄高位圖地形之類的作法,換用了模型,為了能作出迷宮,把地圖分塊,每塊是一個(gè)模型,
            每個(gè)模型有幾條通路,這樣各通路可以據(jù)算法得出隨機(jī)組合的謎宮,為了豐富,每個(gè)入路有好幾套模型可以隨機(jī)
            選取,然后根據(jù)所選擇的模型再隨機(jī)組合出復(fù)雜的謎宮。
            而對(duì)于路點(diǎn),則是平均格子求得的,這點(diǎn)跟普通網(wǎng)游的作法還是有點(diǎn)類似的,
            不是真正意義上的3維尋路,還是2維的, 作法應(yīng)該是從上往下跟碰撞模型進(jìn)行垂直求交得出路點(diǎn),
            然后再對(duì)路點(diǎn)進(jìn)行通路測(cè)試,產(chǎn)生導(dǎo)航圖。(它不是用幾何網(wǎng)格生成的導(dǎo)航圖)

            看下圖我的一個(gè)測(cè)試:
            左邊是一個(gè)模型,右邊是個(gè)有樓梯的另一個(gè)模型(它是個(gè)入口)。藍(lán)色格是導(dǎo)航點(diǎn)。藍(lán)色塊是尋出的路點(diǎn)。

            posted @ 2012-08-27 10:35 flipcode 閱讀(214) | 評(píng)論 (0)編輯 收藏
            泰坦之旅的ai

            titan quest的AI用的是切換式的狀態(tài)機(jī),而尋路用的是path engine第3方庫(kù),游戲中有一個(gè)任務(wù)編輯器主要是生成每一個(gè)任務(wù),每個(gè)任務(wù)中可以生成多個(gè)觸發(fā)器(trigger),每個(gè)觸發(fā)器可以生成一系列條件(condition),并可生成條件成立時(shí)要觸發(fā)的動(dòng)作(action). 這個(gè)有點(diǎn)類似war3的事件編輯器。

            以下是切換式狀態(tài)機(jī)跟蹤的一些記錄,很亂,沒(méi)寫(xiě)總結(jié),只是用于備忘。。。
            AI移動(dòng)跟蹤
            WinMain消息循環(huán)中的Game::Run()中先
            1. gGameEngine->GetFrustumForPlayer(updateFrustum, player->GetCoords().origin); 得到frustum

            2. gEngine->Update(&updateFrustum);進(jìn)行更新, 其中
               調(diào)用 world->Update(worldFrustumList);

               然后遍歷每個(gè)frustum取得對(duì)應(yīng)region進(jìn)行更新

               a. 看看當(dāng)前region是否與frustum相交,如果是則load,否則擴(kuò)大一點(diǎn)再相交,這時(shí)如果相交則將添加到后臺(tái)加載。
               b. 查看portal相關(guān)region進(jìn)行更新
               3. 查看connectedRegions(在地圖裝載得到玩家出生位置后進(jìn)行玩家所在region擴(kuò)大后跟其它region判斷相交所得)進(jìn)行更新 

            3. Region的更新中進(jìn)行l(wèi)evel更新:
              level->Update(frustumList, numFrustums, elapsedTime);
              在其中先取得在frustum中的Entity, 然后再遍歷更新所有Entity,
              之后再更新Entity所在4叉樹(shù)空間.

            4. 角色的更新:
               Entity的更新中, 先UpdateSelf再UpdateAttachedEntities
               (Entity中有PhysicsRigidBody成員physicsObject)

            5. UpdateSelf會(huì)跑到Character::PreAnimationUpdate中執(zhí)行 baseController->Update(localTimeDelta);從而跳到ContrallerAI中執(zhí)行GetExecutingState()->OnUpdate(deltaTime); 從而到達(dá)ControllerNpcStateIdle的更新中進(jìn)行狀態(tài)切換到SetState("Wander", ControllerAIStateData(0, 0, 0)); 
            之后再跑到ControllerNpcStateWander::OnBegin()
            處理:
                int closestPoint = GetClosest(GetController().GetWanderPoints());
                GetController().SetCurrentWanderPoint(closestPoint);
                if (!MoveToCurrentWanderPoint())
                {
                    SetState("Idle", ControllerAIStateData());
                    return;
                }
            這個(gè)在MoveToCurrentWanderPoint()函數(shù)里從隊(duì)列中取出當(dāng)前目標(biāo)點(diǎn)并ControllerAI::WalkTo
            其中會(huì)GetController().WalkTo(location, target);即ControllerAI::WalkTo(。。), 這會(huì)執(zhí)行:
             HandleAction(new WalkAction(GetParentId(), GetAI()->GetPathPosition(), location, target));
            這個(gè)會(huì)執(zhí)行:
                    SetCurrentAction(action);
                    GetCurrentAction()->Execute();從而運(yùn)行了WalkAction::Execute(), 這其中又調(diào)用了Character::WalkTo
             這又會(huì):
                movementMgr->SetNewPathTarget進(jìn)行處理


            最后在CharacterMovementManager::Update()中進(jìn)行角色位置更新:

                    CreateLocalPath(deltaTime, speed);

                    if (!MoveDownPath(deltaTime, speed))
                    {
                        return false;
                    }
                    UpdateCharacterPosition(deltaTime, speed);

            void UIDialogWindow::OnOpen()會(huì)調(diào)用 myNpc->AddSocialTarget( target );
            在void ControllerNpcStateIdle::OnUpdate(Time deltaTime)中判斷如果有SocialTarget則進(jìn)入Chat狀態(tài)處理

            【狀態(tài)處理例子】
            Monster的初始狀態(tài)是Idle,在Monster的更新函數(shù)里:
            一)。進(jìn)行搜敵,并切換成pursue狀態(tài)
            ,并調(diào)追捕狀態(tài)的OnBegin()函數(shù)處理,如果Monster不能行走則切回Idle狀態(tài),否則如果搜不到敵
            人則切換到Return狀態(tài),否則根據(jù)當(dāng)前技能id找出要移到的位置點(diǎn).
            ------------------------------------------------------
            【注意】找到要移到的位置點(diǎn)細(xì)節(jié):
            I. (Character::GetMoveToPoint)找出目標(biāo)點(diǎn):
              1. 目標(biāo)是自己則直接return自己位置
              2. 沒(méi)有目標(biāo)則保存goalPoint=目標(biāo)點(diǎn),distance=技能施放范圍,待后處理.
              3. 目標(biāo)是FixedItem則return FixedItem->GetMoveToPoint(..)里進(jìn)行處理
              4. 目標(biāo)是StrategicMovementBase,則return sm->GetMoveToPoint(..)里進(jìn)行處理
              5. 目標(biāo)是Entity,則goalPoint = entity->GetCoords().origin;并且如果entity阻擋則讓goalPoint回移一點(diǎn)以免浮點(diǎn)出錯(cuò)?否則distance=GetExtents() + entity-

            >GetExtents();待后處理
              6. 目標(biāo)是Character,則,
                 a. 如果是朋友
                   1)如果當(dāng)前是移動(dòng)狀態(tài),則要求目標(biāo)給出DefenseSlot(防御位置點(diǎn))作為goalPoint直接返回.
                   2)否則如果能直線通路到目標(biāo)點(diǎn)的話就直接返回離目標(biāo)比較近的一點(diǎn)(去掉半徑),不能直通則返回0點(diǎn)  
                 b. 如果是敵人
                   1)如果沒(méi)有技能,則goalPoint=目標(biāo)點(diǎn),distance=GetExtents() + target->GetExtents();待后處理
                   2)如果技能不需要AttackSlot或者this是Player, 則
                    goalPoint=目標(biāo)點(diǎn),distance = GetExtents() + target->GetExtents() + skill->GetRange();待后處理
                   3)否則直接返回目標(biāo)算出的AttackSlot攻擊點(diǎn)位置.
              上述2和5以及6中的b.的1)和2)需要待后處理的最后通過(guò) 
                WorldVec3 finalPoint = movementMgr->GetPointAwayFromGoal(goalPoint, distance);
              得到最終位置, 這個(gè)位置還要特殊判斷一下如果不在Region中或者路徑不能到達(dá)的話,則直接用TranslateToFloor到goalPoint.

            【說(shuō)明】:
              1. 什么是AttackSlot/DefenseSlot:
            每個(gè)角色可以有n個(gè)x距離的AttackSlot/DefenseSlot,它會(huì)在周圍x半徑的圓上平分出n個(gè)位置點(diǎn),當(dāng)有其它人要攻擊它或者要來(lái)幫助(防御)它時(shí),它就會(huì)在旁邊找一個(gè)較近的還

            沒(méi)其它人用過(guò)的slot分給這個(gè)其它人。
              2. movementMgr->GetPointAwayFromGoal()函數(shù)細(xì)節(jié):
                先是FindPath(目標(biāo))得出path,再用path->Advance(pathLength - distance)得到回退一點(diǎn)的位置。

            II. 找到目標(biāo)點(diǎn)后,還要調(diào)用movementGoalManager->GetClosestMovePoint(目標(biāo)點(diǎn)) 進(jìn)行處理:
                這個(gè)函數(shù)主要是給范圍武器用的,如果不是使用范圍武器的Monster則不會(huì)調(diào)整目標(biāo)點(diǎn)。
                如果是的話則遍歷全局對(duì)象movementGoalManager中的m_MoveGoalMap目標(biāo)點(diǎn)映射表,求出其它在同一region中的Monster
                所在目標(biāo)點(diǎn)跟當(dāng)前Monster所在目標(biāo)點(diǎn)的距離,如果距離比較近則調(diào)用GetPointAwayFromGoal(目標(biāo)點(diǎn), 3.0);調(diào)整當(dāng)前Monster的目標(biāo)點(diǎn)回退一點(diǎn),并將些處理后的位置及些

            Monsterid映射到m_MoveGoalMap目標(biāo)點(diǎn)映射表中。這樣遍歷過(guò)所有其它Monster的目標(biāo)點(diǎn)進(jìn)行一一檢測(cè)處理后就會(huì)盡量避免與其它Monster擠到一起。
            ------------------------------------------------------

            找到要移到的位置點(diǎn)之后,
            1. 用(CloseEnoughToUseSkill(GetCurrentEnemy(), GetCurrentSkillID()))判斷是否在技能攻擊范圍內(nèi),
            如果在則用IsPathClear(GetCurrentEnemy())來(lái)判斷是不是到直通目標(biāo),是則切換成Attack狀態(tài)后返回,否則切換成NavigateObstacle狀態(tài)后返回。

            2. 否則敵人不在攻擊范圍內(nèi)就看當(dāng)前是否已站在目標(biāo)點(diǎn),是則切回Idle狀態(tài)后返回

            3. 不在目標(biāo)點(diǎn)則看是不是能夠移到目標(biāo)點(diǎn),不能則切回Idle狀態(tài)后返回。

            4. 能移到目標(biāo)點(diǎn)則MoveTo到目標(biāo)點(diǎn).
               這個(gè)MoveTo會(huì)調(diào)用
               HandleAction(new MoveToAction(GetParentId(), GetAI()->GetPathPosition(), location, target, GetAI()->GetSkillReferenceNumber(skill), 1.0, animType));
               這個(gè)會(huì)執(zhí)行到MoveToAction, 其中會(huì)轉(zhuǎn)調(diào):
                    monseter->SetCurrentAttackTarget(targetId, location, skillNumber);
                    monseter->SkillWarmUp( skillNumber, false );
                    monseter->MoveTo(location, GetBlendTime(), animType);
                    monseter->PlayLoopingRunningSound();
              而monseter->MoveTo又會(huì)調(diào)用 movementMgr->SetNewPathTarget(movementMgr->GetPathPosition(), surfacePoint, alreadyThere))
              然后再用SetActionState(Character_ActionState_Move);設(shè)置Action的狀態(tài)為Move,并通過(guò)PlayAnimation播放run動(dòng)作(即調(diào)用GetAnimationBase( type ).PlayAnimation( 

            actor, selection, speedModifier, loop, iteration ),這個(gè)可以參考我另一個(gè)動(dòng)畫(huà)跟蹤文檔看細(xì)節(jié))

            二)。搜敵后會(huì)接著調(diào)用ControllerAI::Update()更新函數(shù):
               1. 先進(jìn)行當(dāng)前狀態(tài)更新()
                  由于前面Monster切換到了pursue追捕狀態(tài),所以執(zhí)行到
                  ControllerMonsterStatePursue::OnUpdate(),其中:
                  a. 追捕所用時(shí)間過(guò)了,則切換回return狀態(tài)
                  b. 重新選擇技能時(shí)間到了則重新找出一個(gè)bestSkill.(這也避免了萬(wàn)一當(dāng)前技能是melee,而玩家總是繞著Monster轉(zhuǎn),怪就會(huì)不停地追不上而沒(méi)法肉搏攻擊)
                  c. 用CloseEnoughToUseSkill判斷是否夠技能施放距離,夠的話用IsPathClear判斷攻擊方向是否可通,是則轉(zhuǎn)Attack狀態(tài),不通則轉(zhuǎn)NavigateObstacle狀態(tài).

               2. 再遍歷執(zhí)行m_PreloadQuestActionList中action.

            上述都在【更祥細(xì)一點(diǎn)】中1。Character::UpdateSelf()中進(jìn)行
            接著會(huì)到【更祥細(xì)一點(diǎn)】中2。 Update subsystems:中的FollowPath()進(jìn)行真正的移動(dòng)處理.
            posted @ 2012-08-13 10:09 flipcode 閱讀(346) | 評(píng)論 (0)編輯 收藏
            dota中的道具/技能及動(dòng)作狀態(tài)機(jī) 相關(guān)原型 設(shè)計(jì)備忘::
            //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            // dota中的道具/技能及動(dòng)作狀態(tài)機(jī) 相關(guān)原型 設(shè)計(jì)備忘::
            /*
                                                         flipcode@qq.com 的草案?jìng)渫y(cè)試通過(guò))
               商店用擁有很多kToyItem供購(gòu)買(mǎi),角色通過(guò)購(gòu)買(mǎi)也可以得到很多kToyItem。
               kToyItem用于kToy物品類的顯示封裝,對(duì)應(yīng)有一個(gè)物品類kToy以及儲(chǔ)存在哪個(gè)格子中,價(jià)格多少等信息。
               kToy中包含3種類型:1.kEquip(裝備),2.kUse(使用), 3.kSkill(技能)
               這3個(gè)類中各自包含一個(gè)listAction(動(dòng)作列表),列表中存放的是kAction動(dòng)作基類。
               kAction類中有Select()和IsValid()以及Execute()函數(shù);
               1. kEquip中的Update()中調(diào)用listAction中每一個(gè)IsValid()函數(shù)來(lái)判斷是否執(zhí)行對(duì)應(yīng)的Execute();
                  
               2. kUse中的Use()函數(shù)中調(diào)用listAction中每一個(gè)IsValid()函數(shù)來(lái)判斷是否執(zhí)行對(duì)應(yīng)的Execute();
               
               3. kSkill中的select()函數(shù)遍歷listAction中每一個(gè)Select()函數(shù)來(lái)判斷是否能選擇該技能,都通過(guò)才選擇。
                  kSkill中的Start()函數(shù)中調(diào)用listActionStart中每一個(gè)IsValid()函數(shù)來(lái)判斷是否執(zhí)行對(duì)應(yīng)的Execute();
                  kSkill中的Cast()函數(shù)中調(diào)用listActionCast中每一個(gè)IsValid()函數(shù)來(lái)判斷是否執(zhí)行對(duì)應(yīng)的Execute();
              說(shuō)明:
              kSkill設(shè)計(jì)時(shí)考慮到施放前搖,故用了start()函數(shù)來(lái)播放前搖動(dòng)作/特效,然后等待前搖時(shí)間完成再調(diào)用cast()函數(shù)來(lái)播放對(duì)應(yīng)的施放動(dòng)作/特效。
              當(dāng)特效完成后再處理listAction(動(dòng)作列表)。dota中還有后搖,我理解成技能冷卻時(shí)間(不知道對(duì)否),當(dāng)cast()時(shí),skill就可以開(kāi)始冷卻了。
               [說(shuō)明]
               角色屬性有:基礎(chǔ)屬性,附加屬性(直接+),加成屬性(*(1+比例)),而
               kAction的派生類kActionProperty專用于處理kEquip(裝備)提高屬性: 
               它用VARY_TYPE類型指明針對(duì)某種屬性, 如: str, int, dex, HP/MP(min/max), atk(min/max)。。。等.
               它用PROPERTY_METHOD區(qū)別是直接加還是比例乘:add/rate。
               這樣角色如果擁有kToyItem的話,那么在更新中就會(huì)調(diào)用每個(gè)物品的kEquip的Update,從而把屬性更新到角色的add_data[類型]和rate_data[類型]中,
               接著角色的更新就會(huì)用(base_data[]+add_data[])*(1+rate_data[])的公式來(lái)處理之(當(dāng)然,dota的一些特殊的屬性使用另外的計(jì)算方法)
               kAction可以方便地?cái)U(kuò)充很多普通派生處理類,只要在相應(yīng)的Execute()進(jìn)行處理即可實(shí)現(xiàn)想要的功能,比如可能派生一個(gè)名為kActionHurt類,
               然后把它加入到kUse/kSkill中的listAction列表中,這樣只要點(diǎn)擊使用,即可Execute中處理加血/扣血。
               另外從kAction中派生的還有一些特殊類型:
               1. kActionEffect(包含listAction成員):
                  kActionEffect執(zhí)行Execute()時(shí)會(huì)調(diào)用全局的kEffectManager(特效管理器)的PlayEffect(effect_class_name)函數(shù)來(lái)產(chǎn)生一個(gè)kEffect的派生類對(duì)象, 并轉(zhuǎn)讓listAction給它。
                  kEffectManager用來(lái)管理listEffect列表,更新處理其中每一個(gè)kEffect。
                  kEffect類中包含一個(gè)listAction(動(dòng)作列表)指針,它是由kActionEffect在產(chǎn)生它時(shí)傳遞過(guò)來(lái)的,這樣在特效完成并且條件成立時(shí)(比如命中敵人)調(diào)用listAction中每一個(gè)IsValid()函數(shù)來(lái)判斷是否執(zhí)行對(duì)應(yīng)的Execute();
               2. kActionState(包含listAction成員):
                  kActionState執(zhí)行Execute()時(shí)會(huì)調(diào)用全局的kStateManager(狀態(tài)管理器)的PlayState(state_class_name)函數(shù)來(lái)產(chǎn)生一個(gè)kState的派生類對(duì)象, 并轉(zhuǎn)讓llistAction給它。
                  kStateManager用來(lái)管理listState列表,更新處理其中每一個(gè)kState。
                  kState類中包含一個(gè)listAction(動(dòng)作列表)指針, 它是由kActionState在產(chǎn)生它時(shí)傳遞過(guò)來(lái)的,這樣在該狀態(tài)完成時(shí)會(huì)調(diào)用listAction中每一個(gè)IsValid()函數(shù)來(lái)判斷是否執(zhí)行對(duì)應(yīng)的Execute();
              注意: kState隊(duì)列的執(zhí)行優(yōu)先于kAIState隊(duì)列,只有kState列表為空時(shí),kAIState才有機(jī)會(huì)執(zhí)行.
              關(guān)于kState和kAIState的區(qū)別:
              a. 動(dòng)作觸發(fā)的狀態(tài)機(jī):
              kState主要是kAction(動(dòng)作)觸發(fā)引起角色的一些臨時(shí)被動(dòng)行為,比如kState被擊退狀態(tài),被暈狀態(tài),狀態(tài)之間可以并行,或者串行(通過(guò)kState中的listAction列表掛接,在kState完成時(shí)遍歷調(diào)用listAction)。
              比如:
                 可以將kActionHurt加入到kStateStun(被暈)狀態(tài)中的listActon中,然后再把kStateStun加到kStateThrustBack(被擊退)中,然后再把kStateThrustBack加入到kShotEffect的listAction中,接著給kActionEffect設(shè)置對(duì)應(yīng)的kShotEffect
              并把kActionEffect加入到kToy中的kSkill的listActon中.這樣,當(dāng)技能使用時(shí)就會(huì)觸發(fā)一個(gè)kActionEffect播放kShotEffect,這個(gè)kShotEffect播放完成時(shí)會(huì)觸發(fā)kStateThrustBack將角色擊退到一邊,退到一邊完成后接著觸發(fā)kStateStun讓角色暈上一會(huì)。
              而如果前面的kShotEffect是范圍特效的話,那在特效傷害范圍的角色都被擊退后再暈上一會(huì)(由于擊退和暈是動(dòng)作狀態(tài)優(yōu)先于角色的AI狀態(tài),所以這時(shí)角色的AI是不運(yùn)行的,只有等擊退后暈完了AI才醒過(guò)一繼續(xù))。
              b. AI行為狀態(tài)機(jī):
              kAIState主要是由kAIBrain(大腦)思考引起的一些主動(dòng)的AI行為,比如kAIRoam漫步, kAIPursue追捕等,各AI狀態(tài)之間不能并行或串行只能切換。在任何時(shí)候包括在kAction的處理中也可以進(jìn)行角色的kAIState切換。
              
               3. kActionTrigger:
                  kActionTrigger中擁有一個(gè)事件名稱列表,當(dāng)該action被execute時(shí)會(huì)通過(guò)kEventManager->PostEvent(Event_Name)來(lái)發(fā)出事件消息。這時(shí)事件監(jiān)聽(tīng)列表中的對(duì)應(yīng)事件號(hào)的觸發(fā)器先判斷kCondition是否成立,是則調(diào)用相應(yīng)的觸發(fā)器的kAction動(dòng)作。
               關(guān)于觸發(fā)器:
               kTrigger觸發(fā)器,擁有l(wèi)istEventName, kCondition, kAction。事件管理器kEventManager可以創(chuàng)建kTrigger,并添加觸發(fā)器監(jiān)聽(tīng)的事件列表(listEventName),條件(kCondition),以及動(dòng)作(kAction)。 
               當(dāng)事件發(fā)生時(shí)可隨時(shí)調(diào)用kEventManager->PostEvent(Event_Name)來(lái)發(fā)出消息,事件的監(jiān)聽(tīng)者kTrigger先判斷kCondition是否成立,是則調(diào)用kAction。
               調(diào)用的kAction即前面所說(shuō)的動(dòng)作基類,當(dāng)動(dòng)作完成時(shí)可以再次PostEvent(...)以便觸發(fā)另外的觸發(fā)器。
               4. kActionPose:
                  這個(gè)Action只是簡(jiǎn)單地調(diào)用一下角色的動(dòng)作播放。
               5. kActionSleep(包含listAction成員):
                  這個(gè)kAction只是延遲一段時(shí)間,時(shí)間到了再調(diào)用listAction各成員的execute()函數(shù).
               由以上設(shè)計(jì)可以知道每一個(gè)kToy道具均可以由不同的處理函數(shù)并行及串行(注意:這里說(shuō)的串/并行跟多線程無(wú)關(guān),概念不一樣)組合而成,這樣就可以實(shí)現(xiàn)動(dòng)作或特效的串行/并發(fā)執(zhí)行,以及觸發(fā)相應(yīng)的處理。
            */
            //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            posted @ 2012-08-13 09:58 flipcode 閱讀(828) | 評(píng)論 (0)編輯 收藏

            mythos中的ai是并發(fā)的棧式狀態(tài)機(jī):

            拿wolf作為例子:
            一。配置文件:
            在ai目錄中的wolf.xml配置它所有的行為(包括每個(gè)行為發(fā)生機(jī)率,參數(shù),以及執(zhí)行函數(shù)):
            其中執(zhí)行函數(shù)以及對(duì)應(yīng)skillid如下:
            1.
              <nBehaviorId>move - approach target</nBehaviorId>
              <nSkillId>monster melee</nSkillId>
            2.
              <nBehaviorId>skill - do skill</nBehaviorId>
              <nSkillId>monster melee</nSkillId>
            3.
              <nBehaviorId>skill - do skill</nBehaviorId>
              <nSkillId>Fidget</nSkillId>
            4.
              <nBehaviorId>move - wander</nBehaviorId>
              <nSkillId/>

            二。ai更新:
               SrvGameTick--》GameEventsProcess--》AI_Update()
              在AI_Update中遍歷執(zhí)行該unit的所有行為(behavior) :
              1. sBehaviorApproachTarget()
                 查找對(duì)應(yīng)的目標(biāo),發(fā)出朝它移動(dòng)指令
                
              1. sBehaviorDoSkill()
                 如果有目標(biāo)則執(zhí)行sSkillExecute進(jìn)行技能施放
                
              2. ...類似功能處理
             
              。。。
             
              【說(shuō)明】:
                mythos的行為是并發(fā)的棧式,最大可以有5個(gè)棧, 用
                int nIndex = tContext.pnStack[ tContext.nStackCurr ]這樣的結(jié)構(gòu)進(jìn)行處理,
                通過(guò)pTable->pBehaviors[ nIndex ]得到對(duì)應(yīng)的行為處理函數(shù)進(jìn)行執(zhí)行處理。
                   
                a. 并發(fā):
                每執(zhí)行完一個(gè)行為函數(shù)后 tContext.pnStack[ tContext.nStackCurr ]++; 這樣就換到unit的下一個(gè)行為函數(shù)再執(zhí)行。
               
                b. 進(jìn)入棧(子函數(shù)):
                tContext.nStackCurr為棧下標(biāo),初始tContext.nStackCurr=0,即為第0個(gè)棧,
                可以設(shè)置tContext.nStackCurr++;并且tContext.pnStack[ tContext.nStackCurr ]=nBranchTo(要走的分支號(hào))。這樣來(lái)
                執(zhí)行分支函數(shù)。 當(dāng)分支函數(shù)完成時(shí)tContext.nStackCurr--再回來(lái)上一級(jí)。
               
                另外有些行為函數(shù)是執(zhí)行一次的,執(zhí)行完了就會(huì)把它從列表中刪除。下次不會(huì)再遍歷到.


            posted @ 2012-08-13 09:51 flipcode 閱讀(176) | 評(píng)論 (0)編輯 收藏
            gunz的ai處理(備忘)
            [更新]
            一個(gè)Actor更新中:
            1. m_TaskManager.Run(fDelta);
            2. ProcessNetwork(fDelta);
            3. ProcessAI(fDelta);
               處理actor->Brain->Think()中
            bool bFind = FindTarget();
            if ( bFind)
            {
              ProcessBuildPath( fDelta);
              ProcessAttack( fDelta);
            }
            4. ProcessMovement(fDelta);
            5. ProcessMotion(fDelta);
            一。ProcessAI()
                actor->Brain->Think()處理中產(chǎn)生一個(gè)Task
                一個(gè)任務(wù)有 移動(dòng),攻擊,延時(shí),轉(zhuǎn)向等,其中攻擊有肉搏,范圍,技能
                比如:actor->Brain->Think()中發(fā)了現(xiàn)敵人后在ProcessAttack()中產(chǎn)生一個(gè)skilltask存入到
                actor->m_TaskManager中
            二。m_TaskManager.Run()
               在在taskMgr中處理m_pCurrTask的3個(gè)步驟(start,run,complete):
               舉例: 如ZTask_Skill:
               1. OnStart()中
                 a.parent(是一個(gè)actor)->Skill(m_nSkill); // 進(jìn)行動(dòng)作輸入(動(dòng)作用了m_AniFSM進(jìn)行管理)
                 b.ZPostNPCSkillStart(ownerid,nSkill,Targetid,TargetPos);
                   這會(huì)生成一個(gè)id為MC_QUEST_PEER_NPC_SKILL_START的cmd并push到全局的m_CommandManager中
               2. OnRun()中
                   if時(shí)間到了則ZPostNPCSkillExecute(ownerid,nSkill,Targetid,TargetPos);
                   產(chǎn)生的命令id==MC_QUEST_PEER_NPC_SKILL_EXECUTE;
               3 . OnComplete()中
                   ZTask_Skill中無(wú)處理.
            三。m_pGameInterface->Update()中從m_CommandQueue中取出cmd, 對(duì)其:
                1. SendCommand(pCommand);
                2. OnCommand(pCommand);
                   switch(cmd->id)調(diào)用對(duì)應(yīng)的處理函數(shù),
                  例如:
                  a. id==MC_QUEST_PEER_NPC_SKILL_START時(shí)將調(diào)用OnPeerNPCSkillStart()
                     在其中通過(guò)uidOwner找得actor得到它的ZModule_Skills處理模塊傳入cmd的參數(shù)處理之.
                     這會(huì)進(jìn)行發(fā)起特效處理
                  b. id==MC_QUEST_PEER_NPC_SKILL_EXECUTE時(shí)時(shí)將調(diào)用OnPeerNPCSkillExecute()
                     在其中通過(guò)uidOwner找得actor得到它的ZModule_Skills處理模塊傳入cmd的參數(shù)處理之.
                     這會(huì)進(jìn)行攻擊特效處理:
                     1). 如果是bHitCheck標(biāo)志的特效,則轉(zhuǎn)讓全局的武器管理類處理:
                         m_WeaponManager.AddMagic( this, vMissilePos, vMissileDir, m_pOwner);進(jìn)行處理
                這里判斷如果循環(huán)次數(shù)減到0,則m_bEnable = false;
                     2).否則:
                       a. 如果有相機(jī)震動(dòng)標(biāo)志,則通知照相機(jī)震動(dòng)處理
                         GetCamera()->Shock( fPower*fDefaultPower, fDuration, rvector( 0.0f, 0.0f, -1.0f));
                       b. 遍歷所有角色,檢測(cè)是否范圍內(nèi)以及抗性沒(méi)抵消完傷害:
                          (1)是攻擊則
                             pObject->OnDamaged(..)
                             否則               
            pObject->OnHealing(..)
                          (2)限速:
                             pMovableModule->SetMoveSpeedRestrictRatio( 0, fDuration);
                           
                          (3)擊退:
                             pObject->AddVelocity( m_pDesc->fModKnockback * 7.f * -dir);
                      3). 特效燃燒效果:
            if(m_pDesc->szCastingEffect[0]) {
                if(type != eq_parts_pos_info_etc)
                efgmgr->AddPartsPosType(m_pDesc->szCastingEffect, Targetid,type,m_pDesc->nEffectTime);
            else 
            efgmgr->Add(m_pDesc->szCastingEffect, vPos,vDir,OwnerID,m_pDesc->nEffectTime);
            }
                      
            if(m_pDesc->szCastingEffectSp[0]) {
            ZGetEffectManager()->AddSp(m_pDesc->szCastingEffectSp,m_pDesc->nCastingEffectSpCount,
            vPos,vDir,m_pOwner->GetUID());
            }
                       3). 提示信息顯示處理
                       4). 聲音播放處理.
            四。ZWeaponMgr處理:
                上述的OnPeerNPCSkillExecute()處理中發(fā)現(xiàn)是飛行特效轉(zhuǎn)交給ZWeaponMgr來(lái)處理,所以這里說(shuō)一下
               在這里會(huì)處理特效模型飛行并處理Explosion( type, pPickObject,pickdir);爆炸傷害!轉(zhuǎn)調(diào)用到pTarget->OnDamaged(..)
            posted @ 2012-08-13 09:49 flipcode 閱讀(285) | 評(píng)論 (0)編輯 收藏
            posted @ 2012-07-03 10:55 flipcode 閱讀(181) | 評(píng)論 (0)編輯 收藏

            載圖,角色用的gunz模型測(cè)試:


            界面用群雄逐鹿的測(cè)試:
            posted @ 2012-05-10 15:29 flipcode 閱讀(173) | 評(píng)論 (0)編輯 收藏

            posted @ 2012-04-01 20:04 flipcode 閱讀(198) | 評(píng)論 (0)編輯 收藏




            圖:

            posted @ 2012-03-23 21:26 flipcode 閱讀(194) | 評(píng)論 (0)編輯 收藏
            僅列出標(biāo)題
            共8頁(yè): 1 2 3 4 5 6 7 8 
            91精品国产91热久久久久福利 | 99蜜桃臀久久久欧美精品网站| 国产ww久久久久久久久久| 99久久精品九九亚洲精品| 四虎国产精品成人免费久久| 中文字幕无码av激情不卡久久| 奇米综合四色77777久久| 国产精品99久久不卡| 精品国产99久久久久久麻豆| 国产精品99精品久久免费| 久久久久无码中| 91精品国产91久久综合| 伊人久久无码精品中文字幕| 99精品久久精品一区二区| 久久免费视频1| 91久久九九无码成人网站| 久久精品国产AV一区二区三区| 66精品综合久久久久久久| 无码人妻久久一区二区三区免费 | 亚洲AV伊人久久青青草原| 国产精品欧美久久久天天影视| 久久99国产精一区二区三区| 一级做a爰片久久毛片免费陪| 午夜精品久久久久久99热| 久久乐国产综合亚洲精品| 久久免费99精品国产自在现线| 国内精品九九久久久精品| 久久精品免费一区二区| 一本色道久久综合狠狠躁篇| 品成人欧美大片久久国产欧美...| 久久久久亚洲AV片无码下载蜜桃| 综合久久一区二区三区| 亚洲精品视频久久久| 看全色黄大色大片免费久久久| 成人国内精品久久久久影院VR| 久久99精品国产麻豆宅宅| 久久九九精品99国产精品| 国产综合久久久久久鬼色| 亚洲国产精品久久久久久| 精品无码久久久久久国产| 久久精品国产99久久香蕉|