176 lines
6.4 KiB
C#
176 lines
6.4 KiB
C#
using Assets.MyGame.Scripts.Net;
|
||
using Assets.MyGame.Scripts.Net.API.GameConfig_SubClass;
|
||
using Assets.MyGame.Scripts.Net.APIResponses;
|
||
using DG.Tweening;
|
||
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
public class UIHome_BY_UISignViewPanel : SubUIBase
|
||
{
|
||
//text_CoinNums是转盘各个位置的详细值 他从GameManager的activityConfig里面读取signConfigs后端配置的个数和text_CoinNums的个数是对应的 这里赋值的时候需要加上其他的数据公式是 值+值*GameManager的gameConfig的vip的signInAdd签到加成
|
||
/* /// <summary>
|
||
/// 签到(GET)
|
||
/// 参数:用户ID
|
||
/// 返回:SignInfo(签到结果)
|
||
/// </summary>
|
||
public static void SignIn(Action<SignInfo> callback)
|
||
{
|
||
APIManager.Response<SignInfo>(APIType.Hall_SignIn, callback);
|
||
}
|
||
*///这个是签到的api封装的方法SLZPDieEvent这个脚本有之前写好的多层转盘的逻辑 签到这里只有单层 你可以直接看一下里面正确的
|
||
public List<Text> text_CoinNums;
|
||
public Button btn_ChouJiang;
|
||
public GameObject zhuanPan;
|
||
Dictionary<int, SignConfig> order_singConfig;
|
||
|
||
[Header("转盘参数(参照SLZPDieEvent)")]
|
||
public int spinRounds = 5; // 到达目标前转的圈数
|
||
public float rotateDuration = 2f; // 旋转总时长
|
||
public float dir = -1f; // 旋转方向(-1逆时针,1顺时针)
|
||
|
||
private bool isSpinning;
|
||
|
||
public override void Awake()
|
||
{
|
||
base.Awake();
|
||
btn_ChouJiang.onClick.AddListener(OnChouJiangClick);
|
||
}
|
||
|
||
protected override void OnShow(object args = null)
|
||
{
|
||
base.OnShow(args);
|
||
RefreshPanel();
|
||
}
|
||
|
||
private void RefreshPanel()
|
||
{
|
||
BuildOrderSignConfig();
|
||
UpdateSlotTexts();
|
||
UpdateBtnState();
|
||
}
|
||
|
||
/// <summary>从GameManager的activityConfig读取signConfigs,按order建立字典</summary>
|
||
private void BuildOrderSignConfig()
|
||
{
|
||
order_singConfig = new Dictionary<int, SignConfig>();
|
||
var signConfigs = GameManager.Instance.activityConfig?.signConfigs;
|
||
if (signConfigs == null) return;
|
||
foreach (var cfg in signConfigs)
|
||
{
|
||
if (cfg == null) continue;
|
||
order_singConfig[cfg.order] = cfg;
|
||
}
|
||
}
|
||
|
||
/// <summary>当前用户的VIP签到加成(gameConfig.vipLevelConfigs按用户vipLevel匹配signInAdd)</summary>
|
||
private double GetSignInAdd()
|
||
{
|
||
var vipConfigs = GameManager.Instance.gameConfig?.vipLevelConfigs;
|
||
if (vipConfigs == null || vipConfigs.Count == 0) return 0;
|
||
var user = GameManager.Instance.user;
|
||
if (user?.assets == null) return 0;
|
||
var vipCfg = vipConfigs.Find(v => v.level == user.assets.vipLevel);
|
||
return vipCfg?.signInAdd ?? 0;
|
||
}
|
||
|
||
/// <summary>转盘格子赋值:值+值*signInAdd(VIP签到加成),按order排序后与text_CoinNums一一对应</summary>
|
||
private void UpdateSlotTexts()
|
||
{
|
||
if (order_singConfig == null || order_singConfig.Count == 0 || text_CoinNums == null) return;
|
||
|
||
var list = new List<SignConfig>(order_singConfig.Values);
|
||
list.Sort((a, b) => a.order - b.order);
|
||
|
||
double add = GetSignInAdd();
|
||
int count = Mathf.Min(list.Count, text_CoinNums.Count);
|
||
for (int i = 0; i < count; i++)
|
||
{
|
||
long gold = list[i].gold;
|
||
long showGold = gold + (long)Math.Round(gold * add);
|
||
text_CoinNums[i].text = FormatGold(showGold);
|
||
}
|
||
}
|
||
|
||
/// <summary>今日是否已签到</summary>
|
||
private bool IsSignedToday()
|
||
{
|
||
var sign = GameManager.Instance.user?.sign;
|
||
return sign != null && sign.isSign;
|
||
}
|
||
|
||
private void UpdateBtnState()
|
||
{
|
||
btn_ChouJiang.interactable = !isSpinning && !IsSignedToday();
|
||
}
|
||
|
||
private void OnChouJiangClick()
|
||
{
|
||
if (isSpinning) return;
|
||
btn_ChouJiang.interactable = false;
|
||
|
||
APIRequestList.SignIn(res =>
|
||
{
|
||
// day是第几天签到(1开始),对应转盘格子 = day-1
|
||
int count = text_CoinNums.Count > 0 ? text_CoinNums.Count : 1;
|
||
int slot = res.day > 0 ? (res.day - 1) % count : 0;
|
||
RotateToSlot(slot, () =>
|
||
{
|
||
string msg = "签到成功";
|
||
if (res.rewardGold > 0) msg += $",获得{FormatGold(res.rewardGold)}金币";
|
||
if (res.rewardDiamond > 0) msg += $",{FormatGold(res.rewardDiamond)}钻石";
|
||
UIManager.Instance.ShowBoardError(msg);
|
||
|
||
APIRequestList.GetUser(user =>
|
||
{
|
||
GameManager.Instance.UpdataUserData(user);
|
||
UpdateBtnState();
|
||
});
|
||
});
|
||
});
|
||
}
|
||
|
||
/// <summary>单层转盘旋转停靠(参照SLZPDieEvent:LocalAxisAdd增量旋转+OutCubic缓动+完成强制校正)</summary>
|
||
private void RotateToSlot(int slot, Action onComplete)
|
||
{
|
||
isSpinning = true;
|
||
int cellCount = text_CoinNums.Count > 0 ? text_CoinNums.Count : 1;
|
||
float targetAngle = slot * (360f / cellCount);
|
||
|
||
float curr = zhuanPan.transform.localRotation.eulerAngles.z;
|
||
float deltaToTarget = AngleDiff(curr, targetAngle, dir);
|
||
float totalDelta = dir * spinRounds * 360f + deltaToTarget;
|
||
|
||
Tween tween = zhuanPan.transform.DOLocalRotate(new Vector3(0, 0, totalDelta), rotateDuration, RotateMode.LocalAxisAdd);
|
||
tween.SetEase(Ease.OutCubic);
|
||
tween.OnComplete(() =>
|
||
{
|
||
// 强制校正到精确目标角度,消除浮点误差
|
||
zhuanPan.transform.localRotation = Quaternion.Euler(0, 0, targetAngle);
|
||
isSpinning = false;
|
||
onComplete?.Invoke();
|
||
});
|
||
}
|
||
|
||
/// <summary>从curr到target的同向角度差(参照SLZPDieEvent.AngleDiff)</summary>
|
||
private float AngleDiff(float curr, float target, float dir)
|
||
{
|
||
float diff = (target - curr) % 360f;
|
||
if (diff < 0) diff += 360f;
|
||
if (dir < 0 && diff > 0) diff -= 360f;
|
||
return diff;
|
||
}
|
||
|
||
/// <summary>金币数值格式化(万/亿单位)</summary>
|
||
private static string FormatGold(long gold)
|
||
{
|
||
if (gold >= 100000000) // 亿
|
||
return $"{(gold / 100000000f):F1}亿";
|
||
if (gold >= 10000) // 万
|
||
return $"{(gold / 10000f):F1}万";
|
||
return gold.ToString("N0");
|
||
}
|
||
}
|