~~~
public class Ship
{
// ----- 方块类变量 -----
public IMyShipController Cockpit;
public IMyShipConnector Connector;
public IMyShipConnector MotherConnector;
public List<IMyLargeTurretBase> AutoWeapons = new List<IMyLargeTurretBase>();
public List<IMySmallGatlingGun> GatlingGuns = new List<IMySmallGatlingGun>();
public List<IMySmallMissileLauncher> RocketLaunchers = new List<IMySmallMissileLauncher>();
public List<IMyCameraBlock> Cameras = new List<IMyCameraBlock>();
public List<IMyGyro> Gyroscopes = new List<IMyGyro>();
public List<IMyThrust> Thrusts = new List<IMyThrust>();
public List<string> ThrustField = new List<string>();
public List<string> gyroYawField = new List<string>();
public List<string> gyroPitchField = new List<string>();
public List<string> gyroRollField = new List<string>();
public List<float> gyroYawFactor = new List<float>();
public List<float> gyroPitchFactor = new List<float>();
public List<float> gyroRollFactor = new List<float>();
// ---- 必要配置变量 ----
public static int timetick;
public string Debug = "Normal"; //错误报告,通过这个变量判断是否初始化成功
// ----- 运动信息和相关变量 -----
public Vector3D Position;
public Vector3D Velocity;
public Vector3D Acceleration;
public double Diameter;
// ---- 瞄准PID算法参数 ------
public double AimRatio = 3; //瞄准精度,单位:度。用来是否瞄准,以便其他动作判断。不影响瞄准的效率。当瞄准块的正前方向量与瞄准块和目标的连线向量夹角小于这个值时,整个系统判定瞄准了目标。
public int AimPID_T = 5; //PID 采样周期(单位:帧),周期越小效果越好,但太小的周期会让积分系数难以发挥效果
public double AimPID_P = 0.8; //比例系数:可以理解为整个PID控制的总力度,建议范围0到1.2,1是完全出力。
public double AimPID_I = 3; //积分系数:增加这个系数会让静态误差增加(即高速环绕误差),但会减少瞄准的震荡。反之同理
public double AimPID_D = 10; //微分系数:增加这个系数会减少瞄准的震荡幅度,但会加剧在小角度偏差时的震荡幅度。反之同理
// 初始化方块方法
public Ship(){}
public Ship(List<IMyTerminalBlock> Blocks)
{
//这里面可以写入更详细的判断方块是否需要获取的条件,例如名字匹配
foreach(IMyTerminalBlock b in Blocks){
if(b is IMyShipController){
this.Cockpit = b as IMyShipController;
}
if(b is IMyCameraBlock){
this.Cameras.Add(b as IMyCameraBlock);
}
if(b is IMyLargeTurretBase){
this.AutoWeapons.Add(b as IMyLargeTurretBase);
}
if(b is IMySmallGatlingGun){
this.GatlingGuns.Add(b as IMySmallGatlingGun);
}
if(b is IMySmallMissileLauncher){
this.RocketLaunchers.Add(b as IMySmallMissileLauncher);
}
if(b is IMyGyro){
this.Gyroscopes.Add(b as IMyGyro);
}
if(b is IMyThrust){
this.Thrusts.Add(b as IMyThrust);
}
if(b is IMyShipConnector && (b as IMyShipConnector).OtherConnector != null){
this.Connector = b as IMyShipConnector;
this.MotherConnector = Connector.OtherConnector;
}
}
if(Cockpit == null) {Debug = "Cockpit Not Found"; return;}
Cameras.ForEach(delegate(IMyCameraBlock cam){cam.ApplyAction("OnOff_On");cam.EnableRaycast = true;});
//处理推进器
for(int i = 0; i < Thrusts.Count; i ++)
{
Base6Directions.Direction CockpitForward = Thrusts[i].WorldMatrix.GetClosestDirection(Cockpit.WorldMatrix.Forward);
Base6Directions.Direction CockpitUp = Thrusts[i].WorldMatrix.GetClosestDirection(Cockpit.WorldMatrix.Up);
Base6Directions.Direction CockpitLeft = Thrusts[i].WorldMatrix.GetClosestDirection(Cockpit.WorldMatrix.Left);
switch (CockpitForward)
{ case Base6Directions.Direction.Forward: ThrustField.Add("Forward"); break; case Base6Directions.Direction.Backward: ThrustField.Add("Backward"); break; }
switch (CockpitUp)
{ case Base6Directions.Direction.Forward: ThrustField.Add("Up"); break; case Base6Directions.Direction.Backward: ThrustField.Add("Down"); break; }
switch (CockpitLeft)
{ case Base6Directions.Direction.Forward: ThrustField.Add("Left"); break; case Base6Directions.Direction.Backward: ThrustField.Add("Right"); break; }
Thrusts[i].ApplyAction("OnOff_On");
}
//处理陀螺仪
for (int i = 0; i < Gyroscopes.Count; i++)
{
Base6Directions.Direction gyroUp = Gyroscopes[i].WorldMatrix.GetClosestDirection(Cockpit.WorldMatrix.Up);
Base6Directions.Direction gyroLeft = Gyroscopes[i].WorldMatrix.GetClosestDirection(Cockpit.WorldMatrix.Left);
Base6Directions.Direction gyroForward = Gyroscopes[i].WorldMatrix.GetClosestDirection(Cockpit.WorldMatrix.Forward);
switch (gyroUp)
{ case Base6Directions.Direction.Up: gyroYawField.Add("Yaw"); gyroYawFactor.Add(1f); break;
case Base6Directions.Direction.Down: gyroYawField.Add("Yaw"); gyroYawFactor.Add(-1f); break;
case Base6Directions.Direction.Left: gyroYawField.Add("Pitch"); gyroYawFactor.Add(1f); break;
case Base6Directions.Direction.Right: gyroYawField.Add("Pitch"); gyroYawFactor.Add(-1f); break;
case Base6Directions.Direction.Forward: gyroYawField.Add("Roll"); gyroYawFactor.Add(-1f); break;
case Base6Directions.Direction.Backward: gyroYawField.Add("Roll"); gyroYawFactor.Add(1f); break;
}
switch (gyroLeft)
{ case Base6Directions.Direction.Up: gyroPitchField.Add("Yaw"); gyroPitchFactor.Add(1f); break;
case Base6Directions.Direction.Down: gyroPitchField.Add("Yaw"); gyroPitchFactor.Add(-1f); break;
case Base6Directions.Direction.Left: gyroPitchField.Add("Pitch"); gyroPitchFactor.Add(1f); break;
case Base6Directions.Direction.Right: gyroPitchField.Add("Pitch"); gyroPitchFactor.Add(-1f); break;
case Base6Directions.Direction.Forward: gyroPitchField.Add("Roll"); gyroPitchFactor.Add(-1f); break;
case Base6Directions.Direction.Backward: gyroPitchField.Add("Roll"); gyroPitchFactor.Add(1f); break;
}
switch (gyroForward)
{ case Base6Directions.Direction.Up: gyroRollField.Add("Yaw"); gyroRollFactor.Add(1f); break;
case Base6Directions.Direction.Down: gyroRollField.Add("Yaw"); gyroRollFactor.Add(-1f); break;
case Base6Directions.Direction.Left: gyroRollField.Add("Pitch"); gyroRollFactor.Add(1f); break;
case Base6Directions.Direction.Right: gyroRollField.Add("Pitch"); gyroRollFactor.Add(-1f); break;
case Base6Directions.Direction.Forward: gyroRollField.Add("Roll"); gyroRollFactor.Add(-1f); break;
case Base6Directions.Direction.Backward: gyroRollField.Add("Roll"); gyroRollFactor.Add(1f); break;
}
Gyroscopes[i].ApplyAction("OnOff_On");
}
}
// ----- 指令类方法 -----
// 持续搜索座标
private int SP_Now_i;
public MyDetectedEntityInfo ScanPoint(Vector3D Point){
MyDetectedEntityInfo FoundTarget = new MyDetectedEntityInfo();
List<IMyCameraBlock> RightAngleCameras = this.GetCanScanCameras(this.Cameras, Point);
if(SP_Now_i >= RightAngleCameras.Count){SP_Now_i=0;}
double ScanSpeed = (RightAngleCameras.Count*2000)/(Vector3D.Distance(Point, this.Position)*60);//每个循环可用于扫描的摄像头个数
if(ScanSpeed >= 1)//每循环可扫描多个
{
FoundTarget = RightAngleCameras[SP_Now_i].Raycast(Point);
SP_Now_i += 1;
if(SP_Now_i >= RightAngleCameras.Count){SP_Now_i=0;}
}
else
{
if(timetick%Math.Round(1/ScanSpeed,0)==0)
{
FoundTarget = RightAngleCameras[SP_Now_i].Raycast(Point);
SP_Now_i += 1;
}
}
return FoundTarget;
}
//瞬时多点扫描,返回第一个碰到的目标,可传入一个参考目标进行匹配
public MyDetectedEntityInfo PulseScanSingle(List<Vector3D> Points, long EntityId = 0){
MyDetectedEntityInfo FoundTarget = new MyDetectedEntityInfo();
int x = 0;//这样做是为了减少不必要的运算量
foreach(Vector3D p in Points){
for(int i = x; i < this.Cameras.Count; i ++){
if(this.Cameras[i].CanScan(p)){
FoundTarget = this.Cameras[i].Raycast(p);
if(!FoundTarget.IsEmpty()){
if(EntityId == 0){
return FoundTarget;
}
else if(FoundTarget.EntityId == EntityId){
return FoundTarget;
}
}
x = i;
break;
}
}
}
return FoundTarget;
}
// 瞬时多点扫描,返回所有碰到的目标(运算量较大)
public List<MyDetectedEntityInfo> PulseScanMultiple(List<Vector3D> Points){
List<MyDetectedEntityInfo> FoundTargets = new List<MyDetectedEntityInfo>();
int x = 0;//这样做是为了减少不必要的运算量
foreach(Vector3D p in Points){
for(int i = x; i < this.Cameras.Count; i ++){
if(this.Cameras[i].CanScan(p)){
MyDetectedEntityInfo FoundTarget = this.Cameras[i].Raycast(p);
if(!FoundTarget.IsEmpty()){
FoundTargets.Add(FoundTarget);
}
x = i;
break;
}
}
}
return FoundTargets;
}
//追踪目标
private int TT_Now_i;
public Vector3D TrackDeviationToTarget; //基于目标坐标系的偏移量,用来修正中心锁定的问题
public MyDetectedEntityInfo TrackTarget(Target Tgt){
MyDetectedEntityInfo FoundTarget = new MyDetectedEntityInfo();
Vector3D posmove = Vector3D.TransformNormal(this.TrackDeviationToTarget, Tgt.Orientation);
Vector3D lidarHitPoint = Tgt.Position + posmove + (timetick - Tgt.TimeStamp)*Tgt.Velocity/60; //这个碰撞点算法是最正确的
List<IMyCameraBlock> RightAngleCameras = GetCanScanCameras(this.Cameras, lidarHitPoint);//获取方向正确的摄像头数量
if(TT_Now_i >= RightAngleCameras.Count){TT_Now_i=0;}
//执行常规追踪
double ScanSpeed = (RightAngleCameras.Count*2000)/((Vector3D.Distance(lidarHitPoint, this.Position))*60);//每个循环可用于扫描的摄像头个数
if(ScanSpeed >= 1)
{
for(int i = 1; i < ScanSpeed; i ++){
FoundTarget = RightAngleCameras[TT_Now_i].Raycast(lidarHitPoint);
TT_Now_i += 1;
if(TT_Now_i >= RightAngleCameras.Count){TT_Now_i=0;}
if(!FoundTarget.IsEmpty() && FoundTarget.EntityId == Tgt.EntityId){
return FoundTarget;
}
}
}
else
{
//这里向上取整实际上是采用了更低一点的频率在扫描,有利于恢复储能
if(timetick%Math.Ceiling(1/ScanSpeed)==0)
{
FoundTarget = RightAngleCameras[TT_Now_i].Raycast(lidarHitPoint);
TT_Now_i += 1;
if(TT_Now_i >= RightAngleCameras.Count){TT_Now_i=0;}
if(!FoundTarget.IsEmpty() && FoundTarget.EntityId == Tgt.EntityId){
return FoundTarget;
}
//常规未找到,继续遍历摄像头进行搜索
if(FoundTarget.IsEmpty() || FoundTarget.EntityId != Tgt.EntityId){
for(int i = 0; i < RightAngleCameras.Count; i ++){
FoundTarget = RightAngleCameras[TT_Now_i].Raycast(lidarHitPoint);
TT_Now_i += 1;
if(TT_Now_i >= RightAngleCameras.Count){TT_Now_i=0;}
if(!FoundTarget.IsEmpty() && FoundTarget.EntityId == Tgt.EntityId){
return FoundTarget;
}
}
}
}
}
//遍历搜索也未找到,进行脉冲阵面扫描
if(FoundTarget.IsEmpty() || FoundTarget.EntityId != Tgt.EntityId){
if(ScanSpeed >= 1 || timetick%Math.Ceiling(1/ScanSpeed)==0){
int LostTick = timetick - Tgt.TimeStamp;
double S_Radius = Tgt.Diameter*1.5; //搜索半径为目标直径1.5倍
double S_Interval = Tgt.Diameter/5; //搜索间隙是目标直径的1/5
Vector3D CenterPoint = Tgt.Position + Tgt.Velocity*LostTick/60 + Vector3D.Normalize(Tgt.Position - this.Position)*Tgt.Diameter/2;
List<Vector3D> Points = new List<Vector3D>();
Points.Add(CenterPoint);
//这里计算出与飞船和目标连线垂直,且互相垂直的两个向量,用作x和y方向遍历
Vector3D Vertical_X = this.CaculateVerticalVector((CenterPoint - this.Position), CenterPoint);
Vector3D Vertical_Y = Vector3D.Normalize(Vector3D.Cross((CenterPoint - this.Position), Vertical_X));
for(double x = 0; x < S_Radius; x += S_Interval){
for(double y = 0; y < S_Radius; y += S_Interval){
Points.Add(CenterPoint + Vertical_X*x + Vertical_Y*y);
Points.Add(CenterPoint + Vertical_X*(-x) + Vertical_Y*y);
Points.Add(CenterPoint + Vertical_X*x + Vertical_Y*(-y));
Points.Add(CenterPoint + Vertical_X*(-x) + Vertical_Y*(-y));
}
}
FoundTarget = this.PulseScanSingle(Points, Tgt.EntityId);
if(!FoundTarget.IsEmpty() && FoundTarget.EntityId == Tgt.EntityId){
MatrixD TargetMainMatrix = FoundTarget.Orientation;
MatrixD TargetLookAtMatrix = MatrixD.CreateLookAt(new Vector3D(), TargetMainMatrix.Forward, TargetMainMatrix.Up);
Vector3D hitpoint = new Vector3D();
Vector3D.TryParse(FoundTarget.HitPosition.ToString(), out hitpoint);
hitpoint = hitpoint + Vector3D.Normalize(hitpoint - this.Position)*2;
this.TrackDeviationToTarget = Vector3D.TransformNormal(hitpoint - FoundTarget.Position, TargetLookAtMatrix);
return FoundTarget;
}
}
}
return FoundTarget;
}
// ----- 工具类方法 -----
//运动类方块初始化
public void MotionInit(){
this.SetThrustOverride("All",0);
this.SetGyroOverride(false);
}
public void UpdatePhysical(int dis_count = 1){
this.Diameter = (this.Cockpit.CubeGrid.Max - this.Cockpit.CubeGrid.Min).Length() * this.Cockpit.CubeGrid.GridSize;
this.Acceleration = ((this.Cockpit.GetPosition() - this.Position) * 60 - this.Velocity) * 60;
this.Velocity = (this.Cockpit.GetPosition() - this.Position) * 60;
this.Position = this.Cockpit.GetPosition();
Ship.timetick += dis_count;
}
// ----- 运动控制算法 -----
// PID瞄准目标函数
private List<Vector3D> Aim_PID_Data = new List<Vector3D>();
public bool AimAtPosition(Vector3D TargetPos)
{
MatrixD refLookAtMatrix = MatrixD.CreateLookAt(new Vector3D(), this.Cockpit.WorldMatrix.Forward, this.Cockpit.WorldMatrix.Up);
Vector3D PositionToMe = Vector3D.Normalize(Vector3D.TransformNormal(TargetPos - this.Position, refLookAtMatrix));
//储存采样点
if(Aim_PID_Data.Count < AimPID_T){
for(int i = 0; i < AimPID_T; i ++){
Aim_PID_Data.Add(new Vector3D());
}
}
else{Aim_PID_Data.Remove(Aim_PID_Data[0]); Aim_PID_Data.Add(PositionToMe);}
//获得采样点积分
double X_I = 0;
double Y_I = 0;
foreach(Vector3D datapoint in Aim_PID_Data){
X_I += datapoint.X;
Y_I += datapoint.Y;
}
//计算输出
double YawValue = AimPID_P*(PositionToMe.X + (1/AimPID_I)*X_I + AimPID_D*(Aim_PID_Data[AimPID_T-1].X - Aim_PID_Data[0].X)/AimPID_T) * 60;
double PitchValue = AimPID_P*(PositionToMe.Y + (1/AimPID_I)*Y_I + AimPID_D*(Aim_PID_Data[AimPID_T-1].Y - Aim_PID_Data[0].Y)/AimPID_T) * 60;
this.SetGyroValue(YawValue, PitchValue, 0);
this.SetGyroOverride(true);
// 计算当前与预期瞄准点的瞄准夹角
Vector3D V_A = TargetPos - this.Position;
Vector3D V_B = this.Cockpit.WorldMatrix.Forward;
double Angle = Math.Acos(Vector3D.Dot(V_A,V_B)/(V_A.Length() * V_B.Length())) * 180 / Math.PI;
if(Angle <= AimRatio){return true;}
else{return false;}
}
//坐标点导航函数
//支持传入一个参考速度来跟踪目标进行速度匹配
//依赖SingleDirectionThrustControl()方法来执行对xyz三轴的独立运算,运算考虑了推进器是否可以工作,但不考虑供电带来的效率问题。
//本方法的结果路径是一个加速-减速-停止路径,通常不会错过目标,在此前提下本方法时间最优,在减速阶段处于对向推进器频繁满载震荡状态,在物理结果上是匀减速运动。
public bool NavigationTo(Vector3D Pos, Vector3D TargetVelocity = new Vector3D())
{
double ShipMass = this.Cockpit.CalculateShipMass().PhysicalMass;
//这个ThrustsPowers经过计算后,分别代表前后左右上下6个方向的理论最大加速度
double[] ThrustsPowers = new double[6];
for(int i = 0; i < this.Thrusts.Count; i ++){
if(this.Thrusts[i].IsFunctional){
switch(this.ThrustField[i]){
case("Backward"): ThrustsPowers[0] += this.Thrusts[i].MaxEffectiveThrust; break;
case("Forward"): ThrustsPowers[1] += this.Thrusts[i].MaxEffectiveThrust; break;
case("Right"): ThrustsPowers[2] += this.Thrusts[i].MaxEffectiveThrust; break;
case("Left"): ThrustsPowers[3] += this.Thrusts[i].MaxEffectiveThrust; break;
case("Down"): ThrustsPowers[4] += this.Thrusts[i].MaxEffectiveThrust; break;
case("Up"): ThrustsPowers[5] += this.Thrusts[i].MaxEffectiveThrust; break;
}
}
}
for(int i = 0; i < ThrustsPowers.Length; i ++){
ThrustsPowers[i] /= ShipMass;
}
MatrixD refLookAtMatrix = MatrixD.CreateLookAt(new Vector3D(), this.Cockpit.WorldMatrix.Forward, this.Cockpit.WorldMatrix.Up);
//这里的PosToMe表示目标坐标基于自己坐标系的座标,x左-右+,y下-上+,z前-后+,MeVelocityToMe使用相同的坐标系规则,表示自己的速度基于自己坐标系
Vector3D PosToMe = Vector3D.TransformNormal(Pos - this.Position, refLookAtMatrix);
Vector3D MeVelocityToMe = Vector3D.TransformNormal(this.Velocity, refLookAtMatrix);
this.SingleDirectionThrustControl(PosToMe.Z, MeVelocityToMe.Z, ThrustsPowers[0], ThrustsPowers[1], "Backward", "Forward", 0.5);
this.SingleDirectionThrustControl(PosToMe.X, MeVelocityToMe.X, ThrustsPowers[2], ThrustsPowers[3], "Right", "Left", 0.5);
this.SingleDirectionThrustControl(PosToMe.Y, MeVelocityToMe.Y, ThrustsPowers[5], ThrustsPowers[4], "Up", "Down", 0.5);
if(TargetVelocity.Length() != 0){
Vector3D TargetVelocityToMe = Vector3D.TransformNormal(TargetVelocity - this.Velocity, refLookAtMatrix);
if(TargetVelocityToMe.X > 0){SetThrustOverride("Left", 100);}else if(TargetVelocityToMe.X < 0){SetThrustOverride("Right", 100);}
if(TargetVelocityToMe.Y > 0){SetThrustOverride("Down", 100);}else if(TargetVelocityToMe.Y < 0){SetThrustOverride("Up", 100);}
if(TargetVelocityToMe.Z > 0){SetThrustOverride("Forward", 100);}else if(TargetVelocityToMe.X < 0){SetThrustOverride("Backward", 100);}
}
if(PosToMe.Length() <= 1){return true;}
return false;
}
//单向推进器导航点控制函数(用于辅助NavigationTo()方法)
//传入基于自己坐标系的目标单向方向,自己的单向速度,正向加速度,反向加速度,正向推进器方向名,反向推进器方向名,导航精度
public void SingleDirectionThrustControl(double PosToMe, double VelocityToMe, double PostiveMaxAcceleration, double NagtiveMaxAcceleration, string PostiveThrustDirection, string NagtiveThrustDirection, double StopRatio){
if(PosToMe < -StopRatio){
double StopTime = -VelocityToMe/NagtiveMaxAcceleration;
if(StopTime < 0){
this.SetThrustOverride(PostiveThrustDirection, 100);
this.SetThrustOverride(NagtiveThrustDirection, 0);
}
else{
double StopDistance = -VelocityToMe*StopTime + 0.5*NagtiveMaxAcceleration*StopTime*StopTime;
if(Math.Abs(PosToMe) > StopDistance){
this.SetThrustOverride(PostiveThrustDirection, 100);
this.SetThrustOverride(NagtiveThrustDirection, 0);
}
else{
this.SetThrustOverride(PostiveThrustDirection, 0);
this.SetThrustOverride(NagtiveThrustDirection, 100);
}
}
}
else if(PosToMe > StopRatio){
double StopTime = VelocityToMe/NagtiveMaxAcceleration;
if(StopTime < 0){
//此时目标在后,运动速度是向前的
this.SetThrustOverride(PostiveThrustDirection, 0);
this.SetThrustOverride(NagtiveThrustDirection, 100);
}
else{
double StopDistance = VelocityToMe*StopTime + 0.5*NagtiveMaxAcceleration*StopTime*StopTime;
if(Math.Abs(PosToMe) > StopDistance){
//实际距离大于刹车距离,执行推进
this.SetThrustOverride(PostiveThrustDirection, 0);
this.SetThrustOverride(NagtiveThrustDirection, 100);
}
else{
//实际距离小于刹车距离,执行刹车
this.SetThrustOverride(PostiveThrustDirection, 100);
this.SetThrustOverride(NagtiveThrustDirection, 0);
}
}
}
else{
this.SetThrustOverride(PostiveThrustDirection, 0);
this.SetThrustOverride(NagtiveThrustDirection, 0);
}
}
// ----- 基础控制类方法 -----
public void TurnBlocksOnOff(List<IMyTerminalBlock> B, bool o)
{
foreach(var b in B){
b.ApplyAction(o?"OnOff_On":"OnOff_Off");
}
}
public void TurnBlocksOnOff(List<IMyGyro> B, bool o){
List<IMyTerminalBlock> BList = new List<IMyTerminalBlock>();
foreach(var b in B){
BList.Add(b as IMyTerminalBlock);
}
TurnBlocksOnOff(BList,o);
}
public void TurnBlocksOnOff(List<IMyThrust> B, bool o){
List<IMyTerminalBlock> BList = new List<IMyTerminalBlock>();
foreach(var b in B){
BList.Add(b as IMyTerminalBlock);
}
TurnBlocksOnOff(BList,o);
}
public void TurnBlocksOnOff(List<IMyLargeTurretBase> B, bool o){
List<IMyTerminalBlock> BList = new List<IMyTerminalBlock>();
foreach(var b in B){
BList.Add(b as IMyTerminalBlock);
}
TurnBlocksOnOff(BList,o);
}
public void SetThrustOverride(string Direction, double Value)
{
if(Value > 100){Value = 100;}
if(Value < 0){Value = 0;}
for(int i = 0; i < this.Thrusts.Count; i ++){
if(Direction == "All"){this.Thrusts[i].ThrustOverridePercentage = (float)Value;}
else{if(this.ThrustField[i] == Direction){this.Thrusts[i].ThrustOverridePercentage = (float)Value;}}
}
}
public void SetGyroOverride(bool bOverride)
{
foreach(IMyGyro g in this.Gyroscopes){g.GyroOverride = bOverride;}
}
public void SetGyroValue(double Y, double P, double R)
{
for (int i = 0; i < this.Gyroscopes.Count; i++){
this.Gyroscopes[i].SetValue(gyroYawField[i], (float)Y * gyroYawFactor[i]);
this.Gyroscopes[i].SetValue(gyroPitchField[i], (float)P * gyroPitchFactor[i]);
this.Gyroscopes[i].SetValue(gyroRollField[i], (float)R * gyroRollFactor[i]);
}
}
public void SetGyroValue(string Field, double Value)
{
switch(Field){
case("Yaw"):
for (int i = 0; i < this.Gyroscopes.Count; i++){
this.Gyroscopes[i].SetValue(gyroYawField[i], (float)Value * gyroYawFactor[i]);
}
break;
case("Pitch"):
for (int i = 0; i < this.Gyroscopes.Count; i++){
this.Gyroscopes[i].SetValue(gyroPitchField[i], (float)Value * gyroPitchFactor[i]);
}
break;
case("Roll"):
for (int i = 0; i < this.Gyroscopes.Count; i++){
this.Gyroscopes[i].SetValue(gyroRollField[i], (float)Value * gyroRollFactor[i]);
}
break;
}
}
public void WeaponsShoot()
{
this.GatlingGuns.ForEach(delegate(IMySmallGatlingGun g){g.ApplyAction("ShootOnce");});
this.RocketLaunchers.ForEach(delegate(IMySmallMissileLauncher g){g.ApplyAction("ShootOnce");});
}
// ---- 运算类方法 ----
public class Target
{
public string Name;
public long EntityId;
public double Diameter;
public int TimeStamp;
public MyDetectedEntityType Type;
public Vector3D Position;
public Vector3D Velocity;
public Vector3D Acceleration;
public Vector3D HitPosition;
public MatrixD Orientation;
public Vector3D AccurateLockPositionToTarget;
public Target(){
this.EntityId = 0;
this.TimeStamp = 0;
}
public Target(MyDetectedEntityInfo thisEntity){
this.EntityId = thisEntity.EntityId;
this.Name = thisEntity.Name;
this.Diameter = Vector3D.Distance(thisEntity.BoundingBox.Max, thisEntity.BoundingBox.Min)/2;
Vector3D.TryParse(thisEntity.Position.ToString(), out this.Position);
Vector3D.TryParse(thisEntity.Velocity.ToString(), out this.Velocity);
Vector3D.TryParse(thisEntity.HitPosition.ToString(), out this.HitPosition);
this.Acceleration = new Vector3D();
this.Orientation = thisEntity.Orientation;
this.TimeStamp = timetick;
}
public void UpdatePhysical(MyDetectedEntityInfo NewInfo){
this.Diameter = Vector3D.Distance(NewInfo.BoundingBox.Max, NewInfo.BoundingBox.Min)/2;
Vector3D.TryParse(NewInfo.Position.ToString(), out this.Position);
Vector3D.TryParse(NewInfo.HitPosition.ToString(), out this.HitPosition);
Vector3D velocity = new Vector3D();
Vector3D.TryParse(NewInfo.Velocity.ToString(), out velocity);
this.Acceleration = (velocity - this.Velocity)*60/(timetick - this.TimeStamp > 0 ? timetick - this.TimeStamp : 1);
this.Velocity = velocity;
this.Orientation = NewInfo.Orientation;
this.TimeStamp = timetick;
}
}
// -- 计算可扫描的摄像头 --
public List<IMyCameraBlock> GetCanScanCameras(List<IMyCameraBlock> Cams, Vector3D Point)
{
List<IMyCameraBlock> res = new List<IMyCameraBlock>();
foreach(IMyCameraBlock cm in Cams){
if(cm.IsFunctional && cm.CanScan(Point)){
res.Add(cm);
}
}
return res;
}
// -- 计算某向量的垂直向量 --
// 传入一个向量,和一个点,返回沿这个点出发与传入向量垂直的归一化向量
public Vector3D CaculateVerticalVector(Vector3D Vector, Vector3D Point)
{
double x = 1;
double y = 1;
double z = (Point.X*Vector.X + Point.Y*Vector.Y + Point.Z*Vector.Z)/Vector.Z;
return Vector3D.Normalize(new Vector3D(x,y,z));
}
}
~~~
- 序言
- 写在前面的话
- 太空工程师
- 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