fix:1、速度加快减慢优化。2、关卡配置表优化。3、白天黑夜模式切换(部分)
This commit is contained in:
@@ -5,6 +5,8 @@ using System.Linq;
|
||||
using DG.Tweening;
|
||||
using FairyGUI;
|
||||
using FGUI.Arrow_game;
|
||||
using FGUI.Common_01;
|
||||
using IgnoreOPS;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ChillConnect
|
||||
@@ -26,11 +28,6 @@ namespace ChillConnect
|
||||
// 关卡总配置数据
|
||||
private LevelConfig _levelConfig;
|
||||
|
||||
// 全局固定参数
|
||||
private const float _pointSpacing = 60f; // 点位间距 60px
|
||||
private const float _moveSpeed = 120f; // 移动速度
|
||||
private List<ArrowConfig> allArrowList = new List<ArrowConfig>();
|
||||
|
||||
// 网格基础参数
|
||||
private readonly int gridColNum = 10;
|
||||
private readonly float pointSpace = 60f;
|
||||
@@ -181,6 +178,11 @@ namespace ChillConnect
|
||||
// ========= 编辑器模拟触摸(仅编辑模式生效) =========
|
||||
|
||||
// ========== 编辑器鼠标拖拽 ==========
|
||||
|
||||
// 初始化未完成,直接跳过拖拽
|
||||
if (!_initComplete)
|
||||
return;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
float moveThreshold = 1f; // 移动阈值,大于这个值才算有效拖动
|
||||
|
||||
@@ -283,6 +285,8 @@ namespace ChillConnect
|
||||
|
||||
protected override void OnOpenBefore(object args)
|
||||
{
|
||||
//加载配置
|
||||
InitAllLevelData();
|
||||
_viewContainer = ui.view_container;
|
||||
// 初始化FGUI模板
|
||||
_dotTemplate = (ArrorPoint)UIPackage.CreateObject("Arrow_game", "ArrorPoint");
|
||||
@@ -315,10 +319,35 @@ namespace ChillConnect
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 消息监听
|
||||
protected override void AddListener()
|
||||
{
|
||||
GameDispatcher.Instance.AddListener(GameMsg.reset_game, OnRestartGame);
|
||||
GameDispatcher.Instance.AddListener(GameMsg.Update102, SetTopCurr);
|
||||
GameDispatcher.Instance.AddListener(GameMsg.Update101, SetTopCurr);
|
||||
}
|
||||
|
||||
#region 页面初始化 & 关闭按钮
|
||||
protected override void RemoveListener()
|
||||
{
|
||||
GameDispatcher.Instance.RemoveListener(GameMsg.reset_game, OnRestartGame);
|
||||
GameDispatcher.Instance.RemoveListener(GameMsg.Update102, SetTopCurr);
|
||||
GameDispatcher.Instance.RemoveListener(GameMsg.Update101, SetTopCurr);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 页面初始化
|
||||
private bool _initComplete = false;
|
||||
private void InitView()
|
||||
{
|
||||
// 重置手势状态
|
||||
_isTwoFingerTouch = false;
|
||||
_isDraging = false;
|
||||
|
||||
SetModel();
|
||||
|
||||
ui.text_level.SetVar("lv", GameHelper.GetLevel().ToString()).FlushVars();
|
||||
|
||||
// 关闭按钮
|
||||
ui.btn_close.SetClick(() => { CtrlCloseUI(); });
|
||||
ui.btn_clear.SetClick(OnClickDeleteItem);
|
||||
@@ -337,30 +366,85 @@ namespace ChillConnect
|
||||
// 滑动条初始居中(对应 1.0 缩放)
|
||||
float initValue = GetSliderValueByScale(1f);
|
||||
_zoomSlider.value = initValue;
|
||||
// 容器初始居中
|
||||
float startX = (Screen.width - _viewContainer.width) * 0.5f;
|
||||
float startY = (Screen.height - _viewContainer.height) * 0.5f;
|
||||
_viewContainer.SetPosition(startX, startY,0);
|
||||
// 先兜底重置为默认锚点
|
||||
_viewContainer.pivot = new Vector2(0, 0);
|
||||
|
||||
// 重置手势状态
|
||||
_isTwoFingerTouch = false;
|
||||
_isDraging = false;
|
||||
if (_levelConfig == null)
|
||||
{
|
||||
_initComplete = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (_levelConfig == null) return;
|
||||
// 1. 绘制网格圆点
|
||||
// 第一步:绘制网格 → 内部会计算网格中心、修改pivot为网格中心
|
||||
DrawGridDots(_levelConfig);
|
||||
|
||||
allArrowList = _levelConfig.arrows;
|
||||
// ========== 核心:把网格中心钉在屏幕中心 ==========
|
||||
// _gridWorldCenter 是 DrawGridDots 里 CalculateGridCenter 算出的值
|
||||
float screenCenterX = Screen.width * 0.5f;
|
||||
float screenCenterY = Screen.height * 0.5f;
|
||||
|
||||
// 2. 初始化所有箭头 + 路径线条 + 标记网格占用
|
||||
// 计算容器需要移动多少,才能让网格中心正好对准屏幕中心
|
||||
float targetContainerX = screenCenterX - _gridWorldCenter.x;
|
||||
float targetContainerY = screenCenterY - _gridWorldCenter.y;
|
||||
|
||||
// 直接设置容器位置
|
||||
_viewContainer.SetPosition(targetContainerX, targetContainerY, 0);
|
||||
// ==================================================
|
||||
|
||||
foreach (var arrow in _levelConfig.arrows)
|
||||
{
|
||||
BuildArrowPath(arrow, _levelConfig);
|
||||
CreateArrowAndLines(arrow, _levelConfig);
|
||||
MarkArrowOccupiedCells(arrow, _levelConfig);
|
||||
}
|
||||
|
||||
_initComplete = true;
|
||||
|
||||
|
||||
SetTopCurr();
|
||||
|
||||
}
|
||||
|
||||
private void SetTopCurr(object a = null)
|
||||
{
|
||||
if (ui.com_money is com_money btnMoney)
|
||||
{
|
||||
btnMoney.text_gold.text = DataMgr.Ticket.Value.ToString("0.00");
|
||||
btnMoney.SetClick(PopMakeup);
|
||||
}
|
||||
}
|
||||
|
||||
private void PopMakeup()
|
||||
{
|
||||
var makeupTaskData = DataMgr.MakeupTaskHistory.Value.Last();
|
||||
var vo = ConfigSystem.GetConfig<MakeupModel>().GetData(makeupTaskData.tableId);
|
||||
if (vo == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
GameHelper.showGameUI = false;
|
||||
uiCtrlDispatcher.Dispatch(UICtrlMsg.MakeupConfirmUI_Open, makeupTaskData);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UI相关
|
||||
/// <summary>
|
||||
/// 切换模式 默认黑夜模式
|
||||
/// </summary>
|
||||
/// <param name="mod">true:白天 false:黑夜</param>
|
||||
private void SetModel(object mod = null)
|
||||
{
|
||||
int idx = 0;
|
||||
if (mod != null)
|
||||
{
|
||||
idx = (bool)mod? 1 : 0;
|
||||
}
|
||||
|
||||
ui.mode.selectedIndex = idx;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
private void InitGridBounds()
|
||||
@@ -428,7 +512,10 @@ namespace ChillConnect
|
||||
#region 配置加载
|
||||
private void LoadLevelConfig()
|
||||
{
|
||||
_levelConfig = JsonHelper.LoadLevel("level_1001.json");
|
||||
// _levelConfig = JsonHelper.LoadLevel("level_1001.json");
|
||||
// 示例:加载第1关 levelId=1001
|
||||
int currentLevelId = GameHelper.GetLevel();
|
||||
_levelConfig = LoadLevelById(currentLevelId);
|
||||
// 给 path 为空的箭头,设置默认方向
|
||||
foreach (var arrow in _levelConfig.arrows)
|
||||
{
|
||||
@@ -442,6 +529,38 @@ namespace ChillConnect
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从 all_levels.json 中按 levelId 读取指定关卡
|
||||
/// </summary>
|
||||
/// <param name="targetLevelId">目标关卡ID 如 1001</param>
|
||||
/// <returns>找到返回关卡数据,没找到返回null</returns>
|
||||
///
|
||||
private static AllLevelRoot _allLevelData;
|
||||
// 游戏启动时调用一次
|
||||
public static void InitAllLevelData()
|
||||
{
|
||||
string path = Path.Combine(Application.streamingAssetsPath, "all_levels.json");
|
||||
string json = File.ReadAllText(path);
|
||||
_allLevelData = JsonUtility.FromJson<AllLevelRoot>(json);
|
||||
}
|
||||
|
||||
public static LevelConfig LoadLevelById(int targetLevelId)
|
||||
{
|
||||
AllLevelRoot root = _allLevelData;
|
||||
if (root == null || root.levels == null) return null;
|
||||
|
||||
// 遍历查找对应关卡
|
||||
foreach (var lv in _allLevelData.levels)
|
||||
{
|
||||
if (lv.levelId == targetLevelId)
|
||||
{
|
||||
return lv;
|
||||
}
|
||||
}
|
||||
Debug.LogWarning($"未找到关卡ID: {targetLevelId}");
|
||||
return null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 【核心】网格坐标工具
|
||||
@@ -531,7 +650,6 @@ namespace ChillConnect
|
||||
SetViewPivotToGridCenter();
|
||||
}
|
||||
|
||||
/// <summary>计算网格整体世界中心(原有网格坐标不变)</summary>
|
||||
/// <summary>计算整个网格圆点区域的世界中心点</summary>
|
||||
private void CalculateGridCenter(LevelConfig cfg)
|
||||
{
|
||||
@@ -693,44 +811,28 @@ namespace ChillConnect
|
||||
CreateArrowOnly(arrow, pathPoints[pathPoints.Count - 1]);
|
||||
arrow.originalArrowPos = new Vector2(arrow.arrowObj.x, arrow.arrowObj.y);
|
||||
arrow.arrowTrackIndex = arrow.totalTrack.Count - 1;
|
||||
}
|
||||
|
||||
// 线条/箭头 统一点击回调
|
||||
private void OnPathClick(ArrowConfig clickArrow)
|
||||
{
|
||||
if (clickArrow.isMoving)
|
||||
{
|
||||
Debug.Log($"[arrow] {clickArrow.id}正在移动,请勿点击其他箭头");
|
||||
return;
|
||||
}
|
||||
|
||||
// 点击的是当前提示箭头,直接隐藏手指
|
||||
if (_currentTipArrow == clickArrow)
|
||||
{
|
||||
HideFingerTip();
|
||||
}
|
||||
|
||||
// ========= 删除模式:直接删除箭头,不走移动逻辑 =========
|
||||
if (_isDeleteMode)
|
||||
{
|
||||
DeleteArrowCompletely(clickArrow);
|
||||
return;
|
||||
}
|
||||
|
||||
// 在 CreateArrowAndLines 方法最后,补充这段初始化代码
|
||||
// ========== 新增:初始化距离偏移 ==========
|
||||
arrow.movedDistance = 0f;
|
||||
// 轨迹总长度 = (点数-1) * 点间距
|
||||
arrow.trackTotalLength = (arrow.totalTrack.Count - 1) * 10f;
|
||||
// 箭头初始在轨迹末端
|
||||
arrow.arrowInitOffset = arrow.trackTotalLength;
|
||||
|
||||
clickArrow.isMoving = true;
|
||||
bool hasBlock = CheckBlockByGrid(clickArrow);
|
||||
Debug.Log("[arrow] 点击箭头:" + clickArrow.id +$"hasBlock==={hasBlock}");
|
||||
if (hasBlock)
|
||||
// 每个线条的初始偏移 = 索引 * 点间距
|
||||
arrow.lineInitOffsets = new List<float>();
|
||||
for (int i = 0; i < arrow.lineUnits.Count; i++)
|
||||
{
|
||||
MoveThenReset(clickArrow);
|
||||
}
|
||||
else
|
||||
{
|
||||
MoveToDisappear(clickArrow);
|
||||
arrow.lineInitOffsets.Add(i * 10f);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region 道具
|
||||
#region 道具(删除和提示)
|
||||
/// <summary>点击删除道具,开启/关闭删除模式</summary>
|
||||
private void OnClickDeleteItem()
|
||||
{
|
||||
@@ -857,6 +959,43 @@ namespace ChillConnect
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region 点击 & 移动逻辑
|
||||
|
||||
// 线条/箭头 统一点击回调
|
||||
private void OnPathClick(ArrowConfig clickArrow)
|
||||
{
|
||||
if (clickArrow.isMoving)
|
||||
{
|
||||
Debug.Log($"[arrow] {clickArrow.id}正在移动,请勿点击其他箭头");
|
||||
return;
|
||||
}
|
||||
|
||||
// 点击的是当前提示箭头,直接隐藏手指
|
||||
if (_currentTipArrow == clickArrow)
|
||||
{
|
||||
HideFingerTip();
|
||||
}
|
||||
|
||||
// ========= 删除模式:直接删除箭头,不走移动逻辑 =========
|
||||
if (_isDeleteMode)
|
||||
{
|
||||
DeleteArrowCompletely(clickArrow);
|
||||
return;
|
||||
}
|
||||
|
||||
clickArrow.isMoving = true;
|
||||
bool hasBlock = CheckBlockByGrid(clickArrow);
|
||||
Debug.Log("[arrow] 点击箭头:" + clickArrow.id +$"hasBlock==={hasBlock}");
|
||||
if (hasBlock)
|
||||
{
|
||||
MoveThenReset(clickArrow);
|
||||
}
|
||||
else
|
||||
{
|
||||
MoveToDisappear(clickArrow);
|
||||
}
|
||||
}
|
||||
// 基于网格行列的阻挡检测
|
||||
private bool CheckBlockByGrid(ArrowConfig curArrow)
|
||||
{
|
||||
@@ -949,7 +1088,7 @@ namespace ChillConnect
|
||||
ShowResult(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isCollide;
|
||||
}
|
||||
@@ -1007,6 +1146,11 @@ namespace ChillConnect
|
||||
{
|
||||
ShowResult(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 消除每条线小概率触发
|
||||
DisappearLineGetReward();
|
||||
}
|
||||
// 8. 退出删除模式
|
||||
_isDeleteMode = false;
|
||||
Debug.Log("[arrow] 箭头已彻底删除");
|
||||
@@ -1041,106 +1185,71 @@ namespace ChillConnect
|
||||
arrow.arrowObj = arrowIns;
|
||||
arrow.isMoving = false;
|
||||
}
|
||||
|
||||
|
||||
// 移动后复位动画(回弹,不释放占用)
|
||||
private void MoveThenReset(ArrowConfig arrow)
|
||||
{
|
||||
RunCoroutine(MoveAndResetCoroutine(arrow));
|
||||
}
|
||||
|
||||
// 回弹速度单独配置,和移动速度分开
|
||||
private float _bounceSpeed = 180f;
|
||||
private IEnumerator MoveAndResetCoroutine(ArrowConfig arrow)
|
||||
{
|
||||
float frameDelay = 0.01f;
|
||||
int stepCount = 2;
|
||||
int moved = 0;
|
||||
int trackMaxIndex = arrow.totalTrack.Count - 1;
|
||||
arrow.movedDistance = 0f;
|
||||
arrow.finalMoveDir = GetFinalMoveDir(arrow);
|
||||
|
||||
// 向前移动的总距离(对应原逻辑2步=20px,可自行调整)
|
||||
float forwardTotal = 20f;
|
||||
float timer = 0f;
|
||||
float duration = forwardTotal / _bounceSpeed;
|
||||
|
||||
string dir;
|
||||
if (arrow.path != null && arrow.path.Count > 0)
|
||||
// 第一段:向前移动
|
||||
while (timer < duration)
|
||||
{
|
||||
dir = arrow.path[arrow.path.Count - 1];
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(arrow.defaultDir))
|
||||
{
|
||||
dir = arrow.defaultDir;
|
||||
}
|
||||
else
|
||||
{
|
||||
dir = "up";
|
||||
}
|
||||
arrow.finalMoveDir = dir;
|
||||
|
||||
while (moved < stepCount)
|
||||
{
|
||||
// 新增空对象防护
|
||||
if (arrow == null || arrow.arrowObj == null)
|
||||
{
|
||||
Debug.Log($"[arrow] MoveAndResetCoroutine arrow 为空, 协程结束");
|
||||
yield break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < arrow.lineUnits.Count; i++)
|
||||
{
|
||||
int curIdx = arrow.lineTrackIndex[i];
|
||||
if (curIdx < trackMaxIndex)
|
||||
{
|
||||
curIdx++;
|
||||
arrow.lineUnits[i].SetPosition(arrow.totalTrack[curIdx].x, arrow.totalTrack[curIdx].y, 0);
|
||||
arrow.lineTrackIndex[i] = curIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
float dx = 0, dy = 0;
|
||||
switch (arrow.finalMoveDir)
|
||||
{
|
||||
case "right": dx = 10; break;
|
||||
case "left": dx = -10; break;
|
||||
case "down": dy = 10; break;
|
||||
case "up": dy = -10; break;
|
||||
}
|
||||
arrow.lineUnits[i].x += dx;
|
||||
arrow.lineUnits[i].y += dy;
|
||||
}
|
||||
}
|
||||
|
||||
int arrowIdx = arrow.arrowTrackIndex;
|
||||
if (arrowIdx < trackMaxIndex)
|
||||
{
|
||||
arrowIdx++;
|
||||
arrow.arrowObj.SetPosition(arrow.totalTrack[arrowIdx].x, arrow.totalTrack[arrowIdx].y, 0);
|
||||
arrow.arrowTrackIndex = arrowIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
float dx = 0, dy = 0;
|
||||
switch (arrow.finalMoveDir)
|
||||
{
|
||||
case "right": dx = 10; break;
|
||||
case "left": dx = -10; break;
|
||||
case "down": dy = 10; break;
|
||||
case "up": dy = -10; break;
|
||||
}
|
||||
arrow.arrowObj.x += dx;
|
||||
arrow.arrowObj.y += dy;
|
||||
}
|
||||
|
||||
moved++;
|
||||
yield return new WaitForSeconds(frameDelay);
|
||||
if (arrow == null || arrow.arrowObj == null) yield break;
|
||||
|
||||
timer += Time.deltaTime;
|
||||
arrow.movedDistance = _bounceSpeed * timer;
|
||||
|
||||
UpdateAllElementsPosition(arrow);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// 复位位置
|
||||
// 第二段:回弹到初始位置
|
||||
timer = 0f;
|
||||
float startDis = arrow.movedDistance;
|
||||
while (timer < duration)
|
||||
{
|
||||
if (arrow == null || arrow.arrowObj == null) yield break;
|
||||
|
||||
timer += Time.deltaTime;
|
||||
float t = timer / duration;
|
||||
arrow.movedDistance = Mathf.Lerp(startDis, 0f, t);
|
||||
|
||||
UpdateAllElementsPosition(arrow);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// 强制复位到初始状态
|
||||
arrow.movedDistance = 0f;
|
||||
UpdateAllElementsPosition(arrow);
|
||||
arrow.isMoving = false;
|
||||
}
|
||||
|
||||
/// <summary>统一更新箭头+所有线条的位置</summary>
|
||||
private void UpdateAllElementsPosition(ArrowConfig arrow)
|
||||
{
|
||||
for (int i = 0; i < arrow.lineUnits.Count; i++)
|
||||
{
|
||||
arrow.lineUnits[i].SetPosition(arrow.originalLinePos[i].x, arrow.originalLinePos[i].y, 0);
|
||||
arrow.lineTrackIndex[i] = i;
|
||||
float curDist = arrow.lineInitOffsets[i] + arrow.movedDistance;
|
||||
Vector2 pos = GetPositionByDistance(arrow, curDist);
|
||||
arrow.lineUnits[i].SetPosition(pos.x, pos.y, 0);
|
||||
}
|
||||
if(arrow.arrowObj != null)
|
||||
{
|
||||
arrow.arrowObj.SetPosition(arrow.originalArrowPos.x, arrow.originalArrowPos.y, 0);
|
||||
}
|
||||
arrow.arrowTrackIndex = arrow.totalTrack.Count - 1;
|
||||
|
||||
arrow.isMoving = false;
|
||||
float arrowCurDist = arrow.arrowInitOffset + arrow.movedDistance;
|
||||
Vector2 arrowPos = GetPositionByDistance(arrow, arrowCurDist);
|
||||
arrow.arrowObj.SetPosition(arrowPos.x, arrowPos.y, 0);
|
||||
}
|
||||
|
||||
private void MoveToDisappear(ArrowConfig arrow)
|
||||
@@ -1148,136 +1257,49 @@ namespace ChillConnect
|
||||
RunCoroutine(MoveAndDisappearCoroutine(arrow));
|
||||
}
|
||||
|
||||
// 新增:统一移动速度(像素/秒),数值越大移动越快,可自由修改
|
||||
[SerializeField] private float _moveSpeed = 800f;
|
||||
|
||||
private IEnumerator MoveAndDisappearCoroutine(ArrowConfig arrow)
|
||||
{
|
||||
Debug.Log($"[arrow] arrow.totalTrack.Count =={arrow.totalTrack.Count}");
|
||||
float frameDelay = 0.01f;
|
||||
int trackMaxIndex = arrow.totalTrack != null ? arrow.totalTrack.Count - 1 : 0;
|
||||
|
||||
string dir;
|
||||
if (arrow.path != null && arrow.path.Count > 0)
|
||||
{
|
||||
dir = arrow.path[arrow.path.Count - 1];
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(arrow.defaultDir))
|
||||
{
|
||||
dir = arrow.defaultDir;
|
||||
}
|
||||
else
|
||||
{
|
||||
dir = "up";
|
||||
}
|
||||
arrow.finalMoveDir = dir;
|
||||
arrow.movedDistance = 0f;
|
||||
arrow.finalMoveDir = GetFinalMoveDir(arrow);
|
||||
|
||||
while (true)
|
||||
{
|
||||
// 兜底:对象已销毁,直接退出
|
||||
// 空对象兜底保护
|
||||
if (arrow == null || arrow.arrowObj == null)
|
||||
{
|
||||
Debug.Log($"arrow 为空, 协程结束");
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
// 线条移动
|
||||
// 每帧累计移动距离:速度 * 时间增量
|
||||
float deltaDis = _moveSpeed * Time.deltaTime;
|
||||
arrow.movedDistance += deltaDis;
|
||||
|
||||
// 更新所有线条位置
|
||||
for (int i = 0; i < arrow.lineUnits.Count; i++)
|
||||
{
|
||||
int curIdx = arrow.lineTrackIndex[i];
|
||||
if (curIdx < trackMaxIndex)
|
||||
{
|
||||
curIdx++;
|
||||
arrow.lineUnits[i].SetPosition(arrow.totalTrack[curIdx].x, arrow.totalTrack[curIdx].y, 0);
|
||||
arrow.lineTrackIndex[i] = curIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
float dx = 0, dy = 0;
|
||||
switch (arrow.finalMoveDir)
|
||||
{
|
||||
case "right": dx = 10; break;
|
||||
case "left": dx = -10; break;
|
||||
case "down": dy = 10; break;
|
||||
case "up": dy = -10; break;
|
||||
}
|
||||
arrow.lineUnits[i].x += dx;
|
||||
arrow.lineUnits[i].y += dy;
|
||||
}
|
||||
float curDist = arrow.lineInitOffsets[i] + arrow.movedDistance;
|
||||
Vector2 pos = GetPositionByDistance(arrow, curDist);
|
||||
arrow.lineUnits[i].SetPosition(pos.x, pos.y, 0);
|
||||
}
|
||||
|
||||
// 箭头移动
|
||||
int arrowIdx = arrow.arrowTrackIndex;
|
||||
if (arrowIdx < trackMaxIndex)
|
||||
{
|
||||
arrowIdx++;
|
||||
arrow.arrowObj.SetPosition(arrow.totalTrack[arrowIdx].x, arrow.totalTrack[arrowIdx].y, 0);
|
||||
arrow.arrowTrackIndex = arrowIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
float dx = 0, dy = 0;
|
||||
switch (arrow.finalMoveDir)
|
||||
{
|
||||
case "right": dx = 10; break;
|
||||
case "left": dx = -10; break;
|
||||
case "down": dy = 10; break;
|
||||
case "up": dy = -10; break;
|
||||
}
|
||||
arrow.arrowObj.x += dx;
|
||||
arrow.arrowObj.y += dy;
|
||||
}
|
||||
// 更新箭头位置
|
||||
float arrowCurDist = arrow.arrowInitOffset + arrow.movedDistance;
|
||||
Vector2 arrowPos = GetPositionByDistance(arrow, arrowCurDist);
|
||||
arrow.arrowObj.SetPosition(arrowPos.x, arrowPos.y, 0);
|
||||
|
||||
// ========= 边界判断:有线箭头取尾部轨迹,单点箭头取自身 =========
|
||||
// 直接取箭头实时坐标,不再使用totalTrack静态点位
|
||||
bool isOut = false;
|
||||
float checkX = 0;
|
||||
float checkY = 0;
|
||||
|
||||
// 线段从起点生成,第 0 个元素才是尾巴
|
||||
if (arrow.lineUnits != null && arrow.lineUnits.Count > 0)
|
||||
{
|
||||
var tailLine = arrow.lineUnits[0];
|
||||
checkX = tailLine.x;
|
||||
checkY = tailLine.y;
|
||||
}
|
||||
else if (arrow.arrowObj != null)
|
||||
{
|
||||
// 纯单点箭头,使用自身坐标
|
||||
checkX = arrow.arrowObj.x;
|
||||
checkY = arrow.arrowObj.y;
|
||||
}
|
||||
|
||||
Debug.Log($"[arrow] arrow.finalMoveDir =={arrow.finalMoveDir}");
|
||||
|
||||
switch (arrow.finalMoveDir)
|
||||
{
|
||||
case "right":
|
||||
Debug.Log($"[arrow] checkX={checkX} | gridRight={gridRight} | gridRight + outOffset={gridRight + outOffset}");
|
||||
if (checkX > gridRight + outOffset) isOut = true;
|
||||
break;
|
||||
case "left":
|
||||
Debug.Log($"[arrow] checkX={checkX} | gridLeft={gridLeft} | gridLeft - outOffset={gridLeft - outOffset}");
|
||||
if (checkX < gridLeft - outOffset) isOut = true;
|
||||
break;
|
||||
case "down":
|
||||
Debug.Log($"[arrow] checkY={checkY} | gridBottom={gridBottom} | gridBottom + outOffset={gridBottom + outOffset}");
|
||||
if (checkY > gridBottom + outOffset) isOut = true;
|
||||
break;
|
||||
case "up":
|
||||
Debug.Log($"[arrow] checkY={checkY} | gridTop={gridTop} | gridTop - outOffset={gridTop - outOffset}");
|
||||
if (checkY < gridTop - outOffset) isOut = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// ========= 超出边界:隐藏 + 计数 + 终止协程 =========
|
||||
Debug.Log($"[arrow] isOut =={isOut}");
|
||||
if (isOut)
|
||||
// 边界检测:以尾部线条为准(和原逻辑一致)
|
||||
Vector2 tailPos = GetPositionByDistance(arrow, arrow.movedDistance);
|
||||
if (CheckIsOutOfBounds(tailPos, arrow.finalMoveDir))
|
||||
{
|
||||
// ========== 以下销毁逻辑和原代码保持一致 ==========
|
||||
ReleaseArrowOccupied(arrow);
|
||||
|
||||
// 销毁线条
|
||||
foreach (var line in arrow.lineUnits)
|
||||
{
|
||||
if(line != null)
|
||||
if (line != null)
|
||||
{
|
||||
_viewContainer.RemoveChild(line);
|
||||
line.Dispose();
|
||||
@@ -1285,8 +1307,7 @@ namespace ChillConnect
|
||||
}
|
||||
arrow.lineUnits.Clear();
|
||||
|
||||
// 销毁箭头
|
||||
if(arrow.arrowObj != null)
|
||||
if (arrow.arrowObj != null)
|
||||
{
|
||||
_viewContainer.RemoveChild(arrow.arrowObj);
|
||||
arrow.arrowObj.Dispose();
|
||||
@@ -1294,79 +1315,142 @@ namespace ChillConnect
|
||||
}
|
||||
|
||||
arrow.isMoving = false;
|
||||
|
||||
_remainArrowCount--;
|
||||
|
||||
if (_remainArrowCount <= 0)
|
||||
{
|
||||
ShowResult(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
DisappearLineGetReward();
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(frameDelay);
|
||||
yield return null; // 每帧执行一次,平滑移动
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 点击 & 移动逻辑
|
||||
private void OnArrowClick(ArrowConfig arrow)
|
||||
|
||||
#region 移动工具方法
|
||||
/// <summary>根据距离,计算沿轨迹的实际坐标</summary>
|
||||
private Vector2 GetPositionByDistance(ArrowConfig arrow, float distance)
|
||||
{
|
||||
if (arrow.isMoving) return;
|
||||
arrow.isMoving = true;
|
||||
}
|
||||
int trackCount = arrow.totalTrack.Count;
|
||||
const float segmentLen = 10f; // 轨迹点固定间距
|
||||
|
||||
private void UpdateArrowMove(ArrowConfig arrow)
|
||||
{
|
||||
// 关键拦截:不允许移动 / 对象已销毁 → 直接退出
|
||||
if (!arrow.isMoving || arrow.arrowObj == null)
|
||||
return;
|
||||
|
||||
if (!arrow.isMoving) return;
|
||||
List<Vector2> path = arrow.pathPointList;
|
||||
|
||||
if (arrow.targetIndex < 0)
|
||||
// 距离在轨迹范围内:两点插值得到精确位置
|
||||
if (distance <= arrow.trackTotalLength)
|
||||
{
|
||||
arrow.isMoving = false;
|
||||
arrow.arrowObj.visible = false;
|
||||
foreach (var line in arrow.lineUnits) line.visible = false;
|
||||
return;
|
||||
}
|
||||
float indexFloat = distance / segmentLen;
|
||||
int index0 = Mathf.FloorToInt(indexFloat);
|
||||
int index1 = Mathf.Min(index0 + 1, trackCount - 1);
|
||||
float t = indexFloat - index0;
|
||||
|
||||
Vector2 targetPos = path[arrow.targetIndex];
|
||||
Vector2 curPos = new Vector2(arrow.arrowObj.x, arrow.arrowObj.y);
|
||||
float distance = Vector2.Distance(curPos, targetPos);
|
||||
|
||||
if (distance < 2f)
|
||||
{
|
||||
arrow.targetIndex--;
|
||||
Vector2 p0 = arrow.totalTrack[index0];
|
||||
Vector2 p1 = arrow.totalTrack[index1];
|
||||
return Vector2.Lerp(p0, p1, t);
|
||||
}
|
||||
// 距离超出轨迹:沿最终方向直线延伸
|
||||
else
|
||||
{
|
||||
Vector2 dir = (targetPos - curPos).normalized;
|
||||
Vector2 newPos = curPos + dir * _moveSpeed * Time.deltaTime;
|
||||
arrow.arrowObj.SetPosition(newPos.x, newPos.y, 0);
|
||||
float extraDis = distance - arrow.trackTotalLength;
|
||||
Vector2 endPos = arrow.totalTrack[trackCount - 1];
|
||||
Vector2 dir = DirToVector2(arrow.finalMoveDir);
|
||||
return endPos + dir * extraDis;
|
||||
}
|
||||
|
||||
RefreshLineVisible(arrow);
|
||||
}
|
||||
|
||||
private void RefreshLineVisible(ArrowConfig arrow)
|
||||
/// <summary>方向字符串转单位向量</summary>
|
||||
/// <summary>方向字符串转单位向量(适配 FGUI 坐标系:y 轴向下)</summary>
|
||||
private Vector2 DirToVector2(string dir)
|
||||
{
|
||||
int segIndex = 0;
|
||||
int totalSeg = arrow.pathPointList.Count - 1;
|
||||
|
||||
for (int s = 0; s < totalSeg; s++)
|
||||
return dir switch
|
||||
{
|
||||
bool isShow = s < arrow.targetIndex;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
arrow.lineUnits[segIndex + i].visible = isShow;
|
||||
}
|
||||
segIndex += 6;
|
||||
"up" => new Vector2(0, -1), // FGUI 向上 = y 减小
|
||||
"down" => new Vector2(0, 1), // FGUI 向下 = y 增大
|
||||
"left" => new Vector2(-1, 0),
|
||||
"right" => new Vector2(1, 0),
|
||||
_ => new Vector2(0, -1)
|
||||
};
|
||||
}
|
||||
/// <summary>统一获取箭头最终移动方向</summary>
|
||||
private string GetFinalMoveDir(ArrowConfig arrow)
|
||||
{
|
||||
if (arrow.path != null && arrow.path.Count > 0)
|
||||
return arrow.path[arrow.path.Count - 1];
|
||||
if (!string.IsNullOrEmpty(arrow.defaultDir))
|
||||
return arrow.defaultDir;
|
||||
return "up";
|
||||
}
|
||||
|
||||
/// <summary>统一边界检测</summary>
|
||||
private bool CheckIsOutOfBounds(Vector2 pos, string dir)
|
||||
{
|
||||
switch (dir)
|
||||
{
|
||||
case "right": return pos.x > gridRight + outOffset;
|
||||
case "left": return pos.x < gridLeft - outOffset;
|
||||
case "down": return pos.y > gridBottom + outOffset;
|
||||
case "up": return pos.y < gridTop - outOffset;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 消除每条线时概率获得奖励
|
||||
/// </summary>
|
||||
private void DisappearLineGetReward()
|
||||
{
|
||||
bool isGet = false;
|
||||
|
||||
int money_rate = ConfigSystem.GetConfig<CommonModel>().rewardrate;
|
||||
var randomNum = UnityEngine.Random.Range(0, 100);
|
||||
// Debug.Log($"[creat] money_rate------------ {randomNum}==={money_rate}");
|
||||
if (GameHelper.IsGiftSwitch() && randomNum < money_rate)
|
||||
{
|
||||
isGet = true;
|
||||
|
||||
// 显示大额奖励
|
||||
float[] cash_array = GameHelper.GetRewardValue(1);
|
||||
var temp = new SuccessData();
|
||||
temp.IsWin = true;
|
||||
temp.cash_number = cash_array[0];
|
||||
temp.rate = (int)cash_array[1];
|
||||
temp.IsLevelSuccess = false;
|
||||
temp.IsH5Reward = false;
|
||||
temp.boost_array = GameHelper.GetRewardBoost(1);
|
||||
DOVirtual.DelayedCall(0.55f, () =>
|
||||
{
|
||||
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.LevelSuccessUI_Open, temp);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (!isGet && Random.Range(0, 100) < ConfigSystem.GetConfig<CommonModel>().Smallrewardsrate)
|
||||
{
|
||||
var rewardData = new RewardData();
|
||||
Vector2 fguiPosition = new Vector2(ui.samll_point.x, ui.samll_point.y);
|
||||
var start = fguiPosition;
|
||||
var end = GameHelper.GetUICenterPosition(ui.com_money.GetChild("text_gold"));
|
||||
float[] cash_array = GameHelper.GetRewardValue(0);
|
||||
Debug.Log($"小额奖励:{cash_array[0]}");
|
||||
var rewardSingleData = new RewardSingleData(102, (decimal)cash_array[0], RewardOrigin.AdTask)
|
||||
{
|
||||
startPosition = start,
|
||||
endPosition = new Vector2(end.x - 135, end.y - 135)
|
||||
};
|
||||
|
||||
rewardData.AddReward(rewardSingleData);
|
||||
rewardData.displayType = RewardDisplayType.RewardFly | RewardDisplayType.ValueChange;
|
||||
GameDispatcher.Instance.Dispatch(GameMsg.GetReward, rewardData);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region 资源清理
|
||||
|
||||
@@ -1403,6 +1487,8 @@ namespace ChillConnect
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 结算
|
||||
|
||||
/// <summary>
|
||||
/// 弹出结算
|
||||
@@ -1454,10 +1540,15 @@ namespace ChillConnect
|
||||
}
|
||||
}
|
||||
|
||||
// 重新开始本局
|
||||
/// <summary>
|
||||
/// 重新开始本局
|
||||
/// </summary>
|
||||
/// <param name="a">true: 重生 false:重开一局或者下一局 </param>
|
||||
private void OnRestartGame(object a = null)
|
||||
{
|
||||
if (a!=null && (bool)a)
|
||||
|
||||
Debug.Log($"[ArrowGameUI] 重新开始本局 a:{(bool)a}");
|
||||
if (a != null && (bool)a)
|
||||
{
|
||||
_heartCount = 3;
|
||||
for (int i = _heartCount; i > 0; i--)
|
||||
@@ -1467,21 +1558,6 @@ namespace ChillConnect
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 恢复默认缩放 1.0
|
||||
float defaultScale = 1f;
|
||||
_viewContainer.scaleX = defaultScale;
|
||||
_viewContainer.scaleY = defaultScale;
|
||||
|
||||
// 2. 设置滑块对应位置
|
||||
_zoomSlider.value = GetSliderValueByScale(defaultScale);
|
||||
// 3. 容器屏幕居中
|
||||
float startX = (Screen.width - _viewContainer.width) * 0.5f;
|
||||
float startY = (Screen.height - _viewContainer.height) * 0.5f;
|
||||
_viewContainer.SetPosition(startX, startY,0);
|
||||
// 4. 清空手势状态
|
||||
_isTwoFingerTouch = false;
|
||||
_isDraging = false;
|
||||
|
||||
// 先清空当前所有动态物体
|
||||
ClearAllDynamicObj();
|
||||
// 重新走初始化流程
|
||||
@@ -1491,22 +1567,12 @@ namespace ChillConnect
|
||||
_collidedArrows.Clear();
|
||||
_remainArrowCount = _levelConfig.arrows.Count;
|
||||
DataMgr.ArrowResultLevel.Value = 1;
|
||||
|
||||
InitView();
|
||||
}
|
||||
|
||||
|
||||
#region 消息监听
|
||||
protected override void AddListener()
|
||||
{
|
||||
GameDispatcher.Instance.AddListener(GameMsg.reset_game, OnRestartGame);
|
||||
|
||||
}
|
||||
|
||||
protected override void RemoveListener()
|
||||
{
|
||||
GameDispatcher.Instance.RemoveListener(GameMsg.reset_game, OnRestartGame);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
|
||||
#region 配置解析 & 数据结构
|
||||
@@ -1547,12 +1613,23 @@ namespace ChillConnect
|
||||
public bool isMoving;
|
||||
public List<Vector2> originalLinePos;
|
||||
public Vector2 originalArrowPos;
|
||||
public int targetIndex;
|
||||
|
||||
public List<Vector2> totalTrack;
|
||||
public List<int> lineTrackIndex;
|
||||
public int arrowTrackIndex;
|
||||
public string finalMoveDir;
|
||||
|
||||
// ========== 新增:距离驱动移动所需字段 ==========
|
||||
public float movedDistance; // 当前整体累计移动距离
|
||||
public float trackTotalLength; // 整条轨迹的总像素长度
|
||||
public List<float> lineInitOffsets; // 每个线条单元的初始距离偏移
|
||||
public float arrowInitOffset; // 箭头的初始距离偏移
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class AllLevelRoot
|
||||
{
|
||||
public List<LevelConfig> levels;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@@ -216,26 +216,6 @@ namespace ChillConnect
|
||||
ui.text_award.text = DataMgr.Coin.Value.ToString();
|
||||
}
|
||||
ui.com_ch.btn_cash.title = GameHelper.getDesByKey("ch_out_1");
|
||||
// if (IsWin)
|
||||
// {
|
||||
// if (GameHelper.IsGiftSwitch()) ui.text_award.text = GameHelper.Get102Str((decimal)AwardNum);
|
||||
// else ui.text_award.text = ((int)AwardNum).ToString();
|
||||
|
||||
// var sk = FXManager.Instance.SetFx<SkeletonAnimation>(ui.bg_parent, Fx_Type.fx_win, ref closeCallback);
|
||||
// sk.state.SetAnimation(0, "out", true);
|
||||
|
||||
// var sk1 = FXManager.Instance.SetFx<SkeletonAnimation>(ui.bg_parent_title, Fx_Type.fx_win_title, ref closeCallback);
|
||||
// sk1.state.SetAnimation(0, "animation", false);
|
||||
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
|
||||
// if (GameHelper.IsGiftSwitch()) ui.text_award.text = GameHelper.Get102Str(DataMgr.Ticket.Value);
|
||||
// else ui.text_award.text = DataMgr.Coin.Value.ToString();
|
||||
// }
|
||||
|
||||
|
||||
|
||||
if (GameHelper.IsGiftSwitch())
|
||||
{
|
||||
@@ -343,6 +323,8 @@ namespace ChillConnect
|
||||
|
||||
DOVirtual.DelayedCall(0.7f, () =>
|
||||
{
|
||||
GameDispatcher.Instance.Dispatch(GameMsg.reset_game, false);
|
||||
|
||||
CtrlCloseUI();
|
||||
// if (IsLevelSuccess) UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.OpenGameUI_Open, true);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user