## 获取方块
我们知道了方块是一个类,那么方块是不是需要通过new方法实例化出来呢?
并不是
当一个方块被放置在游戏场景中的瞬间,游戏的其他代码就已经将这个方块通过new方法实例化出来了。
而我们在编程块中所能做的,只是通过K社提供的几个方法来获取已经存在于场景中的方块。
记住这几点:
>[danger] 1.在编程块中,你只能获取已经存在的方块。
>2.由于编程块本身就是一个方块,你只能在编程块中获取与编程块连接的其他方块。(同网格,包括子网格)
>**3.当你通过某个方法获取了一个方块,并将它赋值给一个公共变量后。只要这个公共变量没有被重新赋值,并且编程块也没有被初始化。在之后的任何时间,编程块中的这个公共变量都能代表这个方块。**
>****
>**这意味着,当你用编程块获取一个方块并赋值给公共变量后,哪怕这个方块脱离了编程块所在网格,并且飞出去无论多远,编程块都可以通过这个公共变量来直接操控这个方块!**
>
>**这就是我们所说的“纠缠效应”**
### 如何获取方块?
K社给了一个类,这个类就相当于编程块本体(大概可以这样理解,可能不准确)。
在编程块中的任何函数中(除了类中),都可以直接使用GridTerminalSystem来访问这个类中的代码。
**编程块有且只有这些方法来获取方块**
>[danger] 顺便提一下,在编程块中。“Me”这个单词,代指编程块自己,它的类型是IMyProgrammableBlock。
>你可以在Main函数中试着写 Echo(Me.CustomName.ToString()); 试试
~~~
namespace Sandbox.ModAPI.Ingame
{
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public interface IMyGridTerminalSystem
{
void GetBlockGroups(List<IMyBlockGroup> blockGroups, Func<IMyBlockGroup, bool> collect = null);
IMyBlockGroup GetBlockGroupWithName(string name);
void GetBlocks(List<IMyTerminalBlock> blocks);
void GetBlocksOfType<T>(List<IMyTerminalBlock> blocks, Func<IMyTerminalBlock, bool> collect = null) where T: class;
void GetBlocksOfType<T>(List<T> blocks, Func<T, bool> collect = null) where T: class;
IMyTerminalBlock GetBlockWithId(long id);
IMyTerminalBlock GetBlockWithName(string name);
void SearchBlocksOfName(string name, List<IMyTerminalBlock> blocks, Func<IMyTerminalBlock, bool> collect = null);
}
}
~~~
光看这些函数的定义,可能不太明白怎么使用。特别是有些void类型的空函数,明明不返回任何值,为什么可以获取到方块,它把获取到的方块放在了哪里?
下面分别举例(这里我只列举两个最常用的):
~~~
//我们通常将方块存为公共变量,这样一方面可以利用纠缠效应,另一方面可以通过一些办法仅在编程块第一帧获取方块,之后就不需要再获取了。
IMyTerminalBlock LCD;
List<IMyThrust> Thrusts;
void Main(){
//获取单个方块
LCD = GridTerminalSystem.GetBlockWithName("LCD_1"); //获取名字包含LCD_1的单个方块。
//注意,这个方法返回的是IMyTerminalBlock类型。
//子类可以直接使用父类的方法,但父类不能使用子类的,这时候我们想使用IMyTextPanel里的WritePublicText()方法给LCD写入文字怎么办呢?
IMyTextPanel LCD_TextPanel_1 = GridTerminalSystem.GetBlockWithName("LCD_1") as IMyTextPanel; //方法1
IMyTextPanel LCD_TextPanel_2 = LCD as IMyTextPanel; //方法2
//可以使用as将父类直接转换成子类,上面这两个写法都是可以的。
//获取多个方块
Thrusts = new List<IMyThrust>(); //记得List结构必须要new以后才可以使用,否则报错
GridTerminalSystem.GetBlocksOfType(Thrusts); //获取到了所有的IMyThrust类型的方块并存入了Thrusts变量中。
//通过条件筛选获取多个方块
Thrusts = new List<IMyThrust>(); //我们重新new了一下Thrust,让它成为一个空List。实际上这里不new也不会报错,因为在GetBlocksOfType方法中,它也会被new一次再赋值的。
GridTerminalSystem.GetBlocksOfType(Thrusts, b => b.CustomName=="MyThrust"); //获取所有类型是IMyThrust并且名字是"MyThrust"的推进器。
/*
这个方法实际上使用了Linq查询,有兴趣可以看Linq部分。如果你只是使用,那么背下来即可
GetBlocksOfType这个方法,必须传入一个参数,并且它使用了out方法,将传入的参数赋值了。
你传入的参数是什么类型,它就会搜索什么类型的方块。
第二个参数可选传入,如果不传入,默认是无条件获取所有该类型方块。如果传入,必须传入一个Linq语句。实际上这里的 b 就代指搜索到的每一个推进器
你也可以用a或者别的,=>是固定写法,=>右侧是一个bool值,相当于判据
如果bool值是true,这个方块就被纳入选择范围,否则不纳入。
不太明白的话,我们再举两个例子
*/
List<IMyTerminalBlock> Blocks = new List<IMyTerminalBlock>();
GridTerminalSystem.GetBlocksOfType(Blocks); //获取所有方块,IMyTerminalBlocks是所有功能方块的基类,记得吗?
GridTerminalSystem.GetBlocksOfType(Blocks, b => true); //这一行与上一行等效,因为我们给的bool值被写死成true
GridTerminalSystem.GetBlocksOfType(Blocks), b => b.CustomName.Contains("MEA"); //只获取名字包含MEA的方块
GridTerminalSystem.GetBlocksOfType(Blocks, b => b.CustomName.StartsWith("MEA_"));//只获取名字以MEA_头的方块
}
~~~
- 序言
- 写在前面的话
- 太空工程师
- MEA小组
- 一、入门
- 1.1 基础概念
- 1.2 编程工具
- 1.3 变量
- 1.4 函数 Function
- 1.5 基本语法
- 1.5.1 运算符
- 1.5.2 if
- 1.5.3 for
- 1.5.4 其他语法
- 1.3 类 Class
- 二、编程块
- 2.1 方块的概念
- 2.2 List<T>结构
- 2.3 获取方块
- 2.4 方块的使用
- 三、Ship 类
- 3.1 简介
- Ship v0.5
- 代码
- 手册(待更新)
- 例子(待更新)
- Ship v1.0
- 代码
- 例子
- 文档
- 实例化
- 内置变量
- 内置方法
- Target类
- 四、运动控制算法在SE中的应用
- 4.1 运动控制介绍
- 4.2 过程控制
- 4.3 震荡和动态误差
- 4.4 误差累加方案
- 4.5 PID算法
- 4.6 对PID算法的一点点简化
- 4.7 一阶惯性系统的PID算法优化的研究
- 五、MEA方块类
- 5.0 核心代码目录
- v1.0核心代码
- v1.1 核心代码
- v2.0 核心代码
- 5.1 类的概念
- 5.2 MEA的方块类(Block)
- 5.3 方块类文档
- 5.4 方块类2.0 全教程
- 5.4.1 安装和使用
- 5.4.2 方块类(Block)
- 5.4.3 显示屏类(DisplayScreen)
- 5.4.4 LCD类(LCD)
- 5.4.5 主控座椅类(Cockpit)
- 六、疯猴的编程笔记
- 第一个程序
- 获取和控制其他块
- 物流与生产
- 界面与通信
- 运动与姿态
- 侦测与导航
- 七、SteamZhou的笔记
- 有趣而花里胡哨的IDEA
- 八、质子对撞炮的笔记
- 属性 Property
- 接口 interface