之前我们已经完成了自动打怪和自动技能的功能,但是会存在一个问题,当技能释放多了以后,MP就不够了。这个时候我们就需要通过自动吃药的功能,给前两个功能持续输出动力。
功能设计
自动吃药的逻辑和自动技能的逻辑思想一样,都是通过建表的思想,判断各种条件,筛选出当前最适合的一个药品,然后调用吃药call。
现在假设有三种药
药1 回血100 1级
药2 回血500 10级
药3 回血1000 20级
当角色在1-10级的时候只需要使用药1即可;在10-20级的时候,优先使用药2,药1的优先级低于药1;在20-30级的时候,药3的优先级大于药2大于药1
1-10级 药1
10-20级 药2和药1
20-30级 药3和药2和药1
根据上面设计的方法,就可以按照角色等级,当前的HP和MP来对药品设计一个权值
角色等级1-10级
药1 HP 0-40% 权值50
角色等级11-20
药2 HP 0-40% 权值60
药1 HP 30-60% 权值50
角色等级21-30
药3 HP 0-40% 权值70
药2 HP 30-50% 权值60
药1 HP 50-60% 权值50
这里就可以在血量多的时候先吃小的药,然后在血量少的时候吃大的药,然后再将这套方法用代码实现即可。
药品表设计
首先新建一个UseItemManager
类
//药品使用详情
struct _stuItemUseInfo
{
//药品名字
wstring m_name;
//药品类型
EmDrugType m_drugtype;
//权值
int m_weight;
//需求
//自身条件 MP范围
_stuValRange m_MpRange;
//等级范围
_stuValRange m_LevelRange;
};
接着创建一个药品使用详情结构体
enum EmDrugType
{
Em_回血,
Em_回蓝
};
//范围属性
struct _stuValRange
{
//最小值
int MinValue;
//最大值
int MaxValue;
};
还有药品类型的宏定义,和范围属性结构体
//药品管理
extern UseItemManager g_UserItemManager;
接着在GlobalData.h中引入药品管理的全局变量。
//药品管理
UseItemManager g_UserItemManager;
GlobalData.cpp中声明
//药品表
vector<_stuItemUseInfo> g_ItemList =
{
{/* 药品名字*/L"魔法药(小量)",/*药品类型*/Em_回蓝,/* 权重*/60,/*HP范围*/{-1,-1},/*MP范围*/{10,800},/*等级范围*/{-1,-1}},
{/* 药品名字*/L"魔法药(中量)",/*药品类型*/Em_回蓝,/* 权重*/70,/*HP范围*/{-1,-1},/*MP范围*/{10,700},/*等级范围*/{0,0}},
{/* 药品名字*/L"强效魔法药",/*药品类型*/Em_回蓝,/* 权重*/80,/*HP范围*/{-1,-1},/*MP范围*/{10,600},/*等级范围*/{0,0}},
{/* 药品名字*/L"金创药(小量)",/*药品类型*/Em_回血,/* 权重*/60,/*HP范围*/{50,150},/*MP范围*/{-1,-1},/*等级范围*/{-1,-1}},
{/* 药品名字*/L"金创药(中量)",/*药品类型*/Em_回血,/* 权重*/70,/*HP范围*/{40,130},/*MP范围*/{-1,-1},/*等级范围*/{-1,-1}},
{/* 药品名字*/L"强效金创药",/*药品类型*/Em_回血,/* 权重*/80,/*HP范围*/{30,100},/*MP范围*/{-1,-1},/*等级范围*/{-1,-1}},
};
然后设计一个全局的药品表,-1表示不判断条件。
代码实现
UseItemManager.h
class UseItemManager
{
//设置药品数据
void SetDrugData(vector<_stuItemUseInfo> drugdata);
//获取最优的使用的技能 传入自身数据和目标数据
_stuObj GetTheBestUseDrug(_stuObj role, _stuObj obj, _stuObjs druglist);
public:
//药品的使用数据表
vector<_stuItemUseInfo> m_DrugList;
};
UseItemManager.cpp
#include "pch.h"
#include "UseItemManager.h"
void UseItemManager::SetDrugData(vector<_stuItemUseInfo> drugdata)
{
m_DrugList = drugdata;
}
_stuObj UseItemManager::GetTheBestUseDrug(_stuObj role, _stuObj obj, _stuObjs druglist)
{
//符合条件的药品列表
vector<_stuItemUseInfo> DataList;
//遍历技能列表 筛选出符合条件的技能
for (auto &item : m_DrugList)
{
//通过药品名字返回技能对象
auto DrugObj = druglist.GetDataByName(item.m_name);
//技能名称为空 跳过
if (DrugObj.m_Name == L"")
{
continue;
}
//-1表示不判断
if (item.m_HpRange.MinValue!=-1&& item.m_HpRange.MaxValue!=-1)
{
//判断血量是否在设置的范围内
if (!(role.m_Obj_HP > item.m_HpRange.MinValue&&role.m_Obj_HP < item.m_HpRange.MaxValue))
{
continue;
}
}
//-1表示不判断
if (item.m_MpRange.MinValue != -1 && item.m_MpRange.MaxValue != -1)
{
//判断蓝量是否在设置的范围内
if (!(role.m_Obj_MP > item.m_MpRange.MinValue&&role.m_Obj_MP < item.m_MpRange.MaxValue))
{
continue;
}
}
//把符合的药品存放到表里
DataList.push_back(item);
}
//筛选出权重最高的药品
int NowValue = 0;
_stuItemUseInfo ChooseDrug;
for (auto drug : DataList)
{
if (drug.m_weight > NowValue)
{
//记录当前药品权重
NowValue = drug.m_weight;
//保存当前药品对象
ChooseDrug = drug;
}
}
//返回权值最高的药品
return druglist.GetDataByName(ChooseDrug.m_name);
}
代码和自动技能差不多,自动吃药的逻辑也相对很简单,就是循环判断当前是否有符合条件的药品,如果有,那么说明角色血量和蓝量掉到了一定程度,就可以调用吃药call进行补充了。一共也就几行代码,这里就不写了。
这个游戏技能和药品都没有CD的概念,如果换到了别的游戏,则需要将CD的数据和条件考虑进去。
补充
最后,这个设计其实还有一个不完美的地方,就是判断的血值范围是用具体的数字,这样每次人物等级提升的时候都需要重新修改,最好的方式是修改成百分比,这样就不需要一直修改了。这个问题修改起来并不难,相信各位都可以自己完成。
Github:https://github.com/TonyChen56/GameReverseNote
完整代码:https://download.csdn.net/download/qq_38474570/79498815