diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs index c81fe6f..5af4ff7 100644 --- a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs @@ -45,13 +45,15 @@ namespace Wpf_AiSportsMicrospace.Views private List circleTexts = new(); private List userList = new(); private List userNumberList = ["0", "0", "0", "0", "0", "0"]; - private double[] circlePositionsX = { 0.07, 0.21, 0.36, 0.50, 0.64, 0.78, 0.92 }; private Main _mainWin => Application.Current.MainWindow as Main; private List<(double XNorm, double YNorm)> circlePositions = new(); private MediaPlayer _mediaPlayer = new MediaPlayer(); private bool IsGameStarted = false; List _useName = ["一号位", "五号位", "二号位", "六号位", "三号位", "七号位",]; + + private readonly object _updateLock = new object(); + private readonly Dictionary _jumpStatus = new Dictionary(); public GroupJumpRope() { InitializeComponent(); @@ -345,83 +347,94 @@ namespace Wpf_AiSportsMicrospace.Views _firstHandTriggered = false; _lastCountdownSecond = 3; } - private Dictionary _lastJumpUpdateTime = new(); // 用于存储最后更新时间 - private Dictionary _lastUIUpdateTime = new(); // 用于防抖处理 - public Human LocateHuman(List humans, double frameWidth, double frameHeight, int circleIndex) + + private void UpdateCircleCounts(List humans) { - if (humans == null || humans.Count == 0) + lock (_updateLock) { - return null; - } + double radiusNormX = 0.07; + double radiusNormY = 0.07; - double circleX = circlePositions[circleIndex].XNorm; - double circleY = circlePositions[circleIndex].YNorm; - double radiusNormX = 0.07; - double radiusNormY = 0.14; - - Human inCircleHuman = null; - bool isOut = false; - - foreach (var hu in humans) - { - var rightFoot = hu.Keypoints.FirstOrDefault(k => k.Name == "right_ankle"); - var leftFoot = hu.Keypoints.FirstOrDefault(k => k.Name == "left_ankle"); - if (rightFoot == null || leftFoot == null) - continue; - - double xRightNorm = rightFoot.X / frameWidth; - double xLeftNorm = leftFoot.X / frameWidth; - double yRightNorm = rightFoot.Y / frameHeight; - double yLeftNorm = leftFoot.Y / frameHeight; - - bool outOfCircle = - xRightNorm < (circleX - radiusNormX) || xRightNorm > (circleX + radiusNormX) || - xLeftNorm < (circleX - radiusNormX) || xLeftNorm > (circleX + radiusNormX) || - yRightNorm < (circleY - radiusNormY) || yRightNorm > (circleY + radiusNormY) || - yLeftNorm < (circleY - radiusNormY) || yLeftNorm > (circleY + radiusNormY); - - if (outOfCircle) + for (int i = 0; i < circlePositions.Count; i++) { - isOut = true; - } - else if (inCircleHuman == null) - { - inCircleHuman = hu; - } - } + var circleX = circlePositions[i].XNorm; + var circleY = circlePositions[i].YNorm; - if (isOut) - userList[circleIndex].ImageState = "3"; - else - { - //if (userList[circleIndex].ImageState == "3") - //{ - // userList[circleIndex].ImageState = "1"; - //} - // 检查当前编号是否未变化超过 2 秒 - if (userNumberList[circleIndex] == userList[circleIndex].NumberText) - { - // 获取上次变化时间 - if (!_lastJumpUpdateTime.TryGetValue(circleIndex, out var lastTime)) - lastTime = DateTime.Now; // 默认当前时间 + Human humanInCircle = null; - var elapsed = (DateTime.Now - lastTime).TotalSeconds; - - if (elapsed > 1) + // 找圈内的人 + foreach (var hu in humans) { - userList[circleIndex].ImageState = "1"; - _lastJumpUpdateTime[circleIndex] = DateTime.Now; + var rightFoot = hu.Keypoints.FirstOrDefault(k => k.Name == "right_ankle"); + var leftFoot = hu.Keypoints.FirstOrDefault(k => k.Name == "left_ankle"); + if (rightFoot == null || leftFoot == null) + continue; + + double xRightNorm = rightFoot.X / userBox.ActualWidth; + double xLeftNorm = leftFoot.X / userBox.ActualWidth; + double yRightNorm = rightFoot.Y / userBox.ActualHeight; + double yLeftNorm = leftFoot.Y / userBox.ActualHeight; + + bool outOfCircle = + xRightNorm < (circleX - radiusNormX) || xRightNorm > (circleX + radiusNormX) || + xLeftNorm < (circleX - radiusNormX) || xLeftNorm > (circleX + radiusNormX) || + yRightNorm < (circleY - radiusNormY) || yRightNorm > (circleY + radiusNormY) || + yLeftNorm < (circleY - radiusNormY) || yLeftNorm > (circleY + radiusNormY); + + if (!outOfCircle) + { + humanInCircle = hu; + break; // 每圈只处理一个人 + } } - // 否则:2 秒内仍在变化,不更新状态 - } - else - { - // 编号发生变化,更新记录,并保持状态不变 - userNumberList[circleIndex] = userList[circleIndex].NumberText; - _lastJumpUpdateTime[circleIndex] = DateTime.Now; + + // 根据是否有人和跳绳数字判断状态 + bool hasHuman = humanInCircle != null; + userList[i].ImageState = GetJumpState(i, hasHuman); + + // 推送计数 + if (hasHuman) + sports[i].Pushing(humanInCircle); } } - return inCircleHuman; + } + + private string GetJumpState(int circleIndex, bool humanInCircle) + { + if (!humanInCircle) + { + // 无人 → 出圈 + return "3"; + } + + string currentNumber = userNumberList[circleIndex]; + + if (!_jumpStatus.ContainsKey(circleIndex)) + { + _jumpStatus[circleIndex] = (currentNumber, DateTime.Now, "1"); // 初始状态先为停止 + return "1"; + } + + var (lastNumber, lastChangeTime, lastState) = _jumpStatus[circleIndex]; + + //if (currentNumber != lastNumber) + //{ + // // 数字变化 → 跳绳中 + // _jumpStatus[circleIndex] = (currentNumber, DateTime.Now, "2"); + // return "2"; + //} + + // 数字未变化,判断是否超过 2 秒 + double elapsed = (DateTime.Now - lastChangeTime).TotalSeconds; + if (elapsed >= 3) + { + // 超过 2 秒未变化 → 停止 + _jumpStatus[circleIndex] = (currentNumber, lastChangeTime, "1"); + return "1"; + } + + // 维持上次状态 + return lastState; } private void DrawCirclesWithText() @@ -475,25 +488,6 @@ namespace Wpf_AiSportsMicrospace.Views sports.Add(sport); } } - private void UpdateCircleCounts(List humans) - { - // 在后台线程运行检测逻辑 - //Parallel.For(0, circlePositions.Count, i => - //{ - // var human = LocateHuman(humans, userBox.ActualWidth, userBox.ActualHeight, i); - // sports[i].Pushing(human); - //}); - - for (int i = 0; i < circlePositions.Count; i++) - { - var human = LocateHuman(humans, userBox.ActualWidth, userBox.ActualHeight, i); - if (human != null) - { - sports[i].Pushing(human); - } - } - } - /// /// 添加带渐变光的圆圈(中心红色,边缘蓝色) @@ -507,7 +501,7 @@ namespace Wpf_AiSportsMicrospace.Views userItem.VerticalAlignment = VerticalAlignment.Top; userItem.HorizontalAlignment = HorizontalAlignment.Left; userItem.ImageState = "1"; - userItem.Margin = new Thickness(centerX - (index == 0 ? 80 : index == 6 ? 190 : 135), centerY - 540, 0, 0); + userItem.Margin = new Thickness(centerX - 265, centerY - 500, 0, 0); userBox.Children.Add(userItem); userList.Add(userItem); return userItem; //