diff --git a/Assets/ChillConnect/FGUI/package/Arrow_game/Arrow_gameBinder.cs b/Assets/ChillConnect/FGUI/package/Arrow_game/Arrow_gameBinder.cs index 8d5a146..4de661d 100644 --- a/Assets/ChillConnect/FGUI/package/Arrow_game/Arrow_gameBinder.cs +++ b/Assets/ChillConnect/FGUI/package/Arrow_game/Arrow_gameBinder.cs @@ -14,6 +14,7 @@ namespace FGUI.Arrow_game UIObjectFactory.SetPackageItemExtension(ArrorPoint.URL, typeof(ArrorPoint)); UIObjectFactory.SetPackageItemExtension(HeartsPanel.URL, typeof(HeartsPanel)); UIObjectFactory.SetPackageItemExtension(com_finger.URL, typeof(com_finger)); + UIObjectFactory.SetPackageItemExtension(btn_big.URL, typeof(btn_big)); } } } \ No newline at end of file diff --git a/Assets/ChillConnect/FGUI/package/Arrow_game/btn_big.cs b/Assets/ChillConnect/FGUI/package/Arrow_game/btn_big.cs new file mode 100644 index 0000000..bed9772 --- /dev/null +++ b/Assets/ChillConnect/FGUI/package/Arrow_game/btn_big.cs @@ -0,0 +1,29 @@ +/** This is an automatically generated class by FairyGUI. Please do not modify it. **/ + +using FairyGUI; +using FairyGUI.Utils; + +namespace FGUI.Arrow_game +{ + public partial class btn_big : GButton + { + public Controller state; + public GImage bg; + public GTextField text; + public const string URL = "ui://sjl9teijrsd4g"; + + public static btn_big CreateInstance() + { + return (btn_big)UIPackage.CreateObject("Arrow_game", "btn_big"); + } + + public override void ConstructFromXML(XML xml) + { + base.ConstructFromXML(xml); + + state = GetControllerAt(0); + bg = (GImage)GetChildAt(0); + text = (GTextField)GetChildAt(1); + } + } +} \ No newline at end of file diff --git a/Assets/ChillConnect/FGUI/package/Arrow_game/btn_big.cs.meta b/Assets/ChillConnect/FGUI/package/Arrow_game/btn_big.cs.meta new file mode 100644 index 0000000..8a8d4b2 --- /dev/null +++ b/Assets/ChillConnect/FGUI/package/Arrow_game/btn_big.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: abd26fd11b29a084b93baa0d815ca0e4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ChillConnect/FGUI/package/Arrow_game/com_arrow_game.cs b/Assets/ChillConnect/FGUI/package/Arrow_game/com_arrow_game.cs index d9fee3c..d6c09c0 100644 --- a/Assets/ChillConnect/FGUI/package/Arrow_game/com_arrow_game.cs +++ b/Assets/ChillConnect/FGUI/package/Arrow_game/com_arrow_game.cs @@ -10,13 +10,15 @@ namespace FGUI.Arrow_game public GGraph bg; public GButton btn_menu; public GComponent view_container; - public ArrowEnd ArrowEnd; public ArrorPoint point; public GButton btn_close; public HeartsPanel HeartsPanel; public GButton btn_clear; public GButton btn_hint; public com_finger com_finger; + public btn_big btn_big; + public btn_big btn_small; + public GSlider zoomSlide; public const string URL = "ui://sjl9teijrsd40"; public static com_arrow_game CreateInstance() @@ -31,13 +33,15 @@ namespace FGUI.Arrow_game bg = (GGraph)GetChildAt(0); btn_menu = (GButton)GetChildAt(1); view_container = (GComponent)GetChildAt(2); - ArrowEnd = (ArrowEnd)GetChildAt(3); - point = (ArrorPoint)GetChildAt(4); - btn_close = (GButton)GetChildAt(6); - HeartsPanel = (HeartsPanel)GetChildAt(7); - btn_clear = (GButton)GetChildAt(9); - btn_hint = (GButton)GetChildAt(10); - com_finger = (com_finger)GetChildAt(11); + point = (ArrorPoint)GetChildAt(3); + btn_close = (GButton)GetChildAt(5); + HeartsPanel = (HeartsPanel)GetChildAt(6); + btn_clear = (GButton)GetChildAt(8); + btn_hint = (GButton)GetChildAt(9); + com_finger = (com_finger)GetChildAt(10); + btn_big = (btn_big)GetChildAt(11); + btn_small = (btn_big)GetChildAt(12); + zoomSlide = (GSlider)GetChildAt(13); } } } \ No newline at end of file diff --git a/Assets/Resources/ChillConnectAssets/FGUI/Arrow_game_atlas0.png b/Assets/Resources/ChillConnectAssets/FGUI/Arrow_game_atlas0.png index d17798f..1680222 100644 Binary files a/Assets/Resources/ChillConnectAssets/FGUI/Arrow_game_atlas0.png and b/Assets/Resources/ChillConnectAssets/FGUI/Arrow_game_atlas0.png differ diff --git a/Assets/Resources/ChillConnectAssets/FGUI/Arrow_game_fui.bytes b/Assets/Resources/ChillConnectAssets/FGUI/Arrow_game_fui.bytes index 1d028d0..c0b1654 100644 Binary files a/Assets/Resources/ChillConnectAssets/FGUI/Arrow_game_fui.bytes and b/Assets/Resources/ChillConnectAssets/FGUI/Arrow_game_fui.bytes differ diff --git a/Assets/Scripts/ModuleUI/ArrowGame/ArrowGameUI.cs b/Assets/Scripts/ModuleUI/ArrowGame/ArrowGameUI.cs index b611cf3..4f77b3f 100644 --- a/Assets/Scripts/ModuleUI/ArrowGame/ArrowGameUI.cs +++ b/Assets/Scripts/ModuleUI/ArrowGame/ArrowGameUI.cs @@ -1,6 +1,7 @@ using System.Collections; using System.Collections.Generic; using System.IO; +using System.Linq; using FairyGUI; using FGUI.Arrow_game; using UnityEngine; @@ -45,7 +46,6 @@ namespace ChillConnect private bool[,] _gridOccupied; // 记录每个箭头占用的所有网格点位(行,列) private Dictionary> _arrowOccupiedCells = new Dictionary>(); - // 爱心数量 private int _heartCount = 3; @@ -60,6 +60,30 @@ namespace ChillConnect // 是否开启删除道具模式 private bool _isDeleteMode = false; + // 手指提示图标 + private com_finger _fingerTipObj; + // 当前正在提示的箭头 + private ArrowConfig _currentTipArrow; + // 手指图标偏移(微调位置) + private readonly Vector2 _fingerOffset = new Vector2(-60, -60); + + + #region 缩放、拖拽、滑动条 全局变量 + // 缩放阈值(滑动条左右边界对应这两个值) + private readonly float _minScale = 0.6f; + private readonly float _maxScale = 1.5f; + // FGUI 滑动条组件 + private GSlider _zoomSlider; + // 双指缩放手势 + private float _lastTwoFingerDistance; + private bool _isTwoFingerTouch; + // 单指拖拽平移 + private Vector2 _lastTouchPos; + private bool _isDraging; + // 拖拽边界留边(防止完全移出屏幕) + private readonly float _dragBorder = 100f; + #endregion + public ArrowGameUI(ArrowGameUICtrl ctrl) : base(ctrl) { uiName = UIConst.ArrowGameUI; @@ -105,6 +129,8 @@ namespace ChillConnect // 销毁所有动态FGUI对象 ClearAllDynamicObj(); + + HideFingerTip(); // 释放模板资源 if (_dotTemplate != null) _dotTemplate.Dispose(); @@ -119,6 +145,7 @@ namespace ChillConnect // 清空网格占用数据 _gridOccupied = null; _arrowOccupiedCells.Clear(); + } protected override void OnBind() @@ -133,6 +160,67 @@ namespace ChillConnect { UpdateArrowMove(arrow); } + + // ========= 双指 = 缩放(优先级最高) ========= + if (Input.touchCount == 2) + { + _isDraging = false; + Touch t0 = Input.GetTouch(0); + Touch t1 = Input.GetTouch(1); + float currentDis = Vector2.Distance(t0.position, t1.position); + + if (!_isTwoFingerTouch) + { + _lastTwoFingerDistance = currentDis; + _isTwoFingerTouch = true; + } + else + { + float delta = currentDis - _lastTwoFingerDistance; + float curScale = _viewContainer.scaleX; + // 缩放灵敏度,按需微调 + curScale += delta * 0.001f; + curScale = Mathf.Clamp(curScale, _minScale, _maxScale); + + // 应用缩放 + _viewContainer.scaleX = curScale; + _viewContainer.scaleY = curScale; + + // 关键:双指缩放后,同步更新滑动条位置 + _zoomSlider.value = GetSliderValueByScale(curScale); + + _lastTwoFingerDistance = currentDis; + } + } + // ========= 单指 = 拖拽平移 ========= + else if (Input.touchCount == 1) + { + Touch touch = Input.GetTouch(0); + Vector2 curTouchPos = touch.position; + + if (touch.phase == TouchPhase.Began) + { + _lastTouchPos = curTouchPos; + _isDraging = true; + _isTwoFingerTouch = false; + } + else if (touch.phase == TouchPhase.Moved && _isDraging) + { + Vector2 offset = curTouchPos - _lastTouchPos; + MoveContainer(offset); + _lastTouchPos = curTouchPos; + } + else if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled) + { + _isDraging = false; + } + } + // 无触摸,重置状态 + else + { + _isTwoFingerTouch = false; + _isDraging = false; + } } protected override void OnOpenBefore(object args) @@ -176,10 +264,31 @@ namespace ChillConnect // 关闭按钮 ui.btn_close.SetClick(() => { CtrlCloseUI(); }); ui.btn_clear.SetClick(OnClickDeleteItem); + ui.btn_hint.SetClick(OnClickHint); + _fingerTipObj = com_finger.CreateInstance(); + _viewContainer.AddChild(_fingerTipObj); + _currentTipArrow = null; + _zoomSlider = ui.zoomSlide; + // 2. 绑定滑动条拖动回调 + _zoomSlider.onChanged.Add(OnZoomSliderChange); + // 3. 容器初始缩放、位置 + _viewContainer.scaleX = 1f; + _viewContainer.scaleY = 1f; + // 滑动条初始居中(对应 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); + // 重置手势状态 + _isTwoFingerTouch = false; + _isDraging = false; + + if (_levelConfig == null) return; - // 1. 绘制网格圆点 DrawGridDots(_levelConfig); @@ -499,6 +608,12 @@ namespace ChillConnect return; } + // 点击的是当前提示箭头,直接隐藏手指 + if (_currentTipArrow == clickArrow) + { + HideFingerTip(); + } + // ========= 删除模式:直接删除箭头,不走移动逻辑 ========= if (_isDeleteMode) { @@ -519,8 +634,9 @@ namespace ChillConnect } } + #region 道具 /// 点击删除道具,开启/关闭删除模式 - public void OnClickDeleteItem() + private void OnClickDeleteItem() { _isDeleteMode = !_isDeleteMode; @@ -535,7 +651,106 @@ namespace ChillConnect Debug.Log("已关闭删除模式"); } } + + private void OnClickHint() + { + ShowRandomArrowTip(); + } + + /// 随机选中有效箭头,显示静态手指提示(不跟随移动) + private void ShowRandomArrowTip() + { + // 先隐藏上一次提示 + HideFingerTip(); + if (_levelConfig == null || _levelConfig.arrows == null || _levelConfig.arrows.Count == 0) + { + Debug.Log("暂无可提示的箭头"); + return; + } + + // 筛选有效箭头 + List validArrows = _levelConfig.arrows + .Where(arrow => arrow != null && arrow.arrowObj != null) + .ToList(); + + if (validArrows.Count == 0) + { + Debug.Log("没有有效箭头可提示"); + return; + } + + // 随机选一个 + int randomIndex = Random.Range(0, validArrows.Count); + _currentTipArrow = validArrows[randomIndex]; + + // 设置手指位置(仅初始化一次,不再刷新) + float x = _currentTipArrow.arrowObj.x + _fingerOffset.x; + float y = _currentTipArrow.arrowObj.y + _fingerOffset.y; + _fingerTipObj.SetPosition(x, y, 0); + _fingerTipObj.visible = true; + } + + /// 隐藏手指提示并清空标记 + private void HideFingerTip() + { + if (_fingerTipObj != null) + { + _fingerTipObj.visible = false; + } + _currentTipArrow = null; + } + #endregion + + + #region 缩放 + + /// 根据缩放值,计算滑动条 value(0~1) + private float GetSliderValueByScale(float scale) + { + float t = (scale - _minScale) / (_maxScale - _minScale); + return Mathf.Clamp01(t); + } + + /// 根据滑动条 value(0~1),计算实际缩放值 + private float GetScaleBySliderValue(float sliderValue) + { + float scale = _minScale + sliderValue * (_maxScale - _minScale); + return Mathf.Clamp(scale, _minScale, _maxScale); + } + + /// 滑动条数值变化回调 + private void OnZoomSliderChange() + { + float scale = GetScaleBySliderValue((float)_zoomSlider.value); + _viewContainer.scaleX = scale; + _viewContainer.scaleY = scale; + } + + /// 移动容器 + 边界限制,防止完全拖出屏幕 + private void MoveContainer(Vector2 offset) + { + float newX = _viewContainer.x + offset.x; + float newY = _viewContainer.y + offset.y; + + float viewW = _viewContainer.width * _viewContainer.scaleX; + float viewH = _viewContainer.height * _viewContainer.scaleY; + + // 左右边界 + float minX = -viewW + _dragBorder; + float maxX = Screen.width - _dragBorder; + newX = Mathf.Clamp(newX, minX, maxX); + + // 上下边界 + float minY = -viewH + _dragBorder; + float maxY = Screen.height - _dragBorder; + newY = Mathf.Clamp(newY, minY, maxY); + + _viewContainer.SetPosition(newX, newY,0); + } + + #endregion + // 基于网格行列的阻挡检测 private bool CheckBlockByGrid(ArrowConfig curArrow) { @@ -637,7 +852,13 @@ namespace ChillConnect private void DeleteArrowCompletely(ArrowConfig arrow) { if (arrow == null) return; - + + // 被删除的是提示箭头,隐藏手指 + if (_currentTipArrow == arrow) + { + HideFingerTip(); + } + // 1. 停止移动标记,拦截Update和协程 arrow.isMoving = false; @@ -1105,6 +1326,19 @@ namespace ChillConnect return; } + // 1. 恢复默认缩放 1倍 + _viewContainer.scaleX = 1f; + _viewContainer.scaleY = 1f; + // 2. 滑动条回归对应位置 + _zoomSlider.value = GetSliderValueByScale(1f); + // 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(); // 重新走初始化流程