Files
ft/Client/Assets/Scripts/UI/AdWheel/AdWheelRewardComponent.cs
2026-06-29 21:18:33 +08:00

211 lines
7.6 KiB
C#

using asap.core;
using Assets.Scripts.UI.AnimationSimulator;
using cfg;
using DG.Tweening;
using Game;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UI.Wheel;
using UnityEngine;
namespace Assets.Scripts.UI.AdWheel
{
public class AdWheelRewardComponent : AbstractWheelRewardComponent
{
#region ui
private GameObject fx_spin;
private GameObject fx_arrow_spin;
private Animation lightAni;
private AnimationState wheelClipLoop;
private Transform zhizhenTrans;
private Dictionary<string, GameObject> _fxNameObjs = new Dictionary<string, GameObject>();
#endregion
private float lastValue;
private int currentSegment = 0;
private int lastSegment = 0;
private Tweener _tweener;
protected override string StartSound => "audio_ui_bonuswheel_arrow_spin_start";
protected override string LoopedSound => "audio_ui_bonuswheel_arrow_spin_loop";
protected override string EndSound => "audio_ui_bonuswheel_arrow_spin_end";
protected override void Awake()
{
base.Awake();
fx_spin = this.gameObject.FindChildGameObject("fx_ui_bonuswheel_spin")?.gameObject;
fx_arrow_spin = this.gameObject.FindChildGameObject("fx_ui_bonuswheel_arrow_spin")?.gameObject;
lightAni = this.gameObject.FindChildGameObject("p_light")?.GetComponent<Animation>();
zhizhenTrans = this.gameObject.FindChildGameObject("zhizhen")?.GetComponent<Transform>();
for (int i = 1; i <= 3; i++)
{
var key = $"fx_ui_bonuswheel_reward_claim_0{i}";
if (_fxNameObjs.ContainsKey(key)) continue;
var fx = this.gameObject.FindChildGameObject(key)?.gameObject;
if (fx == null) continue;
fx.SetActive(false);
_fxNameObjs.Add(key, fx);
}
}
protected override void Start()
{
base.Start();
lightAni.Play("light_idle");
}
protected override void InitUI()
{
base.InitUI();
fx_spin.SetActive(false);
fx_arrow_spin.SetActive(false);
wheelClipLoop = lightAni?["light_spin_loop"];
}
public override void SetData(List<IWheelReward> rewards)
{
for (int i = 0; i < rewards.Count && i < wheelRewardCells.Length; i++)
{
wheelRewardCells[i].SetData(rewards[i]);
}
}
public override void ShowUI()
{
foreach (var rewardCell in wheelRewardCells)
{
rewardCell.ShowUI();
}
}
protected override void EffectStart()
{
base.EffectStart();
InitPointerAni();
_ = LightStarAni();
foreach (var fx in _fxNameObjs)
fx.Value?.SetActive(false);
fx_arrow_spin.SetActive(true);
}
protected override void EffectUpdate(float currentVelocity, float currentValue)
{
base.EffectUpdate(currentVelocity, currentValue);
SetClipLoopSpeed(currentVelocity);
PointerAni(currentValue, currentVelocity);
}
protected override async Task EffectEnd(IWheelReward reward)
{
fx_spin.SetActive(false);
fx_arrow_spin.SetActive(false);
if (_fxNameObjs.TryGetValue(reward.Fx, out var value))
value.SetActive(true);
zhizhenTrans.rotation = Quaternion.Euler(0, 0, 0);
if (!string.IsNullOrEmpty(reward.Audio))
{
GContext.Publish(new EventUISound(reward.Audio));
}
await base.EffectEnd(reward);
lightAni.Play("light_idle");
}
protected override async Task DelayShow()
{
await base.DelayShow();
fx_spin?.SetActive(true);
}
protected override void RevertTargetEndCallbcak()
{
base.RevertTargetEndCallbcak();
_ = LightEndAni();
}
#region private
private void SetClipLoopSpeed(float currentVelocity)
{
wheelClipLoop.speed = Mathf.Max(Mathf.Abs(currentVelocity / 360), 0.1f);
}
private async Task LightStarAni()
{
var time = lightAni["light_spin_start"].length;
lightAni.Play("light_spin_start");
await Awaiters.Seconds(time);
lightAni.Play("light_spin_loop");
}
private async Task LightEndAni()
{
float remainingTime = wheelClipLoop.length * (1f - wheelClipLoop.normalizedTime);
await Awaiters.Seconds(remainingTime);
var clipEndTime = lightAni["light_spin_end"].length;
lightAni.Play("light_spin_end");
await Awaiters.Seconds(clipEndTime);
var clipRewardTime = lightAni["light_reward"].length;
lightAni.Play("light_reward");
}
#endregion
#region CD Shark Animation
public async Task PlayCdEffect(Action endCallback)
{
InitPointerAni();
GContext.Publish(new EventUISound("audio_ui_bonuswheel_arrow_spin_stuck"));
var param = new AnimationSimulatorComponent.Parameter();
param.scale = 360;
param.customVelocity = cdEffectVelocity;
param.startValue = rewardContainer.eulerAngles.z;
param.updateCallback = (float currentVelocity, float currentValue) =>
{
EffectUpdate(currentVelocity, currentValue);
};
await simulator.SharkAni(param);
endCallback?.Invoke();
}
#endregion
#region Pointer Animation
private void InitPointerAni()
{
var currentValue = rewardContainer.eulerAngles.z;
lastValue = currentValue;
lastSegment = GetSegment(currentValue);
}
private void PointerAni(float currentValue, float currentVelocity)
{
currentSegment = GetSegment(currentValue);
lastSegment = GetSegment(lastValue);
var normalizeCurrentAngle = NormalizeAngle(currentValue);
if (currentSegment != lastSegment)
{
int direction = GetCrossDirection(lastSegment, currentSegment);
var time = wheelAngle / currentVelocity;
var pointerTargetAngle = Mathf.Abs(Mathf.Clamp01(normalizeCurrentAngle / wheelAngle) * pointerAngle);
zhizhenTrans.DORotate(new Vector3(0, 0, direction * pointerTargetAngle), time)
.OnComplete(() =>
{
_tweener?.Kill();
_tweener = zhizhenTrans.DORotate(Vector3.zero, revertAngleTime);
});
}
lastValue = currentValue;
}
private int GetSegment(float angle)
{
float normalizedAngle = NormalizeAngle(angle);
return Mathf.FloorToInt(normalizedAngle / SegmentAngle);
}
private float NormalizeAngle(float angle)
{
angle %= FULL_CIRCLE;
if (angle < 0)
angle += FULL_CIRCLE;
return angle;
}
private int GetCrossDirection(int fromSegment, int toSegment)
{
int diff = toSegment - fromSegment;
if ((fromSegment == MaxSegment && toSegment == 0) || (fromSegment == 0 && toSegment == MaxSegment))
diff = -diff;
return diff < 0 ? 1 : -1;
}
#endregion
}
}