using asap.core; using cfg; using DG.Tweening; using GameCore; using System.Collections.Generic; using System.Threading.Tasks; using TMPro; using UnityEngine; using UnityEngine.UI; public class AquariumRandomMapPanel : MonoBehaviour { AquariumManager AM; RectTransform Content; GameObject img_map; int allCount = 5; float height; public float StartDuration = 0.35f; public float AccNum = 3; public float[] SelectedMapNumRandUp = new[] { 2f, 5f }; public float[] SelectedMapNumRandDown = new[] { 4f, 7f }; int MapNum = 2; float BackRatio = 2f; IUIService uIService; float LoopDuration = 0.125f; GameObject result; TMP_Text text_map; TMP_Text text_level; AquariumDetectEgg[] aquariumDetectEggs; Transform eggRoot; Tables _tables; Transform door; private void Awake() { _tables = GContext.container.Resolve(); uIService = GContext.container.Resolve(); AM = GContext.container.Resolve(); Content = transform.Find("Viewport/Content").GetComponent(); img_map = transform.Find("Viewport/Content/Item").gameObject; height = img_map.GetComponent().rect.height; img_map.SetActive(false); result = transform.Find("result").gameObject; text_map = transform.Find("result/text_map").GetComponent(); text_level = transform.Find("result/fishcard/text_level").GetComponent(); eggRoot = transform.Find("eggRoot"); aquariumDetectEggs = eggRoot.GetComponentsInChildren(); //eggRoot.gameObject.SetActive(false); door = transform.Find("door"); } //private void Start() //{ // result.SetActive(false); //} bool isUP; public void SetMap() { isUP = Random.value < 0.5f; float t = Random.Range(0f, 1f); if (isUP) { BackRatio = SelectedMapNumRandUp[0] + (SelectedMapNumRandUp[1] - SelectedMapNumRandUp[0]) * t; } else { BackRatio = SelectedMapNumRandDown[0] + (SelectedMapNumRandDown[1] - SelectedMapNumRandDown[0]) * t; } MapNum = Mathf.CeilToInt(BackRatio); PlayerData playerData = GContext.container.Resolve(); AM.GetRandmMap(); var lastMapID = playerData.lastMapId; List mapDatas = _tables.TbMapData.DataList; List indexs = new List { 0,1 }; for (int i = 2; i < mapDatas.Count; i++) { if (mapDatas[i].ID <= lastMapID) { indexs.Insert(Random.Range(0, indexs.Count), i); } else { break; } } while (indexs.Count < allCount + MapNum) { indexs.AddRange(indexs); } List newIDs = indexs; for (int i = 0; i < allCount + MapNum; i++) { SetMapBg(mapDatas[newIDs[i]].Bg); } var mapData = _tables.TbMapData.DataMap[AM.MapId]; SetMapBg(mapData.Bg); SetMapBg(mapDatas[newIDs[0]].Bg); text_map.text = LocalizationMgr.GetText(mapData.Name_l10n_key); string levelLV = LocalizationMgr.GetText("UI_FishingMapPanel_101006"); int fishCardLevel = GContext.container.Resolve().GetFishLevelByMap(AM.MapId); text_level.text = levelLV + fishCardLevel.ToString(); } public async Task PlayMap() { var sequence = DOTween.Sequence(); //sequence.Append(door.DOLocalMoveX(900, 0.5f).SetEase(Ease.Linear)); float subHeight = height * AccNum; float time = 2 * AccNum / (1 / StartDuration + 1 / LoopDuration); sequence.Append(Content.DOAnchorPosY(subHeight, time).SetEase(Ease.InQuad)); float timer1 = LoopDuration * (allCount - AccNum); sequence.Append(Content.DOAnchorPosY(allCount * height, timer1).SetLoops(2, LoopType.Restart).SetEase(Ease.Linear)); //跑马灯动画 float timer2 = 0; float ratio = MapNum - BackRatio; if (ratio > 0.01) { timer2 = LoopDuration * ratio; sequence.Append(Content.DOAnchorPosY((allCount + ratio) * height, timer2).SetEase(Ease.Linear)); } sequence.Play(); await Awaiters.Seconds(time + timer1 * 2 + timer2); await SharkAni(); } void SetMapBg(string bg) { GameObject go = Instantiate(img_map, Content); Image image = go.transform.GetChild(0).GetComponent(); go.SetActive(true); uIService.SetImageSprite(image, bg); } public void InitEgg() { //开始随机蛋蛋 for (int i = 0; i < aquariumDetectEggs.Length; i++) { if (i < AM.Slot) { AquariumEgg aquariumEgg = _tables.TbAquariumEgg.GetOrDefault(AM.data.slotDatas[i].eggId); aquariumDetectEggs[i].SetIcon(AM.eggNames, aquariumEgg.Icon, i); } else { aquariumDetectEggs[i].gameObject.SetActive(false); } } } public void PlayEgg() { //开始随机蛋蛋 for (int i = 0; i < aquariumDetectEggs.Length; i++) { if (i < AM.Slot) { //AquariumEgg aquariumEgg = _tables.TbAquariumEgg.GetOrDefault(AM.data.slotDatas[i].eggId); aquariumDetectEggs[i].Play(); } } } public void HideMap() { Content.gameObject.SetActive(false); } [Header("物理参数")] [SerializeField, Min(1), Tooltip("弹簧刚度 k (N·m/rad)")] private float springStiffness = 100f; [SerializeField, Min(1), Tooltip("阻尼系数 (N·m·s/rad)")] private float dampingRatio = 15f; [SerializeField, Min(0.1f), Tooltip("动摩擦 (N·m) T_k")] private float dynamicFriction = 3f; [SerializeField, Min(0.1f), Tooltip("转动惯量 (kg·m²)")] private float momentOfInertia = 1.0f; //匀速进入减速的角度,是相对于第一次减速阶段稳定角的角度,正数(减)在奖励顺时针方向,负数(加)在目标点逆时针方向 private float valueOffset2 = 200f; [Header("减速阶段")] [SerializeField, Tooltip("停留左侧时,匀速进入减速的角度,是相对于第一次减速阶段稳定角的角度")] private float[] valueOffsetToTmpStableUp = new float[2] { 0.2f, 0.4f }; [SerializeField, Tooltip("停留右侧时,匀速进入减速的角度")] private float[] valueOffsetToTmpStableDown = new float[2] { -0.2f, -0.4f }; [Header("停止条件")] [SerializeField, Min(10f), Tooltip("第一阶段减速的速度停止条件")] private float velocityStop = 30f; [SerializeField, Min(10f), Tooltip("第二阶段减速的速度停止条件,!!!必须小于 velocityStop !!! ")] private float velocityStopFinal = 10f; [SerializeField, Tooltip("第一阶段减速的角度停止条件")] private float valueStopRatio = 5f; [SerializeField, Tooltip("第二阶段减速的角度停止条件")] private float valueStopFinalRatio = 0.1f; private float currentValue = 0f; private float currentVelocity = 0f; private float targetValue = 0f; bool revertTargetValue = false; bool effectTask; private void DecelerationgAni(float deltaTime) { float valueError = currentValue - targetValue; int direction = valueError > 0 ? 1 : -1; float springTorque = springStiffness * Mathf.Abs(valueError) * direction; float dampingTorque = -dampingRatio * currentVelocity; float frictionTorque = CalculateFrictionTorque(); float totalTorque = springTorque + dampingTorque + frictionTorque; float angularAcceleration = totalTorque / momentOfInertia; currentVelocity += angularAcceleration * deltaTime; CheckStopCondition(); } private float CalculateFrictionTorque() { return -dynamicFriction * Mathf.Sign(currentVelocity); } private void CheckStopCondition() { float valueError = Mathf.Abs(currentValue - targetValue); bool inPosition = valueError < Mathf.Abs(valueStopRatio); bool slowEnough = Mathf.Abs(currentVelocity) < velocityStop; bool inPositionFinal = valueError < Mathf.Abs(valueStopFinalRatio); bool slowEnoughFinal = Mathf.Abs(currentVelocity) < velocityStopFinal; if (inPosition && slowEnough && !revertTargetValue) { targetValue -= valueOffset2; revertTargetValue = true; } else if (inPositionFinal && slowEnoughFinal) { currentVelocity = 0f; currentValue = targetValue; revertTargetValue = false; effectTask = false; } } public async Task SharkAni() { float tmpValue2; if (isUP) { tmpValue2 = UnityEngine.Random.Range(valueOffsetToTmpStableUp[0], valueOffsetToTmpStableUp[1]); } else { tmpValue2 = UnityEngine.Random.Range(valueOffsetToTmpStableDown[0], valueOffsetToTmpStableDown[1]); } valueOffset2 = tmpValue2 * height; revertTargetValue = false; targetValue = (allCount + MapNum) * height; targetValue += valueOffset2; currentValue = allCount * height; currentVelocity = -height / LoopDuration; effectTask = true; while (effectTask) { DecelerationgAni(Time.deltaTime); currentValue -= currentVelocity * Time.deltaTime; Content.anchoredPosition = new Vector2(0, currentValue); await Awaiters.NextFrame; } } }