Files
aibis-dream/Assets/Scripts/MiniGame/ShaftGraph.cs
T
2024-08-19 01:28:50 +08:00

217 lines
6.1 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace AibisDream
{
public class ShaftGraph
{
// 顶点数量
int vertexSize;
// 顶点Map
Shaft[] vertexArray;
// 邻接表
float[,] edgeTable;
// 遍历记录
bool[] vertexRecordArray;
// 动力轴序号
int rootIdx;
public ShaftGraph(Shaft[] shafts)
{
// 为轴赋值
vertexSize = shafts.Length;
vertexRecordArray = new bool[vertexSize];
vertexArray = shafts;
foreach (var shaft in vertexArray)
{
shaft.InitShaft();
}
// 寻找唯一的驱动轴序号
rootIdx = FindDriverIdx();
// 生成边邻接表
GeneEdgeTable();
UpdateSpeed();
}
private int FindDriverIdx()
{
for (int i = 0; i < vertexSize; i++)
{
if (vertexArray[i].shaftType == ShaftType.Driver)
{
return i;
}
}
return -1;
}
/// <summary>
/// 生成边邻接表
/// </summary>
private void GeneEdgeTable()
{
edgeTable = new float[vertexSize, vertexSize];
for (int i = 0; i < vertexSize - 1; i++)
{
for (int j = i + 1; j < vertexSize; j++)
{
// 判断两个Shaft是否临接
if (Shaft.IsShaftConnected(vertexArray[i], vertexArray[j]))
{
edgeTable[i, j] = Shaft.CalcAngularVelocityRatio(vertexArray[i], vertexArray[j]);
edgeTable[j, i] = Shaft.CalcAngularVelocityRatio(vertexArray[j], vertexArray[i]);
}
else
{
edgeTable[i, j] = 0;
edgeTable[j, i] = 0;
}
}
}
}
/// <summary>
/// 某个轴上齿轮发生变化时更新临接关系
/// </summary>
/// <param name="instanceID">轴ID</param>
public void ChangeVertex(int instanceID)
{
// 找到对应idx
int idx = TranInstanceIDToIdx(instanceID);
// 更新该节点对应的邻接表
for (int i = 0; i < vertexSize; i++)
{
// 遇到自身跳过
if (i == idx)
{
continue;
}
// 判断两个Shaft是否临接
if (Shaft.IsShaftConnected(vertexArray[idx], vertexArray[i]))
{
edgeTable[idx, i] = Shaft.CalcAngularVelocityRatio(vertexArray[idx], vertexArray[i]);
edgeTable[i, idx] = Shaft.CalcAngularVelocityRatio(vertexArray[i], vertexArray[idx]);
}
else
{
edgeTable[idx, i] = 0;
edgeTable[i, idx] = 0;
}
}
UpdateSpeed();
}
private int TranInstanceIDToIdx(int instanceID)
{
// 查找对应的序号
int idx = -1;
for (int i = 0; i < vertexSize; i++)
{
if (instanceID == vertexArray[i].GetInstanceID())
{
idx = i;
break;
}
}
return idx;
}
/// <summary>
/// 更新当前所有轴的速度
/// </summary>
public void UpdateSpeed()
{
// 清除遍历记录
Array.Clear(vertexRecordArray, 0, vertexSize);
// 从驱动轴开始计算速度
UpdateShaftSpeedByIdx(rootIdx);
}
private void UpdateShaftSpeedByIdx(int idx)
{
// 已知当前齿轮速度
float currentSpeed = vertexArray[idx].Speed;
for (int i = 0; i < vertexSize; i++)
{
// 遍历临接齿轮
if (i != idx && edgeTable[idx, i] > 0)
{
// 已遍历过就跳过
if (vertexRecordArray[idx])
{
continue;
}
Debug.Log(idx);
// 更新速度
vertexArray[i].Speed = currentSpeed * edgeTable[idx, i];
// 继续寻找相邻齿轮
//UpdateShaftSpeedByIdx(i);
// 已遍历的轴加上标记
vertexRecordArray[i] = true;
}
}
}
/// <summary>
/// 查询可吸附的轴
/// </summary>
/// <param name="pos">齿轮位置</param>
/// <param name="gearRadius">齿轮半径</param>
/// <returns>吸附轴</returns>
public Shaft QuerySnapShaft(Vector3 pos, float gearRadius)
{
if (vertexArray == null || vertexArray.Length == 0)
{
return null;
}
// 查询距离最近的,可吸附的Shaft
Shaft closestShaft = null;
float minDistence = -1;
foreach (var vertex in vertexArray)
{
if (vertex.shaftType == ShaftType.Pluggable && !vertex.HasChildGear())
{
float tempDis = Vector3.Distance(vertex.transform.position, pos);
if (minDistence < 0 || tempDis < minDistence)
{
closestShaft = vertex;
minDistence = tempDis;
}
}
}
// 没查到就返回空
if (closestShaft == null) { return null; }
// 查到了就返回是否吸附
if (minDistence < gearRadius)
{
return closestShaft;
}
else
{
return null;
}
}
}
}