文章目录

  • 任务详情的设计
  • 任务表的设计
  • TaskManager类
  • 自动接任务
  • 自动完成任务
  • 自动任务
  • 最后的总结

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

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

任务详情的设计

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

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

  1. 任务名字
  2. 任务条件
  3. 接任务的 等级
  4. 需要杀死的怪物数量
  5. 任务的地图
  6. 任务地图的坐标
  7. 交接任务的NPC
  8. 选择的奖励

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

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

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

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

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

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

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

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

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

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

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

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

任务表的设计

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

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

准备的任务表如下:

//任务表
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},
};

任务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;
}

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

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

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;
}

自动接任务

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

//自动任务的线程函数
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的位置 接任务)}}
}

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

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

这里用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);}}
}

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

//如果获取到了可接任务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;}}}}

自动任务

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

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;}}}}}
}

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

最后的总结

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

好的,各位,拜了个拜~

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

019 自动任务功能的设计和实现相关推荐

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

    文章目录 界面代码 流程设计 取最近怪物 自动打怪 界面代码 首先新增一个复选框,绑定控件变量和按钮事件,然后在按钮事件添加如下代码 //自动打怪 void MainWnd::OnBnClickedC ...

  2. 网站自动登录功能的设计[转]

    网站的自动登录一直都是有利于提高用户体验的功能,如果设计不好,也非常容易泄漏用户的账户信息. 比较常见的功能实现方案是将用户的登录信息保存在浏览器的Cookie中.看到一些设计有缺陷的网站会将用户的用 ...

  3. 013 自动吃药功能的设计和实现

    文章目录 功能设计 药品表设计 代码实现 补充 之前我们已经完成了自动打怪和自动技能的功能,但是会存在一个问题,当技能释放多了以后,MP就不够了.这个时候我们就需要通过自动吃药的功能,给前两个功能持续 ...

  4. 网站自动登录功能的设计

    我相信有很多IT者都会遇到公司要求网站可以实现自动登录,那什么是自动登录呢? 所谓自动登陆就是当用户第一次访问网站时,输入用户名和密码,然后勾选了自动登陆复选框,进入首页后,点击退出登陆,关闭网页,再 ...

  5. B题-具有自动泊车功能的电动车赛题解析TI杯2022年省级大学生电子设计竞赛联赛(10月)

    1.赛题解析-具有自动泊车功能的电动车(B题) 2.完成本赛题必备的元器件清单 3.赛题实现与动作分解视频演示 4.任务实现软件部分讲解 5.倒车/侧方入库相关的参数调节方法 6.常见问题整理 无名小 ...

  6. 2022 年 TI 杯大学生电子设计竞赛具有自动泊车功能的电动车(B 题)

    2022 年 TI 杯大学生电子设计竞赛具有自动泊车功能的电动车(B 题) 1.任务 设计制作具有自动泊车功能的电动车,可在图 1 所示的作品测试泊车场地上,分别独立完成"倒车入库/出库&q ...

  7. android设计一个多线程和画图的程序小球,Android开发之多线程中实现利用自定义控件绘制小球并完成小球自动下落功能实例...

    本文实例讲述了Android开发之多线程中实现利用自定义控件绘制小球并完成小球自动下落功能的方法.分享给大家供大家参考,具体如下: 1.布局界面 xmlns:tools="http://sc ...

  8. Android应用自动更新功能实现使用AsyncTask!

    为什么80%的码农都做不了架构师?>>>    我所开发应用不是面向大众的应用,所以无法放到应用市场去让大家下载,然后通过应用市场更新.所以我必要做一个应用自动更新功能.但是不难,T ...

  9. bs模型Nd怎么用计算机算,BS模式的下试卷自动生成系统的设计与实现

    B/S模式的下试卷自动生成系统的设计与实现 信息与计算科学06101班马德岭 指导老师:庄曰华 摘要:教学评价是教学工作的一个重要环节,通常的教学评价方式多为通过试卷进行考试,因而试卷的质量将直接影响 ...

最新文章

  1. SQL 语法速成手册
  2. 使用getopts处理选项
  3. 老年市场是蓝海or沙漠?
  4. leetcode:Sort List(一个链表的归并排序)
  5. java资源文件获取属性_Java读写资源文件类Properties
  6. (lucas) Saving Beans
  7. 从事web前端两年半后的迷茫
  8. 电脑运行VirtualBox虚拟机总是提示0x00000000错误的解决方法
  9. 2016-6-3Ajax异步复习
  10. Python 文件(文件夹)匹配(glob模块)(转载)
  11. cocos2d-js adblock插件冲突
  12. RDKit | RDKit分子结构图的详细说明
  13. C/C++ 实现模拟键盘鼠标
  14. 微信小程序(翻译小助手)项目实战
  15. 树莓派与DHT11温度传感器的那些事儿
  16. 【智库解读】明天系、安邦系、海航系、复星系、联想系、中植系、三胞系、宝能系等27个超级民营金融巨头名单及其持股图揭秘!
  17. 视频名词浅析——HDR
  18. 服务器和售票系统,网上售票系统的开发与实现.doc
  19. 数据挖掘时功能和一个聚类分析应用案例
  20. idea配置有道翻译引擎

热门文章

  1. 读书笔记5.3——《让数字说话:审计,就这么简单》:孙含晖
  2. 如何给自己心仪的人每天发送天气提醒消息
  3. python做量化交易
  4. CM2013 能用的 虚假的汉化工具
  5. H5微信分享踩坑大全--文末有微信分享代码大全
  6. 我们拿这10年做什么——让计划服从变化
  7. 8位同步码修改变4位同步码
  8. 利用python编写祝福短信_python实现祝福弹窗效果
  9. 【JDK8语法新特性】:超全总结{lamda,stream,optional,新日期类API},JDK8对策略模式支持,可以直接贴代码运行测试。
  10. 右下角弹出程序的罪魁祸首原来是谷歌浏览器的通知