019 自动任务功能的设计和实现

发布时间:2025-02-10 04:11

利用待办事项功能:电子设备上的此功能可自动提醒你完成任务。 #生活技巧# #组织技巧# #任务清单制作#

文章目录 任务详情的设计任务表的设计TaskManager类自动接任务自动完成任务自动任务最后的总结

之前我们已经完成了自动打怪,自动技能和自动吃药的功能,这一次我们来完成自动任务的功能。自动任务的难度要比前三个高很多,涉及到要处理的细节也很多,我这里写的也不是百分百完美的,只是提供一个基本的思路,如果想要实现一个完美的自动任务的脚本,还需要花时间慢慢完善。

首先新建一个类,命名为TaskManager

任务详情的设计

所谓的自动任务,就是将角色从1级到满级所有的任务全部的数据,记录到一张表。然后挨个遍历并执行。这样的话,就要求我们设计表的信息足够多,并且算法足够强大。这样才能够用一套算法去自动完成所有的任务。

首先需要设计一个任务详情结构体,这个结构体需要包含下面的字段:

任务名字任务条件接任务的 等级需要杀死的怪物数量任务的地图任务地图的坐标交接任务的NPC选择的奖励

根据上面的信息,定义出这样一个结构体

//任务详情表 struct _stuTaskInfo {//任务名字wstring m_Name;//任务IDDWORD m_ID;//交任务的NPCwstring m_FinishNpcName; }; 123456789101112

还需要有一个任务内容,但是任务内容涉及的东西比较多,所以要单独定义一个结构体。

//任务类型 enum TaskTypeEnum {Em_对话,Em_打怪,Em_收集, Em_行为, }; 12345678

首先加一个任务类型的结构体,相关的类型后面慢慢添加。

//任务内容 struct _stuTaskWorkInfo {//任务类型TaskTypeEnum m_WorkType;//需要对话的NPC名字 或者是攻击的怪物的名字或者是收集物品的名字wstring m_Name;//完成任务需要的数量DWORD m_Count; }; //任务内容 vector<_stuTaskWorkInfo> m_WorkList; 123456789101112131415

然后完成任务内容的结构体,把这个结构体的数组放到任务详情表里面。然后是任务奖励。

//任务奖励 struct _stuTaskAward { //奖励名称 wstring m_Name; DWORD m_ChoosePos; }; //任务奖励 vector<_stuTaskAward> m_AwardList; 123456789101112

任务详情表,尽可能加上所有需要的数据。然后再将所有的任务详情定义一个数组,把所有的数据封装进去,就可以通过这个表来完成自动任务了。

上面的是需要我们去完成的任务的结结构体,再加一个可接任务的结构体,当角色没有任务的时候通过这个结构体去接任务。

//可接任务 struct _stuCanGetTaskInfo {//任务名字wstring m_Name;//任务IDDWORD m_ID;//接任务的NPCwstring m_AcceptNpcName;//接任务的等级DWORD m_AcceptLevel; }; 123456789101112131415

可接任务的结构体要比任务详情结构体简单。

任务表的设计

接着准备两张表,一个是已接任务的表,一个是可接任务的表。当前游戏的任务列表如下,这里记录四个

苏醒(一) 去广场拜见村长南苍公 苏醒(二) 去村中集市找阿九 苏醒(三) F9打开背包界面 装备武器木枪 苏醒(四) 去农田打败干枯的稻草人 1234

准备的任务表如下:

//任务表 vector<_stuTaskInfo> g_TaskList= {{/* 任务名字*/L"苏醒(一)",/* 任务ID*/0,/* 交任务的NPC*/L"南苍公",/* 任务内容*/{{Em_对话,L"南苍公",1}},/*是否需要奖励*/FALSE,/* 任务奖励*/{{0}}},{/* 任务名字*/L"苏醒(二)",/* 任务ID*/0,/* 交任务的NPC*/L"阿九",/* 任务内容*/{{Em_对话,L"阿九",1}},/*是否需要奖励*/FALSE,/* 任务奖励*/{{0}}},{/* 任务名字*/L"苏醒(三)",/* 任务ID*/0,/* 交任务的NPC*/L"阿九",/* 任务内容*/{{Em_行为,L"使用装备",1}},/*是否需要奖励*/FALSE,/* 任务奖励*/{{0}}},{/* 任务名字*/L"苏醒(四)",/* 任务ID*/0,/* 交任务的NPC*/L"阿九",/* 任务内容*/{{Em_打怪,L"稻草人",5}},/*是否需要奖励*/FALSE,/* 任务奖励*/{{0}}}, }; //可接任务表 vector<_stuCanGetTaskInfo> g_CanGetTaskList= {{/* 任务名字*/L"苏醒(一)",/* 任务ID*/0,/* 接任务的NPC*/L"南苍公",/* 接任务的等级*/1},{/* 任务名字*/L"苏醒(二)",/* 任务ID*/0,/* 接任务的NPC*/L"南苍公",/* 接任务的等级*/1},{/* 任务名字*/L"苏醒(三)",/* 任务ID*/0,/* 接任务的NPC*/L"阿九",/* 接任务的等级*/1},{/* 任务名字*/L"苏醒(四)",/* 任务ID*/0,/* 接任务的NPC*/L"阿九",/* 接任务的等级*/1}, }; 123456789101112131415161718

任务ID这里暂时不填,另外任务内容,还需要增加一个行为表,来处理苏醒三这种任务。

TaskManager类

这个类需要完成两个函数。首先从当前的已接任务列表中,获取一个任务详情对象。代码如下:

//遍历已接任务列表 获取一个任务详情对象 BOOL TaskManager::GetWorkTask(_stuObjs GetedTaskList, vector<_stuTaskInfo> TaskInfoList, _stuTaskInfo& outTaskInfo, _stuObj& outTaskObj) {//遍历自己设置的任务列表for (auto TaskInfo: TaskInfoList){_stuObj RoleTask;//如果名字不为空 通过名字获取任务对象if (TaskInfo.m_Name !=L""){//在已接任务数据中获取任务对象RoleTask = GetedTaskList.GetDataByName(TaskInfo.m_Name);}//如果ID不为空 通过ID获取任务对象if (TaskInfo.m_ID){RoleTask = GetedTaskList.GetDataByID(TaskInfo.m_ID);}//如果没有这个任务 循环下一个if (RoleTask.m_ID==0){continue;}//如果有 则返回这个任务的任务详情对象和已接任务对象outTaskInfo=TaskInfo;outTaskObj = RoleTask;return TRUE;}return FALSE; } 1234567891011121314151617181920212223242526272829303132333435

这样我们就拿到了一个存在于全局任务表里面的已接任务对象了,这代表这个任务是我们当前需要完成的。

接着如果没有任务,则需要从可接任务里获取一个任务对象,代码如下

BOOL TaskManager::GetCanAcceptTask(_stuObjs CanGetTaskList, vector<_stuCanGetTaskInfo> AcceptTaskList, _stuCanGetTaskInfo& outTaskInfo, _stuObj& outTaskObj) {_stuObj CanGetTask;//遍历可接任务数组 判断是否需要接任务for (auto TaskInfo : AcceptTaskList){//如果任务表的ID不为0if (TaskInfo.m_ID){//则通过ID去可接任务列表中找到任务对象CanGetTask = CanGetTaskList.GetDataByID(TaskInfo.m_ID);}//如果名字不如空if (TaskInfo.m_Name != L""){//则通过ID去可接任务列表中找到任务对象CanGetTask = CanGetTaskList.GetDataByName(TaskInfo.m_Name);}//如果没有这个任务 循环下一个if (CanGetTask.m_ID == 0){continue;}//如果有 则返回这个任务的任务详情对象和已接任务对象outTaskInfo = TaskInfo;outTaskObj = CanGetTask;return TRUE;}return FALSE; } 1234567891011121314151617181920212223242526272829303132333435363738394041 自动接任务

接着来编写我们的自动任务逻辑

//自动任务的线程函数 DWORD AutoTaskProc(LPARAM lParam) {while (true){//获取当前可接任务列表auto CanGetTaskList= GetCanGetTaskData();//任务管理器TaskManager taskManager;//可接任务详情_stuCanGetTaskInfo taskinfo;//任务对象_stuObj taskobj;//获取一个可接任务BOOL IsGetTask = taskManager.GetCanAcceptTask(CanGetTaskList, g_CanGetTaskList, taskinfo, taskobj);//如果获取到了可接任务if (IsGetTask){//开始去接任务(寻路到NPC的位置 接任务)}} } 1234567891011121314151617181920212223242526272829

自动任务的逻辑如上,首先需要获取到可接任务,如果获取到了可接任务,就要去NPC的位置去接任务,那么这里就还需要添加一个NPC的数据表。

//NPC数据表 map<wstring, _stuPos> g_NpcDataList = {{L"南苍公",{0,0,0}},{L"阿九",{0,0,0}},{L"XXX",{0,0,0}}, }; 1234567

这里用map的数据来存储所有的NPC的结构,NPC的坐标可以通过周围遍历去获取,这里逐个记录就可以了。

然后实现一个寻路到NPC的call

//寻路到NPC void Fn_RunToNpc(wstring NpcName, map<wstring, _stuPos> NpcList) {//开始去接任务(寻路到NPC的位置 接任务)auto NpcData = NpcList.find(NpcName);if (NpcData != end(g_NpcDataList)){//调用寻路Call 走到NPC附近Fn_RunToTarget(NpcData->second.x, NpcData->second.y, 1);//等待角色寻路完成 判断角色坐标是否不再产生变化_stuPos LastPos;while (true){//获取角色信息_stuObj RoleData = GetRoleData();//判断最后一次的坐标是否和角色坐标相等 只要有一个不相等 说明角色在寻路if (RoleData.m_Obj_Pos.x!= LastPos.x||RoleData.m_Obj_Pos.y != LastPos.y||RoleData.m_Obj_Pos.z != LastPos.z){//角色在寻路 记录上一次坐标LastPos.x = RoleData.m_Obj_Pos.x;LastPos.y = RoleData.m_Obj_Pos.y;LastPos.z = RoleData.m_Obj_Pos.z;}else{//如果三个坐标都相等 则退出循环break;}Sleep(3000);}} } 1234567891011121314151617181920212223242526272829303132333435

这样就可以实现接任务的逻辑了。

//如果获取到了可接任务if (IsGetTask){//寻路到NPCFn_RunToNpc(taskinfo.m_AcceptNpcName, g_NpcDataList);//接任务Fn_AcceptTask(taskinfo.m_ID);} 12345678910

自动接取任务,逻辑不复杂,但是整个流程如果要自己一个一个去踩坑,就会比较麻烦了。

自动完成任务

接下来就是自动完成任务的逻辑

//获取已接任务列表auto GetedTaskList = GetGetedTaskData();//需要做的任务详情_stuTaskInfo WorkTaskinfo;//需要做的任务对象_stuObj WorkTaskobj;//获取一个需要做的任务BOOL IsGetWorkTask = taskManager.GetNeedWorkTask(GetedTaskList, g_TaskList, WorkTaskinfo, WorkTaskobj);//如果获取到了需要做的任务if (IsGetWorkTask){//判断任务是否已经完成if (taskobj.m_Task_Finish){//寻路到NPCFn_RunToNpc(WorkTaskinfo.m_FinishNpcName, g_NpcDataList);//交任务Fn_CompleteTask(WorkTaskinfo.m_ID);}else{//任务没有完成 需要去做这个任务int index = 0;//遍历存储任务详情的vectorfor (auto Work : WorkTaskinfo.m_WorkList){switch (Work.m_WorkType){case Em_对话:break;case Em_打怪:break;case Em_收集:break;case Em_行为:break;default:break;}}}} 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 自动任务

完整的自动任务逻辑如下:

DWORD AutoTaskProc(LPARAM lParam) {while (true){//获取当前可接任务列表auto CanGetTaskList= GetCanGetTaskData();//任务管理器TaskManager taskManager;//可接任务详情_stuCanGetTaskInfo taskinfo;//任务对象_stuObj taskobj;//获取一个可接任务BOOL IsGetTask = taskManager.GetCanAcceptTask(CanGetTaskList, g_CanGetTaskList, taskinfo, taskobj);//如果获取到了可接任务if (IsGetTask){//寻路到NPCFn_RunToNpc(taskinfo.m_AcceptNpcName, g_NpcDataList);//接任务Fn_AcceptTask(taskinfo.m_ID);}//然后开始去做任务//获取已接任务列表auto GetedTaskList = GetGetedTaskData();//需要做的任务详情_stuTaskInfo WorkTaskinfo;//需要做的任务对象_stuObj WorkTaskobj;//获取一个需要做的任务BOOL IsGetWorkTask = taskManager.GetNeedWorkTask(GetedTaskList, g_TaskList, WorkTaskinfo, WorkTaskobj);//如果获取到了需要做的任务if (IsGetWorkTask){//判断任务是否已经完成if (taskobj.m_Task_Finish){//寻路到NPCFn_RunToNpc(WorkTaskinfo.m_FinishNpcName, g_NpcDataList);//交任务Fn_CompleteTask(WorkTaskinfo.m_ID);}else{//任务没有完成 需要去做这个任务int index = 0;//遍历存储任务详情的vectorfor (auto Work : WorkTaskinfo.m_WorkList){switch (Work.m_WorkType){case Em_对话:break;case Em_打怪:break;case Em_收集:break;case Em_行为:break;default:break;}}}}} } 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182

到这里整个自动任务的框架就已经完成了,我没有去填充实际的数据和做具体的功能测试(其实是因为调试器到期了),代码框架大体就是这样。各位如果想要完成一个完整可用的自动任务的功能,还需要慢慢往这个框架里增加数据和逻辑,并且处理好过程中可能会遇到的问题。

最后的总结

这个系列的文章到这里就已经全部结束了,这个系列的文章给各位提供了RPG游戏通用数据的定位思路,和一个完整的辅助框架的设计流程。当遇到下一个游戏的时候,只需要将准备好的数据,加入到框架的代码里就可以了。如果需要添加新的功能,记得遵循数据和代码逻辑分离的思想,方便后续的复用。

好的,各位,拜了个拜~

Github:https://github.com/TonyChen56/GameReverseNote
完整代码:https://download.csdn.net/download/qq_38474570/79498815

网址:019 自动任务功能的设计和实现 https://www.yuejiaxmz.com/news/view/764289

相关内容

Python定时任务,三步实现自动化
自动化脚本开发,实现自动化任务派发
如何实现自动化操作——Windows任务计划的使用方法详解
PC 下自动化任务,教你 5 步快速实现!
AppTask: 使用Python实现日常APP任务自动化
Linux下的自动化任务与计划任务:让你的系统更智能
用python设计并实现一个简单的任务管理系统
如何使用Python实现日常任务的自动化
项目成功的关键:任务流程自动化
如何在巴点软件中实现自动化任务?

随便看看