企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## MEA-Ship 终于,把基础的概念讲完了。 前面讲的内容可能还不足以让你一下子熟练的编写脚本,但其中涉及的概念和思路是非常有参考价值的。 接下来,让我们开始了解这个由MEA创造的Ship类 class Ship —— “立刻出发” >[danger] 首先必须假设你已经完全了解了前面所涉及到的内容,对基本的名词和概念有所认识。 > ### 引言 Ship是MEA制作并开源的一个编程块脚本中的类(class),或者说,它是一个可以即插即用的脚本开发助手。 在常用的编程块脚本开发中,最基础是工作就是 1. 获取方块,存为变量 2. 调用方块变量的属性和方法,完成一些逻辑操作和控制 当然,这并不是一个繁琐的操作过程。但仅仅是这样并不能满足作为一个Player的需求。 我们经常看到的编程块脚本都是以某一项特定功能为目标而设计的。例如:物流物资管理、LCD显示飞船状态、自动采矿、制导导弹、无人机等。 **以无人机为例:** 一个完善的无人机控制脚本应该至少包含如下功能: 1. 能够以某些方式识别无人机,并获取其中需要控制的远程控制块、推进器、陀螺仪、连接器等。 2. 能够通过某些方式接收母船或玩家发出的指令,并控制无人机做出对应的动作。 3. 指令通常是任务逻辑(去往某个位置、跟随母船...)的形式,而不是行动逻辑(向前移动100米、关闭陀螺仪越级...)。 这样一个脚本的代码结构通常有如下几个层级: * [ ] 1. 方块获取层 * [x] 2. 方块处理层(处理推进器的方向、陀螺仪的方向等) * [x] 3. 方块控制层(批量控制某一侧推进器、批量控制所有不同方向安装的陀螺仪向同一个方向运动的方法) * [x] 4. 算法层(根据所需误差量来操作方块控制层,让方块的输出能满足误差需求,其中可能涉及PID等控制算法) * [x] 5. 功能逻辑层(根据设计的任务功能,封装不同的功能,并连接到算法层,实现功能逻辑) * [ ] 6. 操作层(通过某些交互方式接收用户指令,并控制功能逻辑层) 在这其中: 4、5、6对很多有编程基础的玩家来说,都是一个不小的障碍。 Ship框架的目的,正是为脚本的作者甚至普通玩家提供一个囊括了上图中**勾选项**的开发工具。 ## 简介 >[danger] Ship框架将自己作为一个 **class** 封装起来,不依赖任何外部方法或变量。 目的是为了最大限度保证易用性。你只需要将它整个复制,粘贴,即可放入自己的代码中使用。 它不提供任何获取方块的方法,因为获取方块是一个最基础的工作,脚本的功能决定了它需要获取哪些方块,这也是自由度最高的一个代码层级。 在使用Ship类的时候 ~~~ Ship MyShip; //推荐将Ship变量作为一个公共变量储存,方便全局访问 void Main(){ List<IMyTerminalBlock> blocks ... // 获取方块 MyShip = new Ship(blocks); //传入 List<IMyTerminalBlock> blocks 实例化Ship类 } class Ship{ ... } ~~~ 在此之后,一个Ship类就被实例化成功了,并储存在了MyShip变量中。 之后的所有操作,都可以归纳为对Ship对象MyShip的直接操作。 ~~~ Ship MyShip; void Main(){ MyShip = new Ship(...); //实例化 Vector3D targetPoint = new Vector3D(100,100,0); MyShip.UpdatePhysical(); //更新飞船的物理信息 MyShip.AimAtPosition(targetPoint); //让飞船瞄准坐标 100 100 0 处 MyShip.NavigationTo(targetPoint); //让飞船飞往坐标100 100 0处 } // ==== 开启保存代码后自动运行并自动以每秒60帧速度循环 ==== Program(){ Runtime.UpdateFrequency = UpdateFrequency.Update1; } class Ship(){ ... } ~~~ 在这个例子中,飞船将采用PID算法执行瞄准控制,并采用加速度反馈算法控制推进器导航至目标点。 实际上,在Ship类中,我们将这两个方法进行了封装。 **用坐标点导航算法(NavigationTo)举例,它的执行过程包含了如下几步:** >[danger] 1. 坐标系转换,根据自己驾驶舱将传入的绝对坐标转换到基于自己的坐标系的相对坐标,并获得6个方向的独立分量 >2. 根据自己驾驶舱获得自己的质量信息,并计算6个方向的理论最大加速度 >3. 调用单轴推进辅助函数,并传入该轴向推进器方向、距离差、速度差、加速度最值 3.1 通过传入参数,以当前距离差和速度差计算出理论刹车时间 3.2 通过理论刹车时间计算出当前需要加速还是减速 有兴趣的小伙伴可以去看Ship类中的源代码,这是一个比较复杂的控制过程(一段时间后我自己回过头去看这段算法,都需要一点时间来重新消化)。 Ship类的目的正是将这些繁琐的运算过程简化为一些可复用的方法,当你需要的时候招之即来,当你不需要的时候,你完全可以把它看做一个打包方块变量的袋子。 ~~~ Ship MyShip; void Main(){ MyShip = new Ship(...); //实例化 Echo(MyShip.Thrusts.Count.ToString()); //获取飞船推进器总数 MyShip.SetThrustOverride("Backward", 60); //使用Ship类中的方法设置后方推进器越级60 foreach(IMyThrust t in MyShip.Thrusts){ t.ApplyAction("OnOff_Off"); //同样可以使用游戏自带的接口对方块进行控制。 } } // ==== 开启保存代码后自动运行并自动以每秒60帧速度循环 ==== Program(){ Runtime.UpdateFrequency = UpdateFrequency.Update1; } class Ship(){ ... } ~~~ ### 后话 其实Ship框架中的所有算法都是这么长时间MEA在制作各类控制脚本中总结出来的,在实际应用上经过了大量的检验和升级。在某种意义上,与其说Ship是编程块脚本开发的辅助工具,**倒不如说是MEA对自身成果的总结和开源。**