跳转至

一个基本治疗者状态机

下一步是定义机器人实际行为。为了让示例代码简单,假设你在实现自动治疗者。这个治疗者有两种治疗方式:玩家生命值低于或等于 50% 时使用强治疗,生命值在 51% 到 70% 之间时使用弱治疗。

表示这个行为的状态机需要两个状态,一个用于强治疗,一个用于弱治疗。首先,你需要把状态机定义为包含两个 StateDefinition 对象的向量:

std::vector<StateDefinition> stateMachine(2);

这段代码创建一个名为 stateMachine 的状态机,并用两个空的 StateDefinition 对象初始化它。接下来,你为这些状态定义定义 condition() 和 reach() 函数。强治疗状态最重要,因为它防止角色死亡,所以它应该在向量中排第一,如清单 11-1 所示。

auto curDef = stateMachine.begin();
curDef->condition = [](GameSensors* sensors) {
  return sensors->getHealthPercent() > 50;
};
curDef->reach = [](GameSensors* sensors, 
GameActuators* actuators) {
};

清单 11-1:强治疗状态的代码

这段代码首先创建一个名为 curDef 的迭代器,指向 stateMachine 向量中的第一个 StateDefinition 对象。然后定义对象的 condition() 函数①;用中文说,这个定义是:「如果玩家生命值百分比大于 50,状态就满足。」如果状态不满足,对象的 reach() 函数就调用 strongHeal() 动作函数②,执行强治疗。

强治疗状态定义好后,接下来定义弱治疗状态,如清单 11-2 所示。

curDef++;
curDef->condition = [](GameSensors* sensors) {
  return sensors->getHealthPercent() > 70;
};
curDef->reach = [](GameSensors* sensors, 
GameActuators* actuators) {
  actuators->weakHeal();
};

清单 11-2:弱治疗的代码

递增 curDef 使它指向 stateMachine 向量中的第二个 StateDefinition 对象后,这段代码把对象的 condition() 函数①定义为「如果玩家生命值百分比大于 70,状态就满足。」它还把对象的 reach() 函数定义为 actuators->weakHeal() 调用②。

完成状态机定义后,你必须实现控制器。由于控制器的实际行为包含在状态机中,你只需添加一个简单循环完成它:

for (auto state = stateMachine.begin(); state != 
stateMachine.end(); state++) {
    if ( !state->condition(&sensors)) {
        state->reach(&sensors, &actuators);
        break;
    }

这个控制器循环遍历状态机,执行 condition() 函数返回 false 的第一个状态的 reach() 函数①,并在调用任何 reach() 函数后跳出。最后一步是实现反馈回路,把控制器循环放进去,如清单 11-3 所示。

while (true) {
    for (auto state = stateMachine.begin();
        state != stateMachine.end();
        state++) {
        if (!state->condition(&sensors)) {
            state->reach(&sensors, &actuators);
            break;
        }
        Sleep(FEEDBACK_LOOP_TIMEOUT);
    }
}

清单 11-3:最终治疗状态机和反馈回路

这个循环持续执行控制器循环,并在每次执行之间休眠 FEEDBACK_LOOP_TIMEOUT 毫秒。Sleep() 调用让游戏服务器接收并处理上一次迭代的任何执行,也让游戏客户端在下次执行控制器循环前接收服务器发出的任何执行结果。

如果你对我刚展示的内容还有点困惑,看看图 11-3,它展示了清单 11-3 中无限循环代码如何工作。首先,它检查强治疗条件是否为 true,如果是,就检查弱治疗条件。如果强治疗条件为 false,玩家生命值必须低于或等于 50%,所以会调用强治疗方法。如果弱治疗条件检查为 false,玩家生命值必须在 51%到 70% 之间,所以会执行弱治疗方法。

任何一种方法之后,机器都会休眠。如果两个条件检查都为 true,玩家不需要治疗。机器不做任何改变状态的事情,休眠,然后在 while 循环顶部重新开始。