日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

009 自动打怪功能的设计和实现

發布時間:2025/3/21 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 009 自动打怪功能的设计和实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

      • 界面代碼
      • 流程設計
      • 取最近怪物
      • 自動打怪

界面代碼

首先新增一個復選框,綁定控件變量和按鈕事件,然后在按鈕事件添加如下代碼

//自動打怪 void MainWnd::OnBnClickedCheck1() {static HANDLE hThread = 0;if (m_Auto_Attack.GetCheck()){hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)AutoAttackProc, NULL, 0, NULL);OutputDebugStringA("開啟自動打怪");}else{TerminateThread(hThread, -1);CloseHandle(hThread);hThread = 0;OutputDebugStringA("關閉自動打怪");} }

如果復選框被選中,就啟動線程開始自動打怪,否則強行結束線程。

接著新建一個類,命名為WorkThread,在這里實現我們的自動打怪的邏輯。

流程設計

自動打怪的流程設計如下:

  • 首先獲取到角色的數據
  • 獲取到周圍對象的數據
  • 根據周圍對象和角色的數據取到最近的怪物
  • 釋放技能打怪
  • 判斷怪物血量,如果不為零,則繼續打怪
  • 如果血量為零則跳轉到第一步
  • 在整個自動打怪的流程中,我們已經完成了大部分的步驟,就差第三步,取最近怪物的數據。

    取最近怪物

    _stuObj GetNearestAroundObj(_stuObj RoleData, _stuObjs AroundList);

    聲明一個函數,取最近的怪物,傳入角色對象和怪物對象集合。想要實現這個功能,有三個步驟。

    首先第一步,篩選出周圍對象的類型,因為我們獲取到的對象是包含NPC,怪物,玩家等各種對象類型的。所以需要寫一個函數來篩選出所有的對象,代碼如下:

    //篩選周圍對象的類型 _stuObjs FilterAroundObj(_stuObjs& list, DWORD type) {_stuObjs newList;_stuObj tmp;//遍歷周圍對象的容器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; }

    第二步,計算每個對象和人物之間的距離,代碼如下:

    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新增一個對象距離的屬性

    float m_ObjDistance; //對象距離

    第三步,通過排序算法取出最近的怪物,代碼如下:

    _stuObj SortNearestMonster(_stuObjs& list) {_stuObj tmp;//遍歷周圍對象的容器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;}}}//返回第一個對象return list.m_data.front(); }

    完成了這三個函數,就完成了取最近怪物的功能了,GetNearestAroundObj完整代碼如下:

    _stuObj GetNearestAroundObj(_stuObj RoleData, _stuObjs AroundList) {_stuObj nearobj;//篩選出所有的怪物_stuObjs listdata2 = FilterAroundObj(AroundList, 0x5);//如果size大于0 說明周圍有怪物對象if (listdata2.m_data.size()){//計算每個對象和人物之間的距離CalcAroundDistance(listdata2, RoleData);//冒泡排序取最近怪物nearobj = SortNearestMonster(listdata2);}return nearobj; }

    實際效果如圖:

    自動打怪

    完成了取最近怪物的功能,就相當于完成了一個自動打怪的功能,代碼如下:

    DWORD WINAPI AutoAttackProc() { _Start://取角色數據auto RoleData = GetRoleData();//取周圍對象數據auto AroundData = GetAroundData();//取最近的怪物_stuObj nearobj = GetNearestAroundObj(RoleData, AroundData);//如果坐標和血量都為0 說明沒取到最近的怪物if (nearobj.m_Obj_Pos.x==0&&nearobj.m_Obj_HP==0){return 0;}//獲取技能數據auto SkillData = GetSkillData();//獲取技能對象auto skill = SkillData.GetDataByName(L"基礎射擊");//釋放技能Fn_UseSkill(nearobj, skill);//循環打怪while (true){//打完了以后更新一下血量UpdateAroundObj(nearobj);//如果怪物血量大于0 繼續打怪if (nearobj.m_Obj_HP){Fn_UseSkill(nearobj, skill);}else{//否則 換下一個怪物goto _Start;}//這個休眠是給技能間隔的時間Sleep(300);}return 0; }

    其中更新血量的函數就是重新讀取一下目標怪物的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);//讀取坐標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); }

    到這里,我們就完成了整個自動打怪的功能了,但是這里有個問題,每次攻擊怪物的時候都釋放同一個技能。如果想要做到更加完善的話就需要一套更加強大的自動篩選技能的邏輯。

    那么下一篇文章我們來講自動技能的設計和實現。

    Github:https://github.com/TonyChen56/GameReverseNote

    完整代碼:https://download.csdn.net/download/qq_38474570/79498815

    總結

    以上是生活随笔為你收集整理的009 自动打怪功能的设计和实现的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。