1884 lines
54 KiB
C#
1884 lines
54 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using ScrewsMaster;
|
|
using DG.Tweening;
|
|
using DG.Tweening.Core;
|
|
using DG.Tweening.Plugins.Options;
|
|
using FairyGUI;
|
|
using FGUI.G018_GameHome;
|
|
using Roy.Datas;
|
|
using Roy.ObjectPool;
|
|
using SGame;
|
|
using UnityEngine;
|
|
using UnityEngine.Serialization;
|
|
using UnityEngine.UI;
|
|
using Image = UnityEngine.UI.Image;
|
|
using Random = UnityEngine.Random;
|
|
|
|
public class ShowScrews : MonoBehaviour, ICanvasRaycastFilter
|
|
{
|
|
[FormerlySerializedAs("Cheaps")][SerializeField] private GameObject cheaps;//板子创建的父节点
|
|
[FormerlySerializedAs("BoxStartPos")][SerializeField] private Transform boxStartPos;//box的初始创建位置
|
|
[FormerlySerializedAs("Panel")][SerializeField] private GameObject panel;
|
|
[FormerlySerializedAs("AddHole")][SerializeField] private Button addHole;
|
|
[FormerlySerializedAs("MergeBox")][SerializeField] private Button mergeBox;
|
|
[FormerlySerializedAs("ClearHole")][SerializeField] private Button clearHole;
|
|
[FormerlySerializedAs("CacheArea")][SerializeField] public GameObject cacheArea;
|
|
[FormerlySerializedAs("BoxDestroy")][SerializeField] private Transform boxDestroy;
|
|
[FormerlySerializedAs("Box1_pay")][SerializeField] private GameObject box1Pay;
|
|
[FormerlySerializedAs("Box2_pay")][SerializeField] private GameObject box2Pay;
|
|
|
|
public Button errorBtn;
|
|
|
|
//单例
|
|
public static ShowScrews Instance;
|
|
|
|
private readonly List<string> _panelTypeColors = new List<string>()
|
|
{
|
|
"#F7AB25",
|
|
"#FAE93F",
|
|
"#52D0FF",
|
|
"#87B4FF",
|
|
"#90F050",
|
|
"#FF96D4",
|
|
"#BE9DFF",
|
|
"#B27388",
|
|
"#F5716D",
|
|
};
|
|
|
|
//板子层级的类型
|
|
public Dictionary<int, string> ScrewsType = new Dictionary<int, string>()
|
|
{
|
|
{1,"lsd1" },
|
|
{2,"lsd2" },
|
|
{3,"lsd3" },
|
|
{4,"lsd4" },
|
|
{5,"lsd5" },
|
|
{6,"lsd6" },
|
|
{7,"lsd7" },
|
|
{8,"lsd8" },
|
|
{9,"lsd9" },
|
|
|
|
};
|
|
|
|
//螺丝的类型对应的颜色集合
|
|
public static readonly List<string> ScrewColors = new List<string>()
|
|
{
|
|
"#B0661D",
|
|
"#1E7DAF",
|
|
"#558C20",
|
|
"#7456AD",
|
|
"#BC4542",
|
|
"#C88D1C",
|
|
"#4071C3",
|
|
"#CA579B",
|
|
"#814559",
|
|
};
|
|
|
|
private RectTransform _panelRect;
|
|
|
|
private void Awake()
|
|
{
|
|
if (Instance == null)
|
|
{
|
|
Instance = this;
|
|
}
|
|
else if (Instance != this)
|
|
{
|
|
Destroy(gameObject);
|
|
}
|
|
|
|
}
|
|
|
|
public Camera myCamera;
|
|
void Start()
|
|
{
|
|
myCamera = GetComponent<Canvas>().worldCamera;
|
|
|
|
_panelRect = panel.transform as RectTransform;
|
|
if (Screen.safeArea.y != 0 && topRectTransform != null)
|
|
{
|
|
var newPos = topRectTransform.anchoredPosition;
|
|
newPos.y -= Screen.safeArea.y;
|
|
topRectTransform.anchoredPosition = newPos;
|
|
|
|
// 获取当前图片距离底部的距离
|
|
float topPadding = _panelRect.offsetMax.y;
|
|
|
|
// 设置上部距离
|
|
_panelRect.offsetMax = new Vector2(_panelRect.offsetMax.x, topPadding - Screen.safeArea.y);
|
|
|
|
// 保持底部距离不变
|
|
// panelTransform.offsetMin = new Vector2(panelTransform.offsetMin.x, bottomPadding);
|
|
}
|
|
|
|
|
|
|
|
maskImg.gameObject.SetActive(true);
|
|
|
|
Init();
|
|
|
|
box1Pay.GetComponent<Button>().onClick.AddListener(OnPayBox1);
|
|
box2Pay.GetComponent<Button>().onClick.AddListener(OnPayBox2);
|
|
|
|
addHole.onClick.AddListener(OnAddHoleBtnClick);
|
|
mergeBox.onClick.AddListener(OnMergeBoxBtnClick);
|
|
clearHole.onClick.AddListener(OnClearHoleBtnClick);
|
|
|
|
errorBtn.gameObject.SetActive(false);
|
|
#if !JarvisRelease
|
|
errorBtn.gameObject.SetActive(true);
|
|
if (errorBtn == null) return;
|
|
|
|
errorBtn.onClick.AddListener(() =>
|
|
{
|
|
GameHelper.SendErrorToServer("TestError 001", LogType.Error.ToString());
|
|
});
|
|
#endif
|
|
|
|
}
|
|
|
|
public void InitSaveData()
|
|
{
|
|
var saveObject = SaveData.GetSaveobject();
|
|
|
|
if (saveObject.StageData != null)
|
|
{
|
|
_requestStageData = saveObject.StageData;
|
|
TrackGameCompletion(false);
|
|
saveObject.StageData = null;
|
|
SaveData.saveDataFunc();
|
|
}
|
|
|
|
}
|
|
|
|
#region 新版代码(测试)
|
|
private const float FlyScrewsAnimTime = 1.15f;
|
|
|
|
public bool _isLevelOver;
|
|
public bool gameOver;
|
|
|
|
public int gameMode = 0;
|
|
|
|
[Header("飞行层")]
|
|
public Transform flightControlLayer;
|
|
[Header("全屏遮罩")]
|
|
public Image maskImg;
|
|
|
|
[Header("顶部盒子")]
|
|
public RectTransform topRectTransform;
|
|
|
|
[Header("进度条相关")]
|
|
public Text levelText;
|
|
public Text gameProgressText;
|
|
public Image gameProgress;
|
|
private Vector2 _gameProgressSize = Vector2.zero;
|
|
private float _lastProgress;
|
|
private TweenerCore<Vector2, Vector2, VectorOptions> _gameProgressTween;
|
|
private TweenerCore<int, int, NoOptions> _gameProgressTextTween;
|
|
private const float ProgressAnimTime = 0.5f;
|
|
|
|
[Header("盒子摆放位置父节点")]
|
|
public GameObject boxTargetObj;
|
|
private List<Transform> _screwBoxShowPosList;
|
|
private Dictionary<int, BoxTypeLogic> _activityBoxDic;
|
|
|
|
/// <summary>
|
|
/// 舞台范围
|
|
/// </summary>
|
|
private Vector3[] _stageArea = new Vector3[4];
|
|
private const int ScrewsPerType = 3; // 确保每种至少3个
|
|
|
|
/// <summary>
|
|
/// 关卡所需螺丝数量
|
|
/// </summary>
|
|
private int _screwCountForLevel;
|
|
/// <summary>
|
|
/// 待生成螺丝数量
|
|
/// </summary>
|
|
private int _pendingScrewCount;
|
|
|
|
|
|
//资源相关
|
|
private List<PanelLogic> _panelResList;
|
|
private List<Sprite> _screwsResList;
|
|
private List<BoxTypeLogic> _screwsBoxResList;
|
|
|
|
//生成的对象合集
|
|
public Dictionary<int, List<PanelLogic>> PanelLayerDic;
|
|
private Dictionary<int, List<BoxTypeLogic>> _boxLayerDic;
|
|
|
|
//螺丝相关
|
|
private List<int> _screwsDataList;
|
|
|
|
//螺丝盒相关
|
|
private int _screwBoxCount;
|
|
private int _curScrewBoxCount;
|
|
private Dictionary<int, int> _screwsBoxDataList;
|
|
|
|
/// <summary>
|
|
/// 螺丝合集
|
|
/// </summary>
|
|
private Dictionary<int, int> _screwsTypeDic;
|
|
|
|
/// <summary>
|
|
/// 缓冲区螺丝孔
|
|
/// </summary>
|
|
private List<KongLogic> _kongLogics;
|
|
|
|
/// <summary>
|
|
/// 隐藏的螺丝缓存,被道具或复活清理的
|
|
/// </summary>
|
|
private List<ScrewsLogic> _hideCacheScrewsLogics;
|
|
|
|
private const int DefaultUnlockingHoleCount = 5;
|
|
private const int MaxUnlockingHoleCount = 7;
|
|
private int _curUnlockingHoleCount;
|
|
|
|
/// <summary>
|
|
/// 关卡数据,后端获取
|
|
/// </summary>
|
|
private List<LevelData> _levelDataList;
|
|
|
|
private List<int> _lockPanelLayerList;
|
|
|
|
private Sequence _sequence;
|
|
|
|
private void Init()
|
|
{
|
|
gameMode = GameHome.Mode_simple;
|
|
LoadResources();
|
|
|
|
if (boxTargetObj != null)
|
|
{
|
|
_screwBoxShowPosList = new List<Transform>(4);
|
|
for (int i = 0; i < boxTargetObj.transform.childCount; i++)
|
|
{
|
|
_screwBoxShowPosList.Add(boxTargetObj.transform.GetChild(i));
|
|
}
|
|
}
|
|
|
|
if (cacheArea != null)
|
|
{
|
|
_kongLogics = new List<KongLogic>(8);
|
|
for (int i = 0; i < cacheArea.transform.childCount; i++)
|
|
{
|
|
var kongLogic = cacheArea.transform.GetChild(i).GetComponent<KongLogic>();
|
|
if (kongLogic)
|
|
{
|
|
_kongLogics.Add(kongLogic);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void InitItemBar()
|
|
{
|
|
if (GameHelper.IsGiftSwitch())
|
|
{
|
|
var newPos = topRectTransform.anchoredPosition;
|
|
newPos.y -= 100;
|
|
topRectTransform.anchoredPosition = newPos;
|
|
|
|
float topPadding = _panelRect.offsetMax.y;
|
|
_panelRect.offsetMax = new Vector2(_panelRect.offsetMax.x, topPadding - 100);
|
|
|
|
var addHoleTransform = addHole.transform as RectTransform;
|
|
var mergeBoxTransform = mergeBox.transform as RectTransform;
|
|
addHoleTransform.localPosition += Vector3.right * 150;
|
|
mergeBoxTransform.localPosition += Vector3.right * 75;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 初始化关卡数据
|
|
/// </summary>
|
|
public void InitAllLeveData()
|
|
{
|
|
int conf_num = PlayerPrefs.GetInt("game_conf_num", 1);
|
|
// Debug.Log(conf_num);
|
|
// Debug.Log(PlayerPrefs.GetInt("game_conf_num", 1));
|
|
if (conf_num == 2)
|
|
{
|
|
_levelDataList = ConfigSystem.GetConfig<LevelDataModel_2>().dataList;
|
|
}
|
|
else if (conf_num == 3)
|
|
{
|
|
_levelDataList = ConfigSystem.GetConfig<LevelDataModel_3>().dataList;
|
|
}
|
|
else
|
|
{
|
|
_levelDataList = ConfigSystem.GetConfig<LevelDataModel>().dataList;
|
|
}
|
|
}
|
|
|
|
private void InitCurLevelData(int index)
|
|
{
|
|
var levelData = _levelDataList[index];
|
|
|
|
var screwCount = levelData.screwCount;
|
|
if (screwCount % 3 != 0)
|
|
{
|
|
// 减去余数,使 screwCount 可以被 3 整除
|
|
screwCount -= screwCount % 3;
|
|
Debug.LogError($"配置错误 螺丝数量无法被3整除,原数据{levelData.screwCount} 修改为{screwCount} 请检查{index}关!!!!!!!!");
|
|
}
|
|
|
|
_screwCountForLevel = screwCount;
|
|
_startWeightRatio = levelData.startWeightRatio;
|
|
_screwTypeCount = levelData.screwTypeCount;
|
|
_pendingScrewCount = _screwCountForLevel;
|
|
|
|
if (levelData.panelCountRangePerLayer is { Length: > 1 })
|
|
{
|
|
_minItemsPerLayer = Mathf.Max(levelData.panelCountRangePerLayer[0], 0);
|
|
_maxItemsPerLayer = Mathf.Min(levelData.panelCountRangePerLayer[1] + 1, MaxItemsPerLayer);
|
|
}
|
|
else
|
|
{
|
|
_maxItemsPerLayer = 6;
|
|
_minItemsPerLayer = 3;
|
|
}
|
|
}
|
|
|
|
public int GetCurMaxLevel()
|
|
{
|
|
return _levelDataList.Count;
|
|
}
|
|
|
|
private RequestStageData _requestStageData;
|
|
private void InitLevel(int grade)
|
|
{
|
|
|
|
_requestStageData = new RequestStageData()
|
|
{
|
|
level = grade,
|
|
begin_time = (int)GameHelper.GetNowTime(),
|
|
item_costs = new[] { 0, 0, 0 },
|
|
|
|
};
|
|
|
|
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.OpenGameUI_Open);
|
|
GameDispatcher.Instance.Dispatch(GameMsg.RefreshItemCount);
|
|
_isLevelOver = false;
|
|
gameOver = false;
|
|
// _screwCountForLevel = Screws[grade];
|
|
var index = grade - 1;
|
|
index = index < _levelDataList.Count ? index : _levelDataList.Count - 1;
|
|
InitCurLevelData(index);
|
|
|
|
//获取舞台范围,后续生成对象使用
|
|
panel.GetComponent<RectTransform>().GetLocalCorners(_stageArea);
|
|
|
|
levelText.text = gameMode == 0 ? $"Level {grade}" : "Progress";
|
|
UpdateGameProgress(0);
|
|
|
|
ClearLevelData();
|
|
InitCacheHole();
|
|
|
|
GenerateScrews(_screwTypeCount);
|
|
StartCoroutine(GeneratePanelsEnumerator());
|
|
|
|
|
|
|
|
}
|
|
public float LevelProgress;
|
|
private void UpdateGameProgress(float progress, bool hasAnim = false)
|
|
{
|
|
if (_gameProgressTween != null && _gameProgressTween.IsActive())
|
|
{
|
|
_gameProgressTween.Kill();
|
|
}
|
|
if (_gameProgressTextTween != null && _gameProgressTextTween.IsActive())
|
|
{
|
|
_gameProgressTextTween.Kill();
|
|
}
|
|
|
|
if (_gameProgressSize == Vector2.zero)
|
|
{
|
|
_gameProgressSize = gameProgress.rectTransform.sizeDelta;
|
|
}
|
|
|
|
progress = Mathf.Clamp(progress, 0, 1);
|
|
LevelProgress = progress;
|
|
Debug.Log(progress);
|
|
var startNum = Mathf.RoundToInt(_lastProgress * 100);
|
|
var endNum = Mathf.RoundToInt(progress * 100);
|
|
if (hasAnim)
|
|
{
|
|
_gameProgressTween =
|
|
gameProgress.rectTransform.DOSizeDelta(
|
|
new Vector2(_gameProgressSize.x * progress, _gameProgressSize.y), ProgressAnimTime);
|
|
|
|
_gameProgressTextTween = DOTween.To(() => startNum, x => startNum = x, endNum, ProgressAnimTime)
|
|
.OnUpdate(() =>
|
|
{
|
|
gameProgressText.text = $"{startNum}%"; // 格式化为百分比显示
|
|
});
|
|
}
|
|
else
|
|
{
|
|
gameProgress.rectTransform.sizeDelta = new Vector2(_gameProgressSize.x * progress, _gameProgressSize.y);
|
|
gameProgressText.text = $"{endNum}%";
|
|
}
|
|
|
|
_lastProgress = progress;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清理关卡数据
|
|
/// </summary>
|
|
public void ClearLevelData()
|
|
{
|
|
|
|
if (PanelLayerDic == null)
|
|
{
|
|
PanelLayerDic = new Dictionary<int, List<PanelLogic>>(10);
|
|
}
|
|
else
|
|
{
|
|
foreach (var item in PanelLayerDic)
|
|
{
|
|
foreach (var panelLogic in item.Value)
|
|
{
|
|
PoolManager.Instance.ReturnObject(panelLogic.objectName, panelLogic);//把面板放回对象池
|
|
// Destroy(panelLogic.gameObject);
|
|
}
|
|
}
|
|
PanelLayerDic.Clear();
|
|
}
|
|
|
|
if (_lockPanelLayerList == null)
|
|
{
|
|
_lockPanelLayerList = new List<int>(5);
|
|
}
|
|
else
|
|
{
|
|
_lockPanelLayerList.Clear();
|
|
}
|
|
|
|
if (_screwsDataList == null)
|
|
{
|
|
_screwsDataList = new List<int>(_pendingScrewCount);
|
|
}
|
|
else
|
|
{
|
|
_screwsDataList.Clear();
|
|
}
|
|
|
|
if (_screwsBoxDataList == null)
|
|
{
|
|
_screwsBoxDataList = new Dictionary<int, int>(9);
|
|
}
|
|
else
|
|
{
|
|
_screwsBoxDataList.Clear();
|
|
}
|
|
|
|
|
|
if (_boxLayerDic == null)
|
|
{
|
|
_boxLayerDic = new Dictionary<int, List<BoxTypeLogic>>();
|
|
}
|
|
else
|
|
{
|
|
foreach (var item in _boxLayerDic)
|
|
{
|
|
foreach (var boxTypeLogic in item.Value)
|
|
{
|
|
PoolManager.Instance.ReturnObject(boxTypeLogic.objectName, boxTypeLogic);
|
|
// Destroy(boxTypeLogic.gameObject);
|
|
}
|
|
}
|
|
_boxLayerDic.Clear();
|
|
}
|
|
|
|
if (_activityBoxDic == null)
|
|
{
|
|
_activityBoxDic = new Dictionary<int, BoxTypeLogic>(4);
|
|
}
|
|
else
|
|
{
|
|
_activityBoxDic.Clear();
|
|
}
|
|
|
|
ClearHole();
|
|
|
|
if (_hideCacheScrewsLogics == null)
|
|
{
|
|
_hideCacheScrewsLogics = new List<ScrewsLogic>(10);
|
|
}
|
|
else
|
|
{
|
|
foreach (var screwsLogic in _hideCacheScrewsLogics)
|
|
{
|
|
PoolManager.Instance.ReturnObject(screwsLogic.objectName, screwsLogic);
|
|
// Destroy(screwsLogic.gameObject);
|
|
}
|
|
_hideCacheScrewsLogics.Clear();
|
|
}
|
|
|
|
if (_screwsTypeDic == null)
|
|
{
|
|
_screwsTypeDic = new Dictionary<int, int>();
|
|
}
|
|
else
|
|
{
|
|
_screwsTypeDic.Clear();
|
|
}
|
|
}
|
|
|
|
private void ClearHole()
|
|
{
|
|
foreach (var kongLogic in _kongLogics)
|
|
{
|
|
if (kongLogic.IsUsed())
|
|
{
|
|
kongLogic.RemoveScrews();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 加载舞台资源
|
|
/// </summary>
|
|
private void LoadResources()
|
|
{
|
|
if (_panelResList == null)
|
|
{
|
|
_panelResList = new List<PanelLogic>(20);
|
|
for (int i = 0; i < 20; i++)
|
|
{
|
|
GameObject go = (GameObject)Resources.Load("Prefab/Panel_" + (i + 1));
|
|
var panelLogic = go.GetComponent<PanelLogic>();
|
|
_panelResList.Add(panelLogic);
|
|
PoolManager.Instance.CreatePool($"Panel_{i + 1}", panelLogic, 1, true);
|
|
}
|
|
}
|
|
|
|
if (_screwsResList == null)
|
|
{
|
|
GameObject go = Resources.Load<GameObject>("Prefab/Screw");
|
|
var screwsLogic = go.GetComponent<ScrewsLogic>();
|
|
PoolManager.Instance.CreatePool($"Screw", screwsLogic, 50, true);
|
|
|
|
_screwsResList = new List<Sprite>(9);
|
|
for (int i = 0; i < 9; i++)
|
|
{
|
|
Sprite sp = Resources.Load<Sprite>("UI/ls/lsd" + (i + 1).ToString());
|
|
_screwsResList.Add(sp);
|
|
}
|
|
|
|
}
|
|
|
|
if (_screwsBoxResList == null)
|
|
{
|
|
_screwsBoxResList = new List<BoxTypeLogic>(9);
|
|
// for (int i = 0; i < 9; i++)
|
|
// {
|
|
// var go = (GameObject)Resources.Load("Prefab/box_" + (i + 1).ToString());
|
|
// var boxTypeLogic = go.GetComponent<BoxTypeLogic>();
|
|
// boxTypeLogic.boxType = i + 1;
|
|
// _screwsBoxResList.Add(boxTypeLogic);
|
|
// }
|
|
|
|
var go = (GameObject)Resources.Load("Prefab/Box_Base");
|
|
var boxTypeLogic = go.GetComponent<BoxTypeLogic>();
|
|
_screwsBoxResList.Add(boxTypeLogic);
|
|
|
|
PoolManager.Instance.CreatePool($"Box", boxTypeLogic, 10, true);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 初始化孔位
|
|
/// </summary>
|
|
private void InitCacheHole()
|
|
{
|
|
_curUnlockingHoleCount = DefaultUnlockingHoleCount;
|
|
|
|
for (int i = 0; i < _kongLogics.Count; i++)
|
|
{
|
|
_kongLogics[i].SetLockState(i >= _curUnlockingHoleCount);
|
|
}
|
|
}
|
|
|
|
private void GenerateScrews(int typeCount = -1)
|
|
{
|
|
int totalTypes = _screwsResList.Count;
|
|
// 计算基于每种至少3个时,最多能有多少种螺丝被使用
|
|
var maxPossibleTypes = _pendingScrewCount / ScrewsPerType;
|
|
if (typeCount > 0)
|
|
{
|
|
maxPossibleTypes = typeCount;
|
|
}
|
|
maxPossibleTypes = Mathf.Min(maxPossibleTypes, totalTypes); // 确保不超过总类型数
|
|
|
|
//打点数据
|
|
_requestStageData.item_type = maxPossibleTypes;
|
|
_requestStageData.total_item = _pendingScrewCount;
|
|
|
|
_screwBoxCount = _pendingScrewCount / ScrewsPerType;
|
|
_curScrewBoxCount = _screwBoxCount;
|
|
for (int i = 0; i < _screwBoxCount; i++)
|
|
{
|
|
var index = i % maxPossibleTypes;
|
|
for (int j = 0; j < ScrewsPerType; j++)
|
|
{
|
|
_screwsDataList.Add(index);
|
|
}
|
|
|
|
_screwsBoxDataList.TryAdd(index, 0);
|
|
|
|
_screwsBoxDataList[index]++;
|
|
}
|
|
|
|
ShuffleList(_screwsDataList);
|
|
GenerateScrewsBoxForLevel();
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 生成螺丝盒
|
|
/// </summary>
|
|
void GenerateScrewsBoxForLevel()
|
|
{
|
|
foreach (var data in _screwsBoxDataList)
|
|
{
|
|
_boxLayerDic.Add(data.Key, new List<BoxTypeLogic>());
|
|
for (int i = 0; i < data.Value; i++)
|
|
{
|
|
// GameObject go = Instantiate(_screwsBoxResList[data.Key].gameObject, boxStartPos, true);
|
|
// GameObject go = Instantiate(_screwsBoxResList[0].gameObject, boxStartPos, true);
|
|
var boxTypeLogic = PoolManager.Instance.GetObject<BoxTypeLogic>("Box");
|
|
boxTypeLogic.transform.SetParent(boxStartPos);
|
|
// boxTypeLogic.transform.position = boxStartPos.position;
|
|
boxTypeLogic.transform.localPosition = Vector3.zero;
|
|
boxTypeLogic.transform.localScale = new Vector3(1, 1, 1);
|
|
|
|
// var boxTypeLogic = go.GetComponent<BoxTypeLogic>();
|
|
boxTypeLogic.SetBoxType(data.Key);
|
|
boxTypeLogic.HideBoxCover();
|
|
_boxLayerDic[data.Key].Add(boxTypeLogic);
|
|
}
|
|
}
|
|
|
|
// RandomlyPlaceScrewBoxes();
|
|
}
|
|
|
|
private int GetAvailableCount()
|
|
{
|
|
var availableCount = 2;
|
|
|
|
if (GameHelper.GetPayBox1())
|
|
availableCount++;
|
|
if (GameHelper.GetPayBox2())
|
|
availableCount++;
|
|
|
|
return availableCount;
|
|
}
|
|
|
|
#region 新版随机方法
|
|
private float _startWeightRatio = 0.1f;
|
|
private List<KeyValuePair<int, int>> _screwTypeWeightList;
|
|
private Dictionary<int, float> _weightDict;
|
|
private int _weightSum;
|
|
|
|
|
|
public void AddScrewTypeRecord(int type, int num = 1)
|
|
{
|
|
if (_screwsTypeDic.TryGetValue(type, out var record))
|
|
{
|
|
_screwsTypeDic[type] = record + num;
|
|
}
|
|
else
|
|
{
|
|
_screwsTypeDic.Add(type, num);
|
|
}
|
|
|
|
UpdateBoxTypeWeightRatio();
|
|
}
|
|
|
|
public void RemoveScrewTypeRecord(int type, int num = 3)
|
|
{
|
|
if (_screwsTypeDic.TryGetValue(type, out var record))
|
|
{
|
|
record -= num;
|
|
if (record <= 0)
|
|
{
|
|
_screwsTypeDic.Remove(type);
|
|
}
|
|
else
|
|
{
|
|
_screwsTypeDic[type] = record;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("删除不存在的记录!!!");
|
|
}
|
|
|
|
UpdateBoxTypeWeightRatio();
|
|
}
|
|
|
|
private void UpdateBoxTypeWeightRatio()
|
|
{
|
|
_screwTypeWeightList = _screwsTypeDic.OrderByDescending(x => x.Value).ToList();
|
|
if (_screwTypeWeightList.Count <= 1)
|
|
{
|
|
return;
|
|
}
|
|
var lastRecord = _screwTypeWeightList[0];
|
|
var kinds = 1;
|
|
for (int i = 1; i < _screwTypeWeightList.Count; i++)
|
|
{
|
|
if (_screwTypeWeightList[i].Value > lastRecord.Value)
|
|
{
|
|
kinds++;
|
|
}
|
|
|
|
lastRecord = _screwTypeWeightList[i];
|
|
}
|
|
|
|
//确定权重比例
|
|
var weightRatio = (1.0f - _startWeightRatio) / kinds;
|
|
var curWeightRatio = _startWeightRatio;
|
|
lastRecord = _screwTypeWeightList[0];
|
|
_weightDict = new Dictionary<int, float>(_screwTypeWeightList.Count)
|
|
{
|
|
{lastRecord.Key, curWeightRatio},
|
|
};
|
|
for (int i = 1; i < _screwTypeWeightList.Count; i++)
|
|
{
|
|
if (_screwTypeWeightList[i].Value > lastRecord.Value)
|
|
{
|
|
curWeightRatio += weightRatio;
|
|
}
|
|
|
|
_weightDict.Add(_screwTypeWeightList[i].Key, curWeightRatio);
|
|
lastRecord = _screwTypeWeightList[i];
|
|
}
|
|
|
|
//计算根据权重比例折算后的实际权重
|
|
_weightSum = 0;
|
|
for (int i = 0; i < _screwTypeWeightList.Count; i++)
|
|
{
|
|
var record = _screwTypeWeightList[i];
|
|
_screwTypeWeightList[i] = new KeyValuePair<int, int>(record.Key, Mathf.Max((int)(record.Value * _weightDict[record.Key]), 1));
|
|
_weightSum += _screwTypeWeightList[i].Value;
|
|
}
|
|
}
|
|
|
|
private BoxTypeLogic RandomGetBoxTypeLogin(bool updateWeightRatio = false)
|
|
{
|
|
if (updateWeightRatio) UpdateBoxTypeWeightRatio();
|
|
|
|
var random = Random.Range(0, _weightSum);
|
|
var range = 0;
|
|
var index = 0;
|
|
for (int i = 0; i < _screwTypeWeightList.Count; i++)
|
|
{
|
|
var record = _screwTypeWeightList[i];
|
|
range += record.Value;
|
|
if (random < range)
|
|
{
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
return _boxLayerDic[_screwTypeWeightList[index].Key][0];
|
|
}
|
|
|
|
/// <summary>
|
|
/// 判断展示的螺丝盒中是否有相同类型的
|
|
/// </summary>
|
|
/// <param name="boxType"></param>
|
|
/// <returns></returns>
|
|
private bool HasSameTypeActiveScrewBox(int boxType)
|
|
{
|
|
if (_activityBoxDic == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
foreach (var boxTypeLogic in _activityBoxDic.Values)
|
|
{
|
|
if (boxTypeLogic.boxType == boxType)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private BoxTypeLogic GetMatchingBoxTypeLogic()
|
|
{
|
|
BoxTypeLogic boxLogic;
|
|
var count = 0;
|
|
var isError = false;
|
|
do
|
|
{
|
|
count++;
|
|
boxLogic = RandomGetBoxTypeLogin();
|
|
if (count >= 150)
|
|
{
|
|
Debug.LogError("随机异常");
|
|
isError = true;
|
|
}
|
|
} while (HasSameTypeActiveScrewBox(boxLogic.boxType));
|
|
|
|
if (isError)
|
|
{
|
|
boxLogic = null;
|
|
}
|
|
return boxLogic;
|
|
}
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// 随机排列螺丝盒
|
|
/// </summary>
|
|
private void RandomlyPlaceScrewBoxes(float intervalTime = 0.5f)
|
|
{
|
|
var availableCount = GetAvailableCount();
|
|
var delayTime = 0.05f;
|
|
var sequence = DOTween.Sequence();
|
|
var curBoxTypes = new List<int>(4);
|
|
|
|
if (_activityBoxDic != null)
|
|
{
|
|
var index = 0;
|
|
foreach (var activityScrewBox in _activityBoxDic.Values)
|
|
{
|
|
if (!curBoxTypes.Contains(activityScrewBox.boxType))
|
|
{
|
|
curBoxTypes.Add(activityScrewBox.boxType);
|
|
}
|
|
sequence.Join(activityScrewBox.transform.DOMove(boxStartPos.position, (index + 1) * 0.1f).SetDelay(index * delayTime));
|
|
|
|
index++;
|
|
}
|
|
}
|
|
|
|
_activityBoxDic?.Clear();
|
|
|
|
sequence.AppendInterval(intervalTime);
|
|
|
|
if (_boxLayerDic.Count > availableCount) //剩的盒子比位置多 开始走随机逻辑
|
|
{
|
|
availableCount = _boxLayerDic.Count < availableCount ? _boxLayerDic.Count : availableCount;
|
|
var posIndex = 0;
|
|
do
|
|
{
|
|
var boxLogic = RandomGetBoxTypeLogin();
|
|
if (HasSameTypeActiveScrewBox(boxLogic.boxType))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
_activityBoxDic?.Add(posIndex, boxLogic);
|
|
|
|
var boxAnim = boxLogic.ShowBoxAnim(_screwBoxShowPosList[posIndex].position);
|
|
if (availableCount == 1)
|
|
boxAnim.onComplete += ClearCache;
|
|
|
|
sequence.Join(boxAnim.SetDelay(posIndex * delayTime));
|
|
|
|
posIndex++;
|
|
availableCount--;
|
|
|
|
} while (availableCount > 0);
|
|
|
|
}
|
|
else //剩的盒子没有位置多
|
|
{
|
|
var keysIndex = 0;
|
|
var posIndex = 0;
|
|
for (int i = 0; i < _screwTypeWeightList.Count; i++)
|
|
{
|
|
var boxLogic = _boxLayerDic[_screwTypeWeightList[i].Key][keysIndex];
|
|
_activityBoxDic?.Add(posIndex, boxLogic);
|
|
|
|
var boxAnim = boxLogic.ShowBoxAnim(_screwBoxShowPosList[posIndex].position);
|
|
if (availableCount == 1)
|
|
boxAnim.onComplete += ClearCache;
|
|
sequence.Join(boxAnim.SetDelay(posIndex * delayTime));
|
|
posIndex++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 刷新新的box移动到指定位置
|
|
/// </summary>
|
|
private void SortBoxes(int index)
|
|
{
|
|
var availableCount = GetAvailableCount();
|
|
|
|
if (index < 0 && _activityBoxDic.Count < availableCount && _boxLayerDic.Count >= availableCount)
|
|
{
|
|
BoxTypeLogic boxLogic = GetMatchingBoxTypeLogic();
|
|
|
|
if (boxLogic != null)
|
|
{
|
|
for (int i = 0; i < availableCount; i++)
|
|
{
|
|
var hasContainsKey = _activityBoxDic.ContainsKey(i);
|
|
if (hasContainsKey && _activityBoxDic[i] != null)
|
|
continue;
|
|
|
|
if (hasContainsKey)
|
|
{
|
|
_activityBoxDic[i] = boxLogic;
|
|
}
|
|
else
|
|
{
|
|
_activityBoxDic.Add(i, boxLogic);
|
|
}
|
|
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (_activityBoxDic != null && _activityBoxDic.ContainsKey(index))
|
|
{
|
|
_sequence = DOTween.Sequence();
|
|
|
|
var boxTypeLogic = _activityBoxDic[index];
|
|
|
|
_sequence.Append(boxTypeLogic.ShowBoxAnim(_screwBoxShowPosList[index].position));
|
|
// _sequence.AppendInterval(0.1f);
|
|
_sequence.AppendCallback(ClearCache);
|
|
}
|
|
}
|
|
|
|
private const int MaxItemsPerLayer = 7;
|
|
private int _maxItemsPerLayer = 5;
|
|
private int _minItemsPerLayer = 1;
|
|
private int _screwTypeCount;
|
|
|
|
private int _curLayer;
|
|
private Dictionary<int, RectTransform> _layerRectTransforms;
|
|
IEnumerator GeneratePanelsEnumerator()
|
|
{
|
|
_curLayer = 100;
|
|
yield return -1;
|
|
|
|
var count = 0;
|
|
while (count < 5)
|
|
{
|
|
count++;
|
|
yield return GeneratePanelsForLayer(count > 3);
|
|
}
|
|
|
|
RandomlyPlaceScrewBoxes(2f);
|
|
yield return new WaitForSeconds(0.1f);
|
|
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.OpenGameUI_PlayAnim);
|
|
}
|
|
|
|
IEnumerator GenerateNewPanelLayer()
|
|
{
|
|
if (_lockPanelLayerList.Count > 0)
|
|
{
|
|
var top = _lockPanelLayerList[0];
|
|
foreach (var panelLogic in PanelLayerDic[top])
|
|
{
|
|
panelLogic.SetLock(false, true);
|
|
}
|
|
|
|
_lockPanelLayerList.Remove(top);
|
|
}
|
|
|
|
yield return new WaitForSeconds(1.5f);
|
|
yield return GeneratePanelsForLayer(true);
|
|
}
|
|
|
|
IEnumerator GeneratePanelsForLayer(bool isLock = false)
|
|
{
|
|
if (_pendingScrewCount <= 0)
|
|
{
|
|
yield break;
|
|
}
|
|
|
|
var layer = _curLayer;
|
|
var generatePanelCount = Random.Range(_minItemsPerLayer, _maxItemsPerLayer);
|
|
_curLayer--;
|
|
|
|
var layerList = new List<PanelLogic>();
|
|
var cycleCount = 0;
|
|
|
|
RectTransform rectTransform = GetRectTransformForLayer(layer);
|
|
rectTransform.SetAsFirstSibling();
|
|
|
|
List<int> screwList = new List<int>();
|
|
|
|
while (_pendingScrewCount > 0)
|
|
{
|
|
var newPolygon = RandomGeneratePanel(rectTransform);
|
|
|
|
//确定放置螺丝钉数量
|
|
var holeCount = newPolygon.GetHoleCount();
|
|
holeCount = Mathf.Min(holeCount, _pendingScrewCount);
|
|
|
|
screwList = _screwsDataList.GetRange(_screwCountForLevel - _pendingScrewCount, holeCount);
|
|
//放置螺丝钉
|
|
newPolygon.ShowHole(screwList);
|
|
newPolygon.SetStaticRigidbody();
|
|
|
|
//更新待布置螺丝钉的数量以及当前已布置索引
|
|
_pendingScrewCount -= holeCount;
|
|
|
|
int count = 0;
|
|
int totalIterations = 0; // 总循环计数器
|
|
|
|
var isSuccess = false;
|
|
do
|
|
{
|
|
UpdateRandomPos(newPolygon);
|
|
count++;
|
|
totalIterations++; // 增加总循环计数器
|
|
|
|
if (IsPanelPositionValid(newPolygon, layerList))
|
|
{
|
|
isSuccess = true;
|
|
break; // 如果panel在边界内,退出循环
|
|
}
|
|
} while (count < 100);
|
|
|
|
if (!isSuccess)
|
|
{
|
|
_pendingScrewCount += holeCount;
|
|
}
|
|
|
|
// 最后输出总循环次数的log
|
|
// Debug.LogError($"Total Iterations Completed: {totalIterations} 结果是 {isSuccess}");
|
|
|
|
if (isSuccess)
|
|
{
|
|
newPolygon.transform.localPosition = new Vector3(newPolygon.transform.localPosition.x, newPolygon.transform.localPosition.y, 0f);
|
|
newPolygon.AlignScrewsToRotation();
|
|
|
|
layerList.Add(newPolygon);
|
|
}
|
|
else
|
|
{
|
|
PoolManager.Instance.ReturnObject(newPolygon.objectName, newPolygon);// 放回对象池
|
|
// Destroy(newPolygon.gameObject); //TODO 后续优化放到缓存池,不要直接销毁
|
|
}
|
|
|
|
if (layerList.Count >= generatePanelCount || cycleCount > 20)
|
|
{
|
|
break;
|
|
}
|
|
|
|
cycleCount++;
|
|
}
|
|
|
|
EnsureLayerExists(layer);
|
|
PanelLayerDic[layer].AddRange(layerList);
|
|
yield return -1;
|
|
|
|
var layerRange = ConvertToLayerRange(layer);
|
|
// var curColor = panelTypeColors.Count - (layer % panelTypeColors.Count) - 1;
|
|
var curColor = layer % _panelTypeColors.Count;
|
|
var color = ChangeColor(curColor);
|
|
foreach (var panelLogic in layerList)
|
|
{
|
|
panelLogic.gameObject.layer = layerRange;
|
|
panelLogic.SetLayer(layer);
|
|
panelLogic.SetBackgroundColor(color);
|
|
panelLogic.SetLock(isLock, true);
|
|
#if UNITY_EDITOR
|
|
// panelLogic.SetLayerText(layerRange.ToString());
|
|
#endif
|
|
}
|
|
|
|
if (isLock)
|
|
{
|
|
_lockPanelLayerList.Add(layer);
|
|
}
|
|
|
|
_requestStageData.layer++;
|
|
// Debug.LogError($"目前还剩下{_pendingScrewCount}个螺丝没创建");
|
|
}
|
|
|
|
private int ConvertToLayerRange(int input)
|
|
{
|
|
var modValue = input % 19;
|
|
|
|
return 10 + modValue;
|
|
}
|
|
|
|
private PanelLogic RandomGeneratePanel(Transform parent = null)
|
|
{
|
|
var random = Random.Range(0, _panelResList.Count);
|
|
// var panelGameObject = _panelResList[random].GetComponent<PanelLogic>();
|
|
// if (!PoolManager.Instance.HasPool(panelGameObject.name))
|
|
// {
|
|
// PoolManager.Instance.CreatePool<PanelLogic>(panelGameObject.name, panelGameObject, 1);
|
|
// }
|
|
//
|
|
PanelLogic newPolygon = PoolManager.Instance.GetObject<PanelLogic>($"Panel_{random + 1}");
|
|
// PanelLogic newPolygon =
|
|
// Instantiate(_panelResList[random].gameObject, new Vector3(9999, 9999), Quaternion.identity)
|
|
// .GetComponent<PanelLogic>();
|
|
|
|
newPolygon.transform.SetParent(parent == null ? panel.transform : parent);
|
|
newPolygon.transform.localScale = new Vector3(1, 1, 1);
|
|
newPolygon.gameObject.layer = 0;
|
|
|
|
return newPolygon;
|
|
}
|
|
|
|
private RectTransform GetRectTransformForLayer(int layer)
|
|
{
|
|
_layerRectTransforms ??= new Dictionary<int, RectTransform>();
|
|
|
|
RectTransform rectTransform;
|
|
if (_layerRectTransforms.TryGetValue(layer, out var o))
|
|
{
|
|
rectTransform = o;
|
|
}
|
|
else
|
|
{
|
|
var go = new GameObject("Layer_" + layer);
|
|
rectTransform = go.AddComponent<RectTransform>();
|
|
go.transform.SetParent(panel.transform);
|
|
rectTransform.localScale = Vector3.one;
|
|
rectTransform.localPosition = Vector3.zero;
|
|
_layerRectTransforms.Add(layer, rectTransform);
|
|
}
|
|
|
|
return rectTransform;
|
|
}
|
|
|
|
public bool CheckOverlapWithExistingObjects(PanelLogic newPanelLogic, List<PanelLogic> existingPanelLogics)
|
|
{
|
|
return CheckOverlapWithExistingObjects(newPanelLogic.polygonCollider2D, existingPanelLogics);
|
|
}
|
|
public bool CheckOverlapWithExistingObjects(PolygonCollider2D polygonCollider2D, List<PanelLogic> existingPanelLogics)
|
|
{
|
|
bool canPlace = true;
|
|
|
|
foreach (var item in existingPanelLogics)
|
|
{
|
|
|
|
if (IsOverlapping(item.polygonCollider2D, polygonCollider2D))
|
|
{
|
|
canPlace = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return !canPlace;
|
|
|
|
}
|
|
|
|
// 确保层级在字典中存在
|
|
void EnsureLayerExists(int layer)
|
|
{
|
|
if (!PanelLayerDic.ContainsKey(layer))
|
|
{
|
|
PanelLayerDic.Add(layer, new List<PanelLogic>());
|
|
}
|
|
}
|
|
|
|
public void RemovePanelLogic(PanelLogic panelLogic)
|
|
{
|
|
var layer = panelLogic.GetLayer();
|
|
if (PanelLayerDic.TryGetValue(layer, out var panelLogics))
|
|
{
|
|
if (panelLogics.Contains(panelLogic))
|
|
{
|
|
panelLogics.Remove(panelLogic);
|
|
if (panelLogics.Count > 0) return;
|
|
|
|
PanelLayerDic.Remove(layer);
|
|
StartCoroutine(GenerateNewPanelLayer());
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("删除了不存在的面板,请检查!!!!");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("相关层已不存在,请检查!!!!");
|
|
}
|
|
}
|
|
|
|
private void UpdateRandomPos(PanelLogic panelLogic)
|
|
{
|
|
panelLogic.transform.localPosition = GetStageRandomPos(panelLogic.GetRectMaxEdge() * 0.55f);
|
|
// panelLogic.transform.position = GetStageRandomPos();
|
|
|
|
panelLogic.transform.rotation = Quaternion.Euler(0f, 0.0f, Random.Range(0, 360));
|
|
|
|
Physics2D.SyncTransforms();
|
|
}
|
|
|
|
private Vector3 GetStageRandomPos(float safeDistanceFromEdge = 0)
|
|
{
|
|
// Debug.LogError(safeDistanceFromEdge);
|
|
// safeDistanceFromEdge *= 0.01f;
|
|
Vector3 min = _stageArea[0];
|
|
Vector3 max = _stageArea[2];
|
|
|
|
|
|
float x = Random.Range(min.x + safeDistanceFromEdge, max.x - safeDistanceFromEdge);
|
|
float y = Random.Range(min.y + safeDistanceFromEdge, max.y - safeDistanceFromEdge);
|
|
// float x = Random.Range(min.x , max.x);
|
|
// float y = Random.Range(min.y , max.y);
|
|
|
|
return new Vector3(x, y, 0);
|
|
}
|
|
|
|
private bool IsPanelPositionValid(PanelLogic newPanelLogic, List<PanelLogic> existingPanelLogics)
|
|
{
|
|
// var polygonVertices = GetWorldPoints(newPanelLogic.polygonCollider2D);
|
|
|
|
// 获取矩形的最小和最大 X, Y 值
|
|
// Vector2 minCorner = _stageArea[0];
|
|
// Vector2 maxCorner = _stageArea[2];
|
|
|
|
// 检查多边形的所有顶点是否在矩形内
|
|
// foreach (Vector2 vertex in polygonVertices)
|
|
// {
|
|
// if (vertex.x < minCorner.x || vertex.x > maxCorner.x || vertex.y < minCorner.y || vertex.y > maxCorner.y)
|
|
// {
|
|
// return false; // 只要有一个顶点在矩形外部,立即返回 false
|
|
// }
|
|
// }
|
|
|
|
foreach (var item in existingPanelLogics)
|
|
{
|
|
|
|
if (IsOverlapping(item.polygonCollider2D, newPanelLogic.polygonCollider2D))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true; // 所有顶点都在矩形内部,返回 true
|
|
}
|
|
|
|
private void ShuffleList<T>(List<T> list)
|
|
{
|
|
int n = list.Count;
|
|
while (n > 1)
|
|
{
|
|
n--;
|
|
int k = Random.Range(0, n);
|
|
(list[k], list[n]) = (list[n], list[k]);
|
|
}
|
|
}
|
|
|
|
public Sprite GetScrewsSprite(int index)
|
|
{
|
|
return _screwsResList[index];
|
|
}
|
|
|
|
public BoxTypeLogic GetBoxTypeLogic(int t)
|
|
{
|
|
foreach (var boxTypeLogic in _activityBoxDic.Values)
|
|
{
|
|
if (boxTypeLogic.boxType == t)
|
|
{
|
|
return boxTypeLogic;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public KongLogic GetKongLogic()
|
|
{
|
|
foreach (var kongLogic in _kongLogics)
|
|
{
|
|
if (kongLogic.CanUse())
|
|
{
|
|
return kongLogic;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
public int GetIdleHoleCount()
|
|
{
|
|
var count = 0;
|
|
foreach (var kongLogic in _kongLogics)
|
|
{
|
|
if (kongLogic.CanUse())
|
|
{
|
|
count++;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 盒子满了
|
|
/// </summary>
|
|
/// <param name="boxTypeLogic"></param>
|
|
public void BoxIsFull(BoxTypeLogic boxTypeLogic)
|
|
{
|
|
//数据处理
|
|
_boxLayerDic[boxTypeLogic.boxType].Remove(boxTypeLogic);
|
|
if (_boxLayerDic[boxTypeLogic.boxType].Count == 0)
|
|
{
|
|
_boxLayerDic.Remove(boxTypeLogic.boxType);
|
|
}
|
|
_curScrewBoxCount--;
|
|
|
|
// RemoveScrewTypeRecord(boxTypeLogic.boxType);
|
|
|
|
var index = -1;
|
|
foreach (var item in _activityBoxDic)
|
|
{
|
|
if (item.Value == boxTypeLogic)
|
|
{
|
|
index = item.Key;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (index >= 0)
|
|
{
|
|
_activityBoxDic.Remove(index);
|
|
}
|
|
|
|
//表现
|
|
DOVirtual.DelayedCall(FlyScrewsAnimTime, () =>
|
|
{
|
|
AudioManager.Instance.PlayDynamicEffect(AudioConst.Bonus);
|
|
Debug.Log(_curScrewBoxCount);
|
|
UpdateGameProgress((float)(_screwBoxCount - _curScrewBoxCount) / _screwBoxCount, true);
|
|
boxTypeLogic.PlayBoxFull(() =>
|
|
{
|
|
//是否刷新布局
|
|
if (_curScrewBoxCount - _activityBoxDic.Count >= 0)
|
|
{
|
|
SortBoxes(index);
|
|
}
|
|
|
|
if (_curScrewBoxCount <= 0)
|
|
{
|
|
ClearHole();
|
|
OnGameVictory();
|
|
}
|
|
});
|
|
boxTypeLogic.transform.SetParent(boxDestroy);
|
|
|
|
GameDispatcher.Instance.Dispatch(GameMsg.RefreshLookAd);//盒子跳动
|
|
GameHelper.AddGameExp(3);
|
|
|
|
if (_curScrewBoxCount <= 0 || boxTypeLogic.IsCashBox()) return;
|
|
reward_data temp = new reward_data { start = boxTypeLogic.transform.localPosition };
|
|
GameDispatcher.Instance.Dispatch(GameMsg.FlyGold, temp);//飞钞票
|
|
});
|
|
|
|
//打点数据
|
|
_requestStageData.remove_item += 3;
|
|
|
|
if (_boxLayerDic.Count > _activityBoxDic.Count)
|
|
{
|
|
BoxTypeLogic boxLogic = GetMatchingBoxTypeLogic();
|
|
|
|
if (boxLogic != null)
|
|
{
|
|
_activityBoxDic.Add(index, boxLogic);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清理孔位缓冲区的螺丝到隐藏缓冲区
|
|
/// </summary>
|
|
private void CleanHoleCachePool()
|
|
{
|
|
foreach (var kongLogic in _kongLogics)
|
|
{
|
|
if (kongLogic.IsUsed())
|
|
{
|
|
var screwsLogic = kongLogic.PutScrew(true);
|
|
_hideCacheScrewsLogics.Add(screwsLogic);
|
|
screwsLogic.FlyToTarget(boxStartPos);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清理缓存区
|
|
/// </summary>
|
|
private void ClearCache()
|
|
{
|
|
if (gameOver)
|
|
{
|
|
return;
|
|
}
|
|
var needRemoveScrewsLogics = new List<ScrewsLogic>();
|
|
var temp = _activityBoxDic.Values.ToList();
|
|
foreach (var screwsLogic in _hideCacheScrewsLogics)
|
|
{
|
|
foreach (var activeScrewBox in temp)
|
|
{
|
|
if (screwsLogic.screwsType == activeScrewBox.boxType)
|
|
{
|
|
if (activeScrewBox.CanUseKong(screwsLogic))
|
|
{
|
|
needRemoveScrewsLogics.Add(screwsLogic);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (var screwsLogic in needRemoveScrewsLogics)
|
|
{
|
|
_hideCacheScrewsLogics.Remove(screwsLogic);
|
|
}
|
|
|
|
foreach (var kongLogic in _kongLogics)
|
|
{
|
|
foreach (var activeScrewBox in temp)
|
|
{
|
|
if (kongLogic.IsUsed() && kongLogic.IsSameType(activeScrewBox.boxType))
|
|
{
|
|
if (activeScrewBox.CanUseKong(kongLogic.PutScrew()))
|
|
{
|
|
kongLogic.PutScrew(true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 游戏失败
|
|
/// </summary>
|
|
public void OnGameFailed()
|
|
{
|
|
StartCoroutine(GameOverEnumerator(false));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 通关成功
|
|
/// </summary>
|
|
private void OnGameVictory()
|
|
{
|
|
StartCoroutine(GameOverEnumerator(true));
|
|
}
|
|
|
|
IEnumerator GameOverEnumerator(bool isVictory)
|
|
{
|
|
if (_isLevelOver) yield break;
|
|
_isLevelOver = true;
|
|
|
|
var cashArray = GameHelper.GetRewardValue(2);
|
|
|
|
|
|
var hasExistUI = UIManager.Instance.IsExistUI(UIConst.GetTaskRewardUI);
|
|
if (hasExistUI)
|
|
{
|
|
var ui = UIManager.Instance.GetDynamicUI(UIConst.GetTaskRewardUI);
|
|
ui.baseUI.sortingOrder = 100;
|
|
}
|
|
if (isVictory)
|
|
{
|
|
if (gameMode == GameHome.Mode_simple)
|
|
{
|
|
int level = GameHelper.GetLevel();
|
|
level++;
|
|
GameHelper.SetLevel(level);
|
|
}
|
|
|
|
var temp = new SettlementData { is_success = true, cash_number = cashArray[0], rate = GameHelper.IsGiftSwitch() ? cashArray[1] : 3, is_level_success = true, is_h5_reward = false };
|
|
|
|
yield return new WaitForSeconds(0.5f);
|
|
|
|
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.LevelSuccessUI_Open, temp);
|
|
}
|
|
else
|
|
{
|
|
if ((LevelProgress >= ((float)ConfigSystem.GetConfig<CommonModel>().FailedGiftProgress / 100)) && !is_resurgence)
|
|
//if (true && !is_resurgence)//zhushi
|
|
{
|
|
|
|
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.ResurgenceUI_Open, LevelProgress);
|
|
is_resurgence = true;
|
|
yield return null;
|
|
}
|
|
else
|
|
{
|
|
if (GameHelper.GetReviveCount() < 2)
|
|
{
|
|
yield return new WaitForSeconds(0.3f);
|
|
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.ReviveUI_Open);
|
|
|
|
}
|
|
else
|
|
{
|
|
var temp = new SettlementData { is_success = false, cash_number = cashArray[0], is_level_success = true, is_h5_reward = false };
|
|
yield return new WaitForSeconds(0.3f);
|
|
|
|
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.LevelSuccessUI_Open, temp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public bool is_resurgence = false;
|
|
public void TrackGameCompletion(bool isVictory)
|
|
{
|
|
_requestStageData.end_time = (int)GameHelper.GetNowTime();
|
|
_requestStageData.pass = isVictory;
|
|
|
|
var requestJson = SerializeUtil.ToJsonIndented(_requestStageData);
|
|
var reqData = new RequestResultData
|
|
{
|
|
type = 3,
|
|
result = requestJson
|
|
};
|
|
NetworkKit.PostWithHeader<object>("game/settleUp", reqData, (isSuccess, obj) =>
|
|
{
|
|
Debug.Log($"send log= {isSuccess}=========== {GameHelper.GetLoginModel().uid}");
|
|
});
|
|
|
|
_requestStageData = null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 显示toast
|
|
/// </summary>
|
|
/// <param name="message"></param>
|
|
public void ShowToast(string message)
|
|
{
|
|
Toast toast = ToastPool.Instance.GetFromPool();
|
|
toast.ShowToast(message, 3, 3);
|
|
}
|
|
|
|
/// <summary>
|
|
/// FGUI穿透触发UGUI临时解决方式
|
|
/// </summary>
|
|
/// <param name="sp"></param>
|
|
/// <param name="eventCamera"></param>
|
|
/// <returns></returns>
|
|
public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
|
|
{
|
|
var touchTarget = Stage.inst.touchTarget;
|
|
if (touchTarget is { _batchingBounds: not null })
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
private void OnPayBox1()
|
|
{
|
|
var temp = new PropViewData { type = 3, index = 1 };
|
|
DOVirtual.DelayedCall(0.2f, () =>
|
|
{
|
|
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.PropUI_Open, temp);
|
|
|
|
});
|
|
}
|
|
|
|
private void OnPayBox2()
|
|
{
|
|
var temp = new PropViewData { type = 3, index = 2 };
|
|
DOVirtual.DelayedCall(0.2f, () =>
|
|
{
|
|
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.PropUI_Open, temp);
|
|
|
|
});
|
|
}
|
|
public void OnSuccessPayBox1(int index)
|
|
{
|
|
// string boxName = "Box"+index+"_pay";
|
|
// TODO 临时修改2024年9月19日防止先解锁第四个盒子导致第三个盒子被遮挡相关问题
|
|
// var box = index == 1 ? Box1_pay : Box2_pay;
|
|
//
|
|
// Destroy(box);
|
|
//
|
|
// if (index == 1)
|
|
// GameHelper.SetPayBox1(true);
|
|
// else
|
|
// GameHelper.SetPayBox2(true);
|
|
if (!GameHelper.GetPayBox1())
|
|
{
|
|
GameHelper.SetPayBox1(true);
|
|
NetworkKit.BuriedPoint(BuriedPointEvent.Apple_pay_event, BuriedPointEvent.AddBoxPay + "_" + 1, 1);
|
|
}
|
|
else
|
|
{
|
|
GameHelper.SetPayBox2(true);
|
|
NetworkKit.BuriedPoint(BuriedPointEvent.Apple_pay_event, BuriedPointEvent.AddBoxPay + "_" + 2, 1);
|
|
}
|
|
UpdatePayBoxView();
|
|
|
|
SortBoxes(-1);
|
|
}
|
|
|
|
|
|
public void OnResurrect()
|
|
{
|
|
//FailPanel.SetActive(false);
|
|
//reward_data temp = new reward_data() {change = -10, type = 101 };
|
|
//UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.CoinWnd_newUI_Open, temp);
|
|
_isLevelOver = false;
|
|
gameOver = false;
|
|
GameDispatcher.Instance.Dispatch(GameMsg.Gold_refresh);
|
|
|
|
CleanHoleCachePool();
|
|
|
|
ClearCache();
|
|
}
|
|
|
|
//准备工作,第一个:需要确认第几关,然后是螺丝的数量,创建板子
|
|
public void InitLogic(int level)
|
|
{
|
|
// int level = GameHelper.GetLevel();
|
|
|
|
GameHelper.SetIsWatchAd(0);
|
|
GameHelper.RestartReviveCount();
|
|
UpdatePayBoxView();
|
|
|
|
// level = 1;
|
|
InitLevel(level);
|
|
}
|
|
|
|
private void UpdatePayBoxView()
|
|
{
|
|
var unlockBoxNum = GameHelper.GetPayBox1() ? 1 : 0;
|
|
unlockBoxNum = GameHelper.GetPayBox2() ? unlockBoxNum + 1 : unlockBoxNum;
|
|
if (unlockBoxNum > 0)
|
|
{
|
|
if (box1Pay != null)
|
|
{
|
|
Destroy(box1Pay);
|
|
box1Pay = null;
|
|
}
|
|
}
|
|
if (unlockBoxNum > 1)
|
|
{
|
|
if (box2Pay != null)
|
|
{
|
|
Destroy(box2Pay);
|
|
box2Pay = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool IsOverlapping(PolygonCollider2D collider1, PolygonCollider2D collider2)
|
|
{
|
|
// 检查 collider2 的点是否在 collider1 内
|
|
foreach (Vector2 point in collider2.points)
|
|
{
|
|
Vector2 worldPoint = collider2.transform.TransformPoint(point);
|
|
if (collider1.OverlapPoint(worldPoint))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// 反过来检查 collider1 的点是否在 collider2 内
|
|
foreach (Vector2 point in collider1.points)
|
|
{
|
|
Vector2 worldPoint = collider1.transform.TransformPoint(point);
|
|
if (collider2.OverlapPoint(worldPoint))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// 如果以上检测均未发现重叠,则认为不重叠
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
private Color ChangeColor(int colorLayer)
|
|
{
|
|
string color = _panelTypeColors[colorLayer];
|
|
|
|
ColorUtility.TryParseHtmlString(color, out var nowColor);
|
|
|
|
nowColor.a = 0.68f;
|
|
return nowColor;
|
|
}
|
|
|
|
private Vector2[] GetWorldPoints(PolygonCollider2D polygonCollider)
|
|
{
|
|
Vector2[] localPoints = polygonCollider.points;
|
|
Vector2[] worldPoints = new Vector2[localPoints.Length];
|
|
|
|
for (int i = 0; i < localPoints.Length; i++)
|
|
{
|
|
worldPoints[i] = polygonCollider.transform.TransformPoint(localPoints[i]);
|
|
}
|
|
|
|
return worldPoints;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 道具:添加一个孔
|
|
/// </summary>
|
|
private void OnAddHoleBtnClick()
|
|
{
|
|
if (_curUnlockingHoleCount >= MaxUnlockingHoleCount)
|
|
{
|
|
ShowToast("Already at the maximum value");
|
|
return;
|
|
}
|
|
|
|
int numbers = GameHelper.GetItemNumber(ItemEnum.AddHole);
|
|
if (numbers > 0)
|
|
{
|
|
GameHelper.SetItemNumber(ItemEnum.AddHole, numbers - 1);
|
|
_requestStageData.item_costs[0]++;
|
|
AddHoleLogic();
|
|
}
|
|
else
|
|
{
|
|
var temp = new PropViewData { type = 0, index = 0 };
|
|
DOVirtual.DelayedCall(0.2f, () =>
|
|
{
|
|
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.PropUI_Open, temp);
|
|
|
|
});
|
|
}
|
|
}
|
|
|
|
private void AddHoleLogic()
|
|
{
|
|
_kongLogics[_curUnlockingHoleCount].SetLockState(false);
|
|
_curUnlockingHoleCount++;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 道具:替换箱子
|
|
/// </summary>
|
|
private void OnMergeBoxBtnClick()
|
|
{
|
|
int numbers = GameHelper.GetItemNumber(ItemEnum.MergeBox);
|
|
if (numbers > 0)
|
|
{
|
|
GameHelper.SetItemNumber(ItemEnum.MergeBox, numbers - 1);
|
|
_requestStageData.item_costs[1]++;
|
|
MergeBoxLogic();
|
|
}
|
|
else
|
|
{
|
|
var temp = new PropViewData { type = 1, index = 0 };
|
|
DOVirtual.DelayedCall(0.2f, () =>
|
|
{
|
|
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.PropUI_Open, temp);
|
|
|
|
});
|
|
}
|
|
}
|
|
|
|
private void MergeBoxLogic()
|
|
{
|
|
AudioManager.Instance.PlayDynamicEffect(AudioConst.SwitchBox);
|
|
RandomlyPlaceScrewBoxes();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清除孔洞
|
|
/// </summary>
|
|
private void OnClearHoleBtnClick()
|
|
{
|
|
var noneUsedKong = true;
|
|
foreach (var kongLogic in _kongLogics)
|
|
{
|
|
if (!kongLogic.IsLock() && kongLogic.IsUsed())
|
|
{
|
|
noneUsedKong = false;
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
if (noneUsedKong)
|
|
{
|
|
ShowToast("No Holes to clean");
|
|
return;
|
|
}
|
|
|
|
int numbers = GameHelper.GetItemNumber(ItemEnum.ClearHole);
|
|
if (numbers > 0)
|
|
{
|
|
GameHelper.SetItemNumber(ItemEnum.ClearHole, numbers - 1);
|
|
_requestStageData.item_costs[2]++;
|
|
ClearHolesLogic(); //清除孔洞到看不见的缓冲区
|
|
}
|
|
else
|
|
{
|
|
var temp = new PropViewData { type = 2, index = 0 };
|
|
DOVirtual.DelayedCall(0.2f, () =>
|
|
{
|
|
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.PropUI_Open, temp);
|
|
});
|
|
}
|
|
}
|
|
public void ClearHoleBtnClick()
|
|
{
|
|
var noneUsedKong = true;
|
|
foreach (var kongLogic in _kongLogics)
|
|
{
|
|
if (!kongLogic.IsLock() && kongLogic.IsUsed())
|
|
{
|
|
noneUsedKong = false;
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
if (noneUsedKong)
|
|
{
|
|
ShowToast("No Holes to clean");
|
|
return;
|
|
}
|
|
|
|
_requestStageData.item_costs[2]++;
|
|
ClearHolesLogic(); //清除孔洞到看不见的缓冲区
|
|
|
|
}
|
|
|
|
|
|
private void ClearHolesLogic()
|
|
{
|
|
CleanHoleCachePool();
|
|
}
|
|
|
|
private void OnApplicationPause(bool pauseStatus)
|
|
{
|
|
var saveObject = SaveData.GetSaveobject();
|
|
|
|
if (pauseStatus)
|
|
{
|
|
if (_requestStageData == null)
|
|
{
|
|
return;
|
|
}
|
|
saveObject.StageData = _requestStageData;
|
|
}
|
|
else
|
|
{
|
|
saveObject.StageData = null;
|
|
}
|
|
|
|
SaveData.saveDataFunc();
|
|
}
|
|
} |