using Assets.MyGame.Scripts.Net;
using Newtonsoft.Json;
using Spine.Unity;
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using static Assets.MyGame.Scripts.Net.WebResponses.ChineseChess.ChineseChessGameClassList;
public class HintData
{
public ChessGameRoom roomData;
public int hintType; //1求和2认输
}
///
/// GoldConfigRequired Socket 推送数据
///
[Serializable]
public class GoldConfigRequiredData
{
public string targetUserId;
public ChessGameRoom room;
}
public enum CountdownType
{
WaitPlayer, // 等待玩家进入,超时 → 退出到选房
WaitHostStart, // 等待房主开始游戏,超时 → 退出到选房
WaitSetCoin, // 等待设置金额,超时 → 退出到选房
WaitOpponent, // 等待对手操作,超时 → 自动处理
}
public class ChineseChessMainPanel : GameMainPanel_Base
{
public Button btn_QiuHe;
public Button btn_RenShu;
public Button btn_HuiQi;
public Button btn_SheZhi;
public Button btn_GuiZe;
public Button btn_StartGame;
public Image img_DengDaiZhong;
public ChessGameRoom roomData;
public static Dictionary dic_RoomData=new Dictionary();
public Button btn_FanHuiDaTing;
[Header("Bottom")]
public TextMeshProUGUI tmp_Name_Bottom;
public TextMeshProUGUI tmp_CoinCount_Bottom;
public TextMeshProUGUI tmp_WaitTime_Bottom;
public Image img_Title_Bottom;
[Header("Top")]
public TextMeshProUGUI tmp_Name_Top;
public TextMeshProUGUI tmp_CoinCount_Top;
public TextMeshProUGUI tmp_WaitTime_Top;
public Image img_Title_Top;
private Coroutine waitCountdown;
public SkeletonGraphic skeletonGraphic;
public string skineName_JinXingZhong;
public string skineName_KaiShi;
public string skineName_PiPeiChengGong;
public string skineName_ZhengZaiPiPei;
public string animName_Close;
public string animName_Open;
public string animName_Loop;
#region Spine 动画辅助
/// 激活/禁用 Spine(不用时禁用节省性能,用时激活)
public void ActiveSpine(bool active)
{
if (skeletonGraphic == null) return;
if (skeletonGraphic.gameObject.activeSelf != active)
skeletonGraphic.gameObject.SetActive(active);
}
/// 设置 Spine skin(切换皮肤并重置 slot)
public void SetSpineSkin(string skinName)
{
if (skeletonGraphic == null || string.IsNullOrEmpty(skinName)) return;
ActiveSpine(true);
var skel = skeletonGraphic.Skeleton;
if (skel == null) return;
skel.SetSkin(skinName);
skel.SetSlotsToSetupPose();
skeletonGraphic.LateUpdate();
}
/// 播放 Spine 动画
public void PlaySpineAnim(string animName, bool loop = true)
{
if (skeletonGraphic == null || string.IsNullOrEmpty(animName)) return;
ActiveSpine(true);
skeletonGraphic.AnimationState.SetAnimation(0, animName, loop);
}
/// 切换到"正在匹配"状态
public void Spine_ZhengZaiPiPei()
{
SetSpineSkin(skineName_ZhengZaiPiPei);
PlaySpineAnim(animName_Loop, true);
}
/// 切换到"匹配成功"状态:Open → 完成后播 Close → 禁用
public void Spine_PiPeiChengGong()
{
SetSpineSkin(skineName_PiPeiChengGong);
PlaySpineAnim(animName_Open, false);
// Open 播完后播 Close,然后禁用 Spine
StartCoroutine(DelayedSpineClose());
}
/// Open 动画播完后播放 Close 动画并禁用 Spine
private IEnumerator DelayedSpineClose()
{
// 等 Open 动画播完
yield return new WaitForSeconds(0.5f);
PlaySpineAnim(animName_Close, false);
// Close 播完后禁用 Spine
yield return new WaitForSeconds(0.5f);
ActiveSpine(false);
}
/// 切换到"开始游戏"状态(短暂过渡)
public void Spine_KaiShi()
{
SetSpineSkin(skineName_KaiShi);
PlaySpineAnim(animName_Open, false);
}
/// 切换到"进行中"状态
public void Spine_JinXingZhong()
{
SetSpineSkin(skineName_JinXingZhong);
PlaySpineAnim(animName_Loop, true);
}
/// 延迟切换到"进行中"状态(等 KaiShi 过渡动画播完)
private IEnumerator DelayedSpine_JinXingZhong()
{
// 等待开始过渡动画播放完(默认 0.5s)
yield return new WaitForSeconds(0.5f);
Spine_JinXingZhong();
}
/// KaiShi 动画流程:Open 播完后切 Loop 播一小会,再播 Close 关闭并禁用
private IEnumerator DelayedKaiShiLoopToClose()
{
// 等 Open 动画播完
yield return new WaitForSeconds(0.5f);
// 切 Loop 动画播一小会
PlaySpineAnim(animName_Loop, true);
yield return new WaitForSeconds(1f);
// 播 Close 动画并禁用 Spine
PlaySpineAnim(animName_Close, false);
yield return new WaitForSeconds(0.5f);
ActiveSpine(false);
}
#endregion
///
/// 加载头像精灵(优先使用缓存,否则异步下载)
///
public static void LoadAvatar(Image target, string avatarUrl, System.Action onLoaded = null)
{
if (target == null) return;
var sprite = GameManager.Instance.GetAvatarSprite(avatarUrl);
if (sprite != null)
{
target.sprite = sprite;
onLoaded?.Invoke(sprite);
return;
}
// 缓存未命中,通过 DownSprite 协程异步加载
GameManager.Instance.StartCoroutine(LoadAvatarCoroutine(target, avatarUrl, onLoaded));
}
private static IEnumerator LoadAvatarCoroutine(Image target, string avatarUrl, System.Action onLoaded)
{
// 构造一个临时的 UserBaseInfo 对象来复用 DownSprite 逻辑
var tempInfo = new UserBaseInfo { avatarUrl = avatarUrl };
yield return tempInfo.DownSprite(sprite =>
{
if (sprite != null && target != null)
target.sprite = sprite;
onLoaded?.Invoke(sprite);
});
}
public static string FormatGold(long gold)
{
if (gold >= 100000000)
{
// 截取两位小数,不四舍五入
long yi = gold / 100000000;
long remainder = gold % 100000000;
long decimals = remainder * 100 / 100000000;
if (decimals > 0)
return $"{yi}.{decimals:D2}亿";
return $"{yi}亿";
}
if (gold >= 10000)
{
// 截取两位小数,不四舍五入
long wan = gold / 10000;
long remainder = gold % 10000;
long decimals = remainder * 100 / 10000; // 两位小数
if (decimals > 0)
return $"{wan}.{decimals:D2}万";
return $"{wan}万";
}
return gold.ToString();
}
public void StartGame(string msg)
{
var va = JsonConvert.DeserializeObject>(msg.ToString());
ChessGameRoom chessGameRoom = va.arguments[0];
UpdateUserData(chessGameRoom);
switch (chessGameRoom.users.Count)
{
case 1:
{
tmp_Name_Top.text = "等待玩家进入";
tmp_CoinCount_Top.text = "";
img_Title_Top.gameObject.SetActive(false);
if (tmp_WaitTime_Bottom != null) tmp_WaitTime_Bottom.text = "等待玩家进入02:00";
if (tmp_WaitTime_Top != null) tmp_WaitTime_Top.text = "等待玩家进入02:00";
StartWaitCountdown(120, CountdownType.WaitPlayer, "等待玩家进入");
// 正在匹配
Spine_ZhengZaiPiPei();
}
break;
case 2:
{
StopWaitCountdown();
img_Title_Top.gameObject.SetActive(true);
// 判断是否为房主
bool isRoomOwner = chessGameRoom.users.Count > 0
&& chessGameRoom.users[0].userId == GameManager.Instance.user.BaseInfo.number;
if (isRoomOwner)
{
btn_StartGame.gameObject.SetActive(true);
btn_StartGame.onClick.RemoveAllListeners();
btn_StartGame.onClick.AddListener(() =>
{
// 房主点击开始 → 发送 StartGame Socket 请求
btn_StartGame.gameObject.SetActive(false);
StopWaitCountdown();
WebSocketSendList.StartGameChineseChess(chessGameRoom.roomId, GameManager.Instance.user.BaseInfo.number);
});
}
else
{
btn_StartGame.gameObject.SetActive(false);
}
StartWaitCountdown(60, CountdownType.WaitHostStart, "等待房主开始游戏");
// 匹配成功
Spine_PiPeiChengGong();
}
break;
default:
break;
}
}
///
/// 服务端推送 GoldConfigRequired → 显示金币设置面板(红方配置)
/// data: { targetUserId, room }
///
public void OnGoldConfigRequired(string msg)
{
StopWaitCountdown();
var result = JsonConvert.DeserializeObject>(msg);
var data = result.arguments[0];
// 更新房间数据
if (data.room != null)
{
roomData = data.room;
UpdateUserData(data.room);
}
// 判断当前用户是否为红方(targetUserId)
bool isRedSide = data.targetUserId == GameManager.Instance.user.BaseInfo.number;
if (isRedSide)
{
// 红方显示金币设置面板
subUIManager.ShowAsync(UIPanel.ZGXQSelectCoin, roomData);
StartWaitCountdown(60, CountdownType.WaitSetCoin, "等待设置金额");
}
else
{
// 黑方等待红方设置金币
StartWaitCountdown(60, CountdownType.WaitSetCoin, "等待对方设置金额");
}
}
public void UpdateUserData(ChessGameRoom chessGameRoom)
{
foreach (var item in chessGameRoom.users)
{
if (item.userId == GameManager.Instance.user.BaseInfo.number)
{
tmp_Name_Bottom.text ="ID:" + item.userId;
tmp_CoinCount_Bottom.text = FormatGold(item.gold);
LoadAvatar(img_Title_Bottom, item.userAvatar);
}
else
{
tmp_Name_Top.text ="ID:" + item.userId;
tmp_CoinCount_Top.text = FormatGold(item.gold);
LoadAvatar(img_Title_Top, item.userAvatar);
}
}
}
public override void Awake()
{
base.Awake();
btn_FanHuiDaTing.onClick.AddListener(() =>
{
UIManager.Instance.Close(UIPanel.MainGamePanelZGXQ);
});
btn_GuiZe.onClick.AddListener(() =>
{
subUIManager.ShowAsync(UIPanel.ZGXQIntroduce);
});
}
protected override void OnShow(object args = null)
{
base.OnShow(args);
// 回到选房间界面时显示等待中(连带父对象)
SetDengDaiZhongActive(true);
subUIManager.ShowAsync(UIPanel.ZGXQDistrict, args);
// 选房阶段不使用 Spine,禁用
ActiveSpine(false);
}
///
/// 显示/隐藏等待中(连带控制父对象链)
///
public void SetDengDaiZhongActive(bool active)
{
if (img_DengDaiZhong != null)
{
img_DengDaiZhong.gameObject.SetActive(active);
}
}
public void IsShowHint(string id,int type)
{
if (GameManager.Instance.user.BaseInfo.number!=id)
{
subUIManager.ShowAsync(UIPanel.ZGXQHint, new HintData
{
roomData = roomData,
hintType = type
});
}
}
public void InitRoomData()
{
// 游戏已开始,停止所有倒计时
StopWaitCountdown();
// 关闭游戏说明面板(双方都准备完毕,进入进行中)
subUIManager.Close(UIPanel.ZGXQGameExplain);
// 双方都准备完毕:播放 KaiShi Spine 动画 Open → Loop 一小会 → Close
Spine_KaiShi();
StartCoroutine(DelayedKaiShiLoopToClose());
btn_QiuHe.onClick.RemoveAllListeners();
btn_RenShu.onClick.RemoveAllListeners();
btn_QiuHe.onClick.AddListener(() =>
{
WebSocketSendList.GameOperationChineseChess(roomData.roomId,1,GameManager.Instance.user.BaseInfo.number);
});
btn_RenShu.onClick.AddListener(() =>
{
//WebSocketSendList.GameOperationChineseChess(roomData.roomId, 2, GameManager.Instance.user.BaseInfo.number);
subUIManager.ShowAsync(UIPanel.ZGXQHint, new HintData
{
roomData = roomData,
hintType = 2
});
});
}
public void Start()
{
}
///
/// 开始等待倒计时
///
/// 总秒数
/// 倒计时类型
/// 等待时显示的文字,如"等待玩家进入"
public void StartWaitCountdown(int seconds, CountdownType type = CountdownType.WaitPlayer, string waitMsg = null)
{
if (waitCountdown != null) StopCoroutine(waitCountdown);
waitCountdown = StartCoroutine(WaitCountdownRoutine(seconds, type, waitMsg));
}
///
/// 停止等待倒计时
///
public void StopWaitCountdown()
{
if (waitCountdown != null)
{
StopCoroutine(waitCountdown);
waitCountdown = null;
}
if (tmp_WaitTime_Bottom != null) tmp_WaitTime_Bottom.text = "";
if (tmp_WaitTime_Top != null) tmp_WaitTime_Top.text = "";
}
private IEnumerator WaitCountdownRoutine(int totalSeconds, CountdownType type, string waitMsg)
{
int remaining = totalSeconds;
while (remaining >= 0)
{
string timeStr = $"{remaining / 60:D2}:{remaining % 60:D2}";
switch (type)
{
default:
string displayText = string.IsNullOrEmpty(waitMsg) ? timeStr : $"{waitMsg}{timeStr}";
if (tmp_WaitTime_Bottom != null)
tmp_WaitTime_Bottom.text = displayText;
if (tmp_WaitTime_Top != null)
tmp_WaitTime_Top.text = displayText;
break;
}
yield return new WaitForSeconds(1f);
remaining--;
}
switch (type)
{
default:
// 超时:返回选房间界面
subUIManager.CloseAll();
WebSocketSendList.GetRoomListChineseChess(1);
break;
}
}
protected override void OnHide()
{
base.OnHide();
// 退出:播放 Close 动画后禁用 Spine
PlaySpineAnim(animName_Close, false);
ActiveSpine(false);
WebSocketManager.Instance.Close(SocketType.chess);
Screen.orientation = ScreenOrientation.LandscapeLeft;
}
}