【兴趣发展】简述如何制作战斗模拟器
简述如何制作战斗模拟器
对于数学问题,自己想出答案和确认别人的答案是否正确,哪一个更简单
设计别人解不开的谜题和解开那个问题,何者更难?
开篇两句与本篇主题关系并不密切,只为吸引点击。。
这篇稿子会简单介绍如何制作一个战斗模拟器。战斗模拟器可能很多人做过或者尝试做过。战斗模拟器在对某些量化较难的战斗类型,可以起到验证作用(也只是如此而已)。
制作一个战斗模拟器还是有些微门槛的——0基础需要约5~8小时左右的VBA学习。而在制作过程中,可以对已掌握的VBA知识进行一番实战,也可以让自己对战斗设计的细节部分想的更加透彻。
制作准备:
基础VBA知识
处于网络环境(用于临时搜索查询)
对战斗系统的足够了解
需求整理:
本次制作的模拟器,模拟的是一个7宫格的卡牌对战(可想象为2个队伍分别“凸”对方):
统计若干次战斗的胜负,计算出胜率%
战斗日志,对于战斗中的攻击/技能的发动,展示其伤害值及相应的被攻击单位的血量变化,以及相应的发动技能所消耗的怒气/能量值的变化情况。
支持对技能的攻击目标顺位规则自定义。
虽然为讲述方便,本文介绍的是不带buff的战斗情形,但考虑到代码的复用性,本模拟器应支持较少的代码改动即可支持buff的添加和删除。
同上,虽然本例经简化没有进行暴击/命中等判定,但实际上可以三两行代码添加该功能。
战斗界面应是一个独立的窗体,否则在sheet里容易在操作时发生各种异常。
成品展示:
开始制作:
我们先把模拟器拆成4个部分:
- 配置部分
- 属性展示
- 战斗过程
- 战报展示
1.1. 配置部分
这部分分2块,1个是上阵的卡牌配置,另1个是技能配置,分别如下:
技能表的e/f/g列分别代表技能在位于上中下路释放技能时,选择目标的位置编号的优先顺序。
1.2. 属性展示
ALT+F11呼出VBE窗口,创建一个userform,使用2个listbox用以读取配置中的武将列表,其余控件类型见下图:
补充说明,插入用户窗体的方法见下图:
1.3. 战斗过程
这部分大概是最繁琐的。
先介绍一个概念——集合对象。
1.3.1. 集合对象
Office 2013 and later
Collection 对象是可作为一个单元引用的已排序的项目集合。
注释
Collection 对象提供了一种将一组相关项目当作单个对象的便捷方式。集合中的项目或成员只需要根据它们存在于该集合中这一事实进行关联。集合的成员不必具有同一数据类型。
可以采用创建其他对象的相同方法来创建集合。例如:
Dim X As New Collection
集合创建后,可使用 Add 方法添加成员或使用 Remove 方法删除成员。使用 Item 方法可从集合中返回特定成员,而使用 For Each...Next 语句可循环访问整个集合。
通过使用集合对象,我们可以把双方的武将分别放进2个集合中,这样可以方便的使用for each循环语句,挨个行动,当然也可以在将来扩展出“速度”属性时,对武将集合进行速度的排序。以下是回合循环的部分代码(完整代码会附件方式放在最后)
1.3.2. 类模块
我创建了武将和技能2个类(vba叫类模块),不知道是不是有必要,但是我还是用自己的理解解释一下吧,(因为本文是希望0基础的同学也可以在数小时内学习和完成编辑器制作的)——类,就是类别的意思,英文是Class(非拽文,部分时候确实英文更好理解些),它是对“对象”的抽象,“对象”就是某个具体的武将(比如张飞、赵云)、技能。那么“武将”就是类,“张飞”就是属于“武将”类的一个具体的东西。
创建一个类的方法是:
费这么大劲创建了武将类之后,我们就可以使用“.语法”(点语法)给武将这个类定义各种属性,比如:武将名、攻击力、生命值、技能ID等等。
还可以给这个类定义方法:
比如我们可以在血量结算时,在log里加入记录,或者在进行攻击或者释放技能后做点什么事情。一切你能想到的东西,都可以尝试在这里加入。
1.3.3. 类的属性和方法
给类添加属性的语法为:
Private wname$
相应的存/取值的方法为:
Public Property Get Name() As String
Name = wname
End Property
Public Property Let Name(ByVal newValue As String)
wname = newValue
End Property
估计没接触面向对象编程的同学看到上面这段有这种困扰,为什么有2个方法,3个变量,我继续用土话翻译(不一定最准确,但可能更好理解,最终我们只要知道怎么用即可):
Name是武将这个类的“武将名字“属性对外的称呼,wname则是对类的(私有的)。
在我们创建一个类的实例时,比如张飞:
Dim wa02 As New Warriors
我们再让wa02这个武将的名字叫张飞。
wa02.Name = .Cells(3, 2).Value 注:第3行第2列的单元格所填的内容是”张飞”
这时候调用的方法是
Public Property Let Name(ByVal newValue As String)
wname = newValue 注:这里newValue的值就是”张飞”
End Property
而在我们使用.语法调用张飞这个武将的名字属性时,比如:
Debug.print wa02.Name
这时,调用的方法是
Public Property Get Name() As String
Name = wname
End Property
1.3.4. 战斗的循环
除了冗长的赋值,战斗逻辑部分的代码应该是100~300行之间,主要分为2个过程:
1是回合过程,2是技能过程。
回合过程中,使用Do while语句依次遍历进攻方和防守方武将,判断其是否行动过,是否能行动,是否阵亡。这里可以使用And函数,或上流的2进制(如状态属性为xxxx,第一个x取值0或1代表是否行动过)
技能过程接收一个技能ID的参数,对该ID的技能所配置的攻击目标的位置序列进行遍历,依次进行攻击,直至达到最大目标数。
1.4. 战报展示
使用一个textbox控件放置战斗日志,这个textbox的文本内容,在我们追踪的事件过程中,会被更新并显示在战斗界面中,以伤血结算为例:
每个武将的血量变化,将会在原本的TXET值的后面文本连接相应的提示内容。
以上就是一个简单的战斗模拟器的制作过程了,相应的excel见附件。
1 / 9
EXCEL密码:1303215