Files
aibis-dream/Assets/Scripts/MiniGame/Engine/EngineSystem.cs
T
2024-12-30 23:31:37 +08:00

320 lines
9.1 KiB
C#

using System;
using System.Linq;
using AibisDream.FixSystem;
using AibisDream.Framework;
using AibisDream.Kit;
using AibisDream.Utility;
using DG.Tweening;
using UnityEngine;
using UnityEngine.Serialization;
namespace AibisDream
{
public class EngineSystem : SystemHasData
{
public static string DataPath = Application.streamingAssetsPath + "/LevelData/EngineSystem/";
private SpriteRenderer _cover;
private AirGate _airGate;
[Header("系统配置")] [SerializeField] public EngineConfig config;
[Header("系统数据")] [SerializeField] private EngineData engineData;
[FormerlySerializedAs("盖板移动时间")] [SerializeField]
private float coverMoveDuration = 5f;
[FormerlySerializedAs("盖板移动距离")] [SerializeField]
private float coverMoveDistance = 2.8f;
private bool IsValid => engineData.isValid.Value;
public event Action<EngineData> UpdateDashboard;
private void Awake()
{
FixSystemCenter.SystemDic.Register(this);
_cover = transform.Find("Cover").GetComponent<SpriteRenderer>();
_airGate = transform.Find("Air Gate").GetComponent<AirGate>();
}
private void Start()
{
OnLoad();
gameObject.SetActive(false);
}
private void OnLoad()
{
engineData = new EngineData(config.invalidTime);
// 初始档位置为2
_airGate.MoveToLevel(2);
DialogController.Instance?.SetVariable("$curAirLevel", 2);
engineData.UpdateAirLevel(1, config.maxLevel); // 内部档位从0计数,1就是2
}
private void Update()
{
// 更新部分按时间自然计算的指标
DataAutoChange();
// 更新看板
UpdateDashboard?.Invoke(engineData);
}
private void DataAutoChange()
{
// 自然减速
engineData.OilChange(-config.oilDownRatio);
engineData.CalcAir(config.airMaxRatio, config.airMinRatio, config.baseAirMax);
// 推算速度
engineData.CalcSpeed(config.acceleratedSpeed, config.resistance);
// 判断是否成功
if (engineData.CheckSuccess(config.targetSpeed))
{
DialogController.Instance?.StartDialogNode("EngineSuccess");
}
}
/// <summary>
/// 加速过程
/// </summary>
public void AddOil()
{
if (IsValid)
{
engineData.OilChange(config.oilUpRatio);
}
// 失效期无法加油门
}
/// <summary>
/// 更新引擎气门变化
/// </summary>
/// <param name="curLevel">当前气门等级</param>
public void UpdateAirLevel(int curLevel)
{
engineData.UpdateAirLevel(curLevel, config.maxLevel);
DialogController.Instance?.SetVariable("$curAirLevel", curLevel + 1);
DialogController.Instance?.StartDialogNode("调整进气档位");
}
/// <summary>
/// 打开盖板
/// </summary>
/// <returns>动画序列</returns>
public Tween OpenCover()
{
AudioManager.PlayLoop2Audio("amb_shitou_engine");
var sq = DOTween.Sequence();
// 盖板上移
var moveDis = new Vector3(0, coverMoveDistance, 0);
sq.Join(_cover.transform.DOBlendableMoveBy(moveDis, coverMoveDuration));
// 盖板淡出
sq.Join(_cover.DOFade(0, coverMoveDuration));
// 为引擎系统解锁
sq.OnComplete(Unlock);
return sq;
}
/// <summary>
/// 关闭盖板
/// </summary>
/// <returns>动画序列</returns>
public Tween CloseCover()
{
AudioManager.PauseLoop2Audio();
var sq = DOTween.Sequence();
sq.Join(_cover.DOFade(1, coverMoveDuration));
var moveDis = new Vector3(0, -coverMoveDistance, 0);
sq.Join(_cover.transform.DOBlendableMoveBy(moveDis, coverMoveDuration));
// 锁定引擎系统
sq.OnComplete(Lock);
return sq;
}
public void Lock()
{
// 禁止油门和气门
}
public void Unlock()
{
// 开启油门和气门
}
#region 数据加载与保存
private string[] _keyOptions;
public override string CurDataKey { get; set; }
public override string[] GetDataKeyOptions()
{
return _keyOptions ??= ConfigUtil.Instance.GetFileNames(DataPath);
}
public override void Load()
{
if (string.IsNullOrEmpty(CurDataKey))
{
Debug.Log("配置项名称为空");
return;
}
if (!ConfigUtil.Instance.TryLoadConfig<EngineConfig>(DataPath + CurDataKey,
out var data))
{
Debug.Log("没有找到配置项");
return;
}
config = data;
// 重置Data
OnLoad();
}
public override void Save()
{
if (string.IsNullOrEmpty(CurDataKey))
{
Debug.Log("名称不为空");
return;
}
ConfigUtil.Instance.SaveConfig(config, DataPath + CurDataKey);
if (!_keyOptions.Contains(CurDataKey))
{
// 重新读取key
_keyOptions = ConfigUtil.Instance.GetFileNames(DataPath);
}
}
#endregion
}
[Serializable]
public struct EngineConfig
{
public float oilDownRatio;
public float oilUpRatio;
public float acceleratedSpeed;
public float resistance;
public float airMaxRatio;
public float airMinRatio;
public float baseAirMax;
public int maxLevel;
public float targetSpeed;
public float invalidTime;
}
[Serializable]
public struct EngineData
{
private const float SuccessDuration = 1.5f;
public float curSpeed;
public float curOil;
public float curAir;
public float curAirMin;
public float curAirMax;
public int curAirLevel;
public AutoFlipBool isValid;
public bool inAirRange;
public float reachTargetTime;
public bool isSuccess;
public EngineData(float flipDelayTime)
{
isValid = new AutoFlipBool(flipDelayTime, true);
curSpeed = 0;
curOil = 0;
curAir = 0;
curAirMin = 0;
curAirMax = 0;
curAirLevel = 0;
inAirRange = false;
reachTargetTime = 0;
isSuccess = false;
}
public void OilChange(float oilChangeRatio)
{
curOil = CommonUtil.Limit(curOil + oilChangeRatio * Time.deltaTime, 1f, 0f);
}
public void CalcSpeed(float acceleratedSpeed, float resistance)
{
var addNum = inAirRange && isValid.Value
? (curOil * acceleratedSpeed - curSpeed * resistance) * Time.deltaTime
: -curSpeed * resistance * Time.deltaTime;
curSpeed = CommonUtil.Limit(curSpeed + addNum, 1f, 0f);
}
public void CalcAir(float airMaxRatio, float airMinRatio, float baseAirMax)
{
curAirMax = CommonUtil.Limit(curSpeed * (curAirLevel + 1) * airMaxRatio + baseAirMax, 1f, 0f);
curAirMin = CommonUtil.Limit(curSpeed * (curAirLevel + 1) * airMinRatio, 0.8f, 0f);
curAir = curOil;
// 如果离开范围且当前在系统有效期,就进入一段失效期
var curInAirRange = curAir <= curAirMax && curAir >= curAirMin;
if (inAirRange && !curInAirRange && !isSuccess)
{
// 出界的话
if (curAir > curAirMax) DialogController.Instance?.StartDialogNode("引擎过速");
if (curAir < curAirMin) DialogController.Instance?.StartDialogNode("引擎掉速");
isValid.Value = false;
}
inAirRange = curInAirRange;
}
public void UpdateAirLevel(int level, int maxLevel)
{
curAirLevel = level;
if (curAirLevel > maxLevel)
{
curAirLevel = maxLevel - 1;
}
if (curAirLevel < 0)
{
curAirLevel = 0;
}
}
public bool CheckSuccess(float targetSpeed)
{
// 已经成功就不用校验了
if (isSuccess) return false;
if (curSpeed >= targetSpeed)
{
reachTargetTime += Time.deltaTime;
}
else
{
reachTargetTime = 0;
}
// 如果速度达标时间足够就判断成功
if (!(reachTargetTime >= SuccessDuration)) return false;
isSuccess = true;
return true;
}
}
}