diff --git a/doc/posts/1_rocos_basic/1_2_0_simple_play.md b/doc/posts/1_rocos_basic/1_2_0_simple_play.md index 1cffed3..28e7e4f 100644 --- a/doc/posts/1_rocos_basic/1_2_0_simple_play.md +++ b/doc/posts/1_rocos_basic/1_2_0_simple_play.md @@ -116,4 +116,15 @@ name = 'TestMyRun', `Client`的每次重启都会加载最新的战术包,如果不重启也可以手动刷新。你可以通过勾选设置是否进入测试模式,并在下拉框中选择你想要测试的Play,然后点击按钮来运行。 -现在你可以通过界面配置并执行刚刚书写的`TestMyRun`了。 \ No newline at end of file +现在你可以通过界面配置并执行刚刚书写的`TestMyRun`了。 + +## 总结 + +一个典型的play脚本,应该包含以下几个部分: +- 整个play是一个`table`,通过`gPlayTable.CreatePlay`来创建。 +- `firstState`是play的初始状态。 +- `name`是play的名称。 +- 每个状态是一个KV键值对,key是状态名称,value是一个`table` + - `switch`是状态切换函数,用于返回下一个状态的名称。 + - `match`是匹配规则,用于匹配对应的角色。 + - 其他的key是角色名称,value是一个`task`。 \ No newline at end of file diff --git a/doc/posts/1_rocos_basic/1_2_1_closure_params.md b/doc/posts/1_rocos_basic/1_2_1_closure_params.md index 6dc0ca1..5f3dfae 100644 --- a/doc/posts/1_rocos_basic/1_2_1_closure_params.md +++ b/doc/posts/1_rocos_basic/1_2_1_closure_params.md @@ -75,7 +75,7 @@ end 实现的效果如下: ```{thumbnail} ../../img/1_2_1_run_circle.gif - :width: 70% + :width: 40% :align: center ``` diff --git a/doc/posts/1_rocos_basic/1_3_2_switch_function.md b/doc/posts/1_rocos_basic/1_3_2_switch_function.md index fed20a4..50317b6 100644 --- a/doc/posts/1_rocos_basic/1_3_2_switch_function.md +++ b/doc/posts/1_rocos_basic/1_3_2_switch_function.md @@ -1 +1,68 @@ -# Play - 状态跳转函数[TODO] +# Play - 状态跳转函数 +在[Play - 让机器人动起来](./1_2_0_simple_play.md)一节中,我们通过简单的脚本演示了如何实现两点间的运动。在脚本中,有一个`switch`函数,用于切换不同的状态。在本节中,我们将详细介绍`switch`函数的使用方法。 + +## switch函数的运行 + +`switch`函数是Play中的一个重要组成部分,用于判断当前状态是否需要切换到下一个状态。在Play的执行过程中,每一帧开始当前状态的`switch`函数会被立刻调用,以判断是否需要切换状态。下面是一个简单的例子: + +```lua +gPlayTable.CreatePlay{ + firstState = 'run1', -- 初始状态 + + ['run1'] = { + switch = function() -- 判断如果到达目标点则结束脚本 + if player.toTargetDist('Leader') < 100 then + return 'finish' + end + end, + Leader = task.goto(Pos(0,0)), -- 设置任务:移动到(0,0) + match = '(L)' -- 用于Leader角色的单次匹配 + }, + + name = "TestRun", -- Play的名称 +} +``` + +在上面的代码中,`switch`函数判断了Leader角色是否到达目标点,如果到达则返回`finish`状态,Play结束。在实际的开发中,`switch`函数可以根据不同的需求进行自定义,例如判断是否到达目标点、是否有敌方机器人等。其返回值的类型为`string`,表示下一个状态的名称,如果返回`nil`则表示不切换状态,继续执行当前状态。其返回值的类型以及含义具体如下: + +- `nil`(`return nil`或无`return`):不切换状态,继续执行当前状态。 +- `exit`或者`finish`:结束Play的执行(一般用于定位球等脚本执行完跳转到一般脚本)。 +- 其他`string`:下一个状态的名称,表示切换到下一个状态。 + +## switch函数的一般使用 + +在实际的开发中,`switch`函数的使用可以大致归类为以下几种情况: + +* 基于几何信息 + * 距离(到点/到球/到某个机器人/禁区/球门/边界) + * 角度(朝向/角度差) + * 速度(机器人速度/球速) + * 位置(在某个区域/在某个角色附近) +* 基于事件 + * 某个机器人是否持球 + * 某个机器人是否踢球 + * 红外传感器信息 + * 球出界 + * 球消失 + * 机器人数量变化 +* 基于裁判盒信息 + * 比赛状态(Normal Start指令) +* 基于时间 + * 固定时间 + * 满足某条件后的持续时间(bufcnt函数) +* *其他* + * 自动裁判机状态等 + +上述的所列举的判断有部分已经封装成更容易使用的接口,分布在`player.lua`/`enemy.lua`/`ball.lua`/`cond.lua`这几个模块中。 + +:::{admonition} 小trick +由于当前play框架中,并没有设计除了switch以外的每帧调用的代码段,所以有时也会将需要在当前帧调用的任务放在switch里面,例如: +* 多机器人协同的策略模块(c++)层的调用 +* 希望在play层临时绘制的debug可视化信息 +* 特殊的,*如果你遇到了需要在第一次进入play时初始化的情况,可以将fristState设置成init,并将init状态的switch作为你的初始化函数使用* + +::: + +## 总结 + +依据上述介绍,我们可以看到`switch`函数在Play中的重要性。通过`switch`函数,我们可以根据不同的需求切换状态,实现复杂的策略逻辑。在实际的开发中,我们可以根据不同的需求自定义`switch`函数,实现更加灵活的策略逻辑。 \ No newline at end of file