009 自动打怪功能的设计和实现
文章目錄
- 界面代碼
- 流程設(shè)計(jì)
- 取最近怪物
- 自動(dòng)打怪
界面代碼
首先新增一個(gè)復(fù)選框,綁定控件變量和按鈕事件,然后在按鈕事件添加如下代碼
//自動(dòng)打怪 void MainWnd::OnBnClickedCheck1() {static HANDLE hThread = 0;if (m_Auto_Attack.GetCheck()){hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)AutoAttackProc, NULL, 0, NULL);OutputDebugStringA("開啟自動(dòng)打怪");}else{TerminateThread(hThread, -1);CloseHandle(hThread);hThread = 0;OutputDebugStringA("關(guān)閉自動(dòng)打怪");} }如果復(fù)選框被選中,就啟動(dòng)線程開始自動(dòng)打怪,否則強(qiáng)行結(jié)束線程。
接著新建一個(gè)類,命名為WorkThread,在這里實(shí)現(xiàn)我們的自動(dòng)打怪的邏輯。
流程設(shè)計(jì)
自動(dòng)打怪的流程設(shè)計(jì)如下:
在整個(gè)自動(dòng)打怪的流程中,我們已經(jīng)完成了大部分的步驟,就差第三步,取最近怪物的數(shù)據(jù)。
取最近怪物
_stuObj GetNearestAroundObj(_stuObj RoleData, _stuObjs AroundList);聲明一個(gè)函數(shù),取最近的怪物,傳入角色對(duì)象和怪物對(duì)象集合。想要實(shí)現(xiàn)這個(gè)功能,有三個(gè)步驟。
首先第一步,篩選出周圍對(duì)象的類型,因?yàn)槲覀儷@取到的對(duì)象是包含NPC,怪物,玩家等各種對(duì)象類型的。所以需要寫一個(gè)函數(shù)來篩選出所有的對(duì)象,代碼如下:
//篩選周圍對(duì)象的類型 _stuObjs FilterAroundObj(_stuObjs& list, DWORD type) {_stuObjs newList;_stuObj tmp;//遍歷周圍對(duì)象的容器for (auto it = begin(list.m_data); it != end(list.m_data); it++){if (it->m_Obj_HP&&it->m_ObjType == type){tmp = *it;newList.m_data.push_back(tmp);}}return newList; }第二步,計(jì)算每個(gè)對(duì)象和人物之間的距離,代碼如下:
void CalcAroundDistance(_stuObjs& list, _stuObj self) {for (auto it = begin(list.m_data); it != end(list.m_data); it++){//勾股定理求距離float a = it->m_Obj_Pos.x - self.m_Obj_Pos.x;float b = it->m_Obj_Pos.y - self.m_Obj_Pos.y;it->m_ObjDistance = sqrt(a*a + b * b);} }這里需要給_stuObj新增一個(gè)對(duì)象距離的屬性
float m_ObjDistance; //對(duì)象距離第三步,通過排序算法取出最近的怪物,代碼如下:
_stuObj SortNearestMonster(_stuObjs& list) {_stuObj tmp;//遍歷周圍對(duì)象的容器for (auto it = begin(list.m_data); it != end(list.m_data); it++){for (auto it = begin(list.m_data); it != end(list.m_data) - 1; it++){if (it->m_ObjDistance > (it + 1)->m_ObjDistance){tmp = *(it + 1);*(it + 1) = *it;*it = tmp;}}}//返回第一個(gè)對(duì)象return list.m_data.front(); }完成了這三個(gè)函數(shù),就完成了取最近怪物的功能了,GetNearestAroundObj完整代碼如下:
_stuObj GetNearestAroundObj(_stuObj RoleData, _stuObjs AroundList) {_stuObj nearobj;//篩選出所有的怪物_stuObjs listdata2 = FilterAroundObj(AroundList, 0x5);//如果size大于0 說明周圍有怪物對(duì)象if (listdata2.m_data.size()){//計(jì)算每個(gè)對(duì)象和人物之間的距離CalcAroundDistance(listdata2, RoleData);//冒泡排序取最近怪物nearobj = SortNearestMonster(listdata2);}return nearobj; }實(shí)際效果如圖:
自動(dòng)打怪
完成了取最近怪物的功能,就相當(dāng)于完成了一個(gè)自動(dòng)打怪的功能,代碼如下:
DWORD WINAPI AutoAttackProc() { _Start://取角色數(shù)據(jù)auto RoleData = GetRoleData();//取周圍對(duì)象數(shù)據(jù)auto AroundData = GetAroundData();//取最近的怪物_stuObj nearobj = GetNearestAroundObj(RoleData, AroundData);//如果坐標(biāo)和血量都為0 說明沒取到最近的怪物if (nearobj.m_Obj_Pos.x==0&&nearobj.m_Obj_HP==0){return 0;}//獲取技能數(shù)據(jù)auto SkillData = GetSkillData();//獲取技能對(duì)象auto skill = SkillData.GetDataByName(L"基礎(chǔ)射擊");//釋放技能Fn_UseSkill(nearobj, skill);//循環(huán)打怪while (true){//打完了以后更新一下血量UpdateAroundObj(nearobj);//如果怪物血量大于0 繼續(xù)打怪if (nearobj.m_Obj_HP){Fn_UseSkill(nearobj, skill);}else{//否則 換下一個(gè)怪物goto _Start;}//這個(gè)休眠是給技能間隔的時(shí)間Sleep(300);}return 0; }其中更新血量的函數(shù)就是重新讀取一下目標(biāo)怪物的HP
//更新血量(再次讀取HP) void UpdateAroundObj(_stuObj& obj) {//讀取血量obj.m_Obj_HP = ReadDword(obj.m_Obj + 0x65C);obj.m_Obj_HP = ReadDword(obj.m_Obj_HP + 0x1AC);//讀取坐標(biāo)obj.m_Obj_Pos.x = ReadFloat(obj.m_Obj + 0x80);obj.m_Obj_Pos.y = ReadFloat(obj.m_Obj + 0x84);obj.m_Obj_Pos.z = ReadFloat(obj.m_Obj + 0x88); }到這里,我們就完成了整個(gè)自動(dòng)打怪的功能了,但是這里有個(gè)問題,每次攻擊怪物的時(shí)候都釋放同一個(gè)技能。如果想要做到更加完善的話就需要一套更加強(qiáng)大的自動(dòng)篩選技能的邏輯。
那么下一篇文章我們來講自動(dòng)技能的設(shè)計(jì)和實(shí)現(xiàn)。
Github:https://github.com/TonyChen56/GameReverseNote
完整代碼:https://download.csdn.net/download/qq_38474570/79498815
總結(jié)
以上是生活随笔為你收集整理的009 自动打怪功能的设计和实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 008 释放技能call分析
- 下一篇: 010 自动技能的设计和实现