diff --git a/Wpf_AiSportsMicrospace/Optimizes.cs b/Wpf_AiSportsMicrospace/Optimizes.cs
deleted file mode 100644
index 1f335a7..0000000
--- a/Wpf_AiSportsMicrospace/Optimizes.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using Newtonsoft.Json;
-using Yztob.AiSports.Postures.Sports;
-using Yztob.AiSports.Postures.Things;
-
-namespace Wpf_AiSportsMicrospace
-{
- public class Optimizes
- {
- ///
- /// 执行运动微调
- ///
- /// 要微调的运动
- public static void Optimizeing(SportBase sport)
- {
- if (sport == null)
- throw new ArgumentNullException(nameof(sport));
-
- //获取运动的检测规则,如果使用的是规则检测时提供
- Console.WriteLine(JsonConvert.SerializeObject(sport.Rules));
- //获取运动的检测动作样本姿态,如果使用的是相似度时提供
- Console.WriteLine(JsonConvert.SerializeObject(sport.Samples));
-
- switch (sport.Key)
- {
- case "squat":
- var loggicRule = sport.Rules["squat"] as CalcLogicAndRule;
- //删除手部姿态检查规则
- loggicRule.Rules.RemoveAt(2);
- loggicRule.Rules.RemoveAt(1);
- break;
- }
- }
- }
-}
diff --git a/Wpf_AiSportsMicrospace/Views/Home.xaml.cs b/Wpf_AiSportsMicrospace/Views/Home.xaml.cs
index 7d451d3..a6ea386 100644
--- a/Wpf_AiSportsMicrospace/Views/Home.xaml.cs
+++ b/Wpf_AiSportsMicrospace/Views/Home.xaml.cs
@@ -20,6 +20,7 @@ using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Threading;
+using Views.JumpingJack;
using Views.JumpLong;
using Views.JumpRope;
using Views.SquatFu;
@@ -169,7 +170,7 @@ namespace Wpf_AiSportsMicrospace
//var newPage = new GroupJumpRope();
//mainWin?.SwitchPageWithMaskAnimation(newPage, true);
- var newPage = new WhackAMole();
+ var newPage = new BambooDragonfly();
mainWin?.SwitchPageWithMaskAnimation(newPage, true);
}
else if (coverFlow.SelectedIndex == 1)
diff --git a/Wpf_AiSportsMicrospace/Views/JumpingJack/BambooDragonfly.xaml b/Wpf_AiSportsMicrospace/Views/JumpingJack/BambooDragonfly.xaml
index 61892ca..7d680a0 100644
--- a/Wpf_AiSportsMicrospace/Views/JumpingJack/BambooDragonfly.xaml
+++ b/Wpf_AiSportsMicrospace/Views/JumpingJack/BambooDragonfly.xaml
@@ -1,12 +1,162 @@
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:local="clr-namespace:Wpf_AiSportsMicrospace.MyUserControl"
+ xmlns:gif="http://wpfanimatedgif.codeplex.com"
+ mc:Ignorable="d" Height="1080" Width="1920" Loaded="UserControl_Loaded" Unloaded="UserControl_Unloaded">
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Wpf_AiSportsMicrospace/Views/JumpingJack/BambooDragonfly.xaml.cs b/Wpf_AiSportsMicrospace/Views/JumpingJack/BambooDragonfly.xaml.cs
index 01e8068..5af73be 100644
--- a/Wpf_AiSportsMicrospace/Views/JumpingJack/BambooDragonfly.xaml.cs
+++ b/Wpf_AiSportsMicrospace/Views/JumpingJack/BambooDragonfly.xaml.cs
@@ -1,5 +1,14 @@
-using System;
+using AiSportsMicrospaceDB.DBContext;
+using Dto;
+using Enum;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using SportExpand;
+using System;
using System.Collections.Generic;
+using System.ComponentModel;
+using System.IO;
+using System.Runtime.CompilerServices;
using System.Text;
using System.Windows;
using System.Windows.Controls;
@@ -7,9 +16,18 @@ using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
+using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
+using Wpf_AiSportsMicrospace;
+using Wpf_AiSportsMicrospace.Common;
+using Wpf_AiSportsMicrospace.Enum;
+using Wpf_AiSportsMicrospace.MyUserControl;
+using Wpf_AiSportsMicrospace.Views;
+using Yztob.AiSports.Inferences.Things;
+using Yztob.AiSports.Postures.Sports;
+using Yztob.AiSports.Sensors.Things;
namespace Views.JumpingJack
{
@@ -18,9 +36,702 @@ namespace Views.JumpingJack
///
public partial class BambooDragonfly : UserControl
{
+ private Main _mainWin => Application.Current.MainWindow as Main;
+ private MediaPlayer _mediaPlayer = new MediaPlayer();
+ List RankingItemList = new();
+
+ public event PropertyChangedEventHandler PropertyChanged;
+ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+ private GameState _currentGameState = GameState.NotStarted;
+ private readonly object _updateLock = new object();
+ private readonly Dictionary _jumpStatus = new Dictionary();
+ private GroupJumpRopeContext _groupJumpRopeContext;
+
public BambooDragonfly()
{
InitializeComponent();
+ Loaded += UserControl_Loaded;
+ Unloaded += UserControl_Unloaded;
+ _groupJumpRopeContext = new GroupJumpRopeContext();
+ }
+
+ private async void UserControl_Loaded(object sender, RoutedEventArgs e)
+ {
+ // 使用局部变量保存事件处理方法,以便解绑
+ Action handler = null;
+
+ var app = (App)Application.Current;
+ using var scope = App.AppHost.Services.CreateScope();
+ var db = scope.ServiceProvider.GetRequiredService();
+ var cfg = await db.SixGroupPoints.FirstOrDefaultAsync();
+ //var pointlist = JsonSerializer.Deserialize>(cfg!.PointsJson);
+
+ List<(double XNorm, double YNorm)> pointlist =
+ [(cfg.point1.X, cfg.point1.Y),(cfg.point2.X, cfg.point2.Y),
+ (cfg.point3.X, cfg.point3.Y), (cfg.point4.X, cfg.point4.Y),
+ (cfg.point5.X, cfg.point5.Y),(cfg.point6.X, cfg.point6.Y)];
+ _groupJumpRopeContext.CirclePositions = pointlist;
+
+ DrawCirclesWithText();
+
+ // 播放音乐
+ PlayMusic("raisehand.mp3");
+ }
+
+ private void UserControl_Unloaded(object sender, RoutedEventArgs e)
+ {
+ _mainWin.HumanFrameUpdated -= OnHumanFrameUpdated;
+ }
+
+ private void PlayMusic(string musicFileName)
+ {
+ // 获取项目根目录
+ string projectRoot = System.IO.Path.Combine(AppContext.BaseDirectory, @"..\..\..");
+ string musicPath = System.IO.Path.Combine(projectRoot, "Resources", "Music", musicFileName);
+ string imgPath = System.IO.Path.Combine(projectRoot, "Resources", "Img", "提示图.png");
+
+ if (!File.Exists(musicPath))
+ {
+ Console.WriteLine($"音乐文件不存在: {musicPath}");
+ return;
+ }
+
+ _mediaPlayer.Open(new Uri(musicPath, UriKind.Absolute));
+
+ ShowCenterTip(imgPath, TimeSpan.FromSeconds(3));
+
+ // 监听播放完成事件
+ _mediaPlayer.MediaEnded += MediaPlayer_MediaEnded;
+ //_mainWin.WebcamClient.StartExtract();
+ _mediaPlayer.Play();
+ }
+ private void ShowCenterTip(string imagePath, TimeSpan duration)
+ {
+ var tipImage = new Image
+ {
+ Source = new BitmapImage(new Uri(imagePath, UriKind.Absolute)),
+ HorizontalAlignment = HorizontalAlignment.Center,
+ VerticalAlignment = VerticalAlignment.Center,
+ Opacity = 0,
+ Margin = new Thickness(0, -100, 0, 0),
+ };
+
+ // 增加图片的大小,调整比例
+ tipImage.Width = 1920 * 0.9; // 宽度为 Canvas 宽度的 90%
+ tipImage.Height = 1080 * 0.6; // 高度为 Canvas 高度的 60%
+
+ // 将图片添加到 Overlay Canvas
+ userBox.Children.Add(tipImage);
+
+ // 渐变出现动画
+ var fadeInAnimation = new DoubleAnimation
+ {
+ From = 0,
+ To = 1,
+ Duration = TimeSpan.FromSeconds(1.5)
+ };
+ tipImage.BeginAnimation(UIElement.OpacityProperty, fadeInAnimation);
+
+ // 定时移除,并且渐变消失
+ Task.Delay(duration).ContinueWith(_ =>
+ {
+ Dispatcher.Invoke(() =>
+ {
+ // 渐变消失动画
+ var fadeOutAnimation = new DoubleAnimation
+ {
+ From = 1,
+ To = 0,
+ Duration = TimeSpan.FromSeconds(1.5)
+ };
+ tipImage.BeginAnimation(UIElement.OpacityProperty, fadeOutAnimation);
+
+ // 完成后移除图片
+ fadeOutAnimation.Completed += (s, e) =>
+ {
+ userBox.Children.Remove(tipImage);
+ };
+ });
+ });
+ }
+
+ private void MediaPlayer_MediaEnded(object sender, EventArgs e)
+ {
+ // 音乐播放完成后的逻辑
+ Console.WriteLine("音乐播放完成!");
+
+ // 可在这里绑定抽帧事件
+ _mainWin.HumanFrameUpdated += OnHumanFrameUpdated;
+ }
+
+ private bool _isCountdownStarted = false; // 新增标记
+ private void OnHumanFrameUpdated(object sender, List humans)
+ {
+ try
+ {
+ if (humans == null || humans.Count == 0) return;
+
+ switch (_currentGameState)
+ {
+ case GameState.NotStarted: // 未开始
+ if (!_isCountdownStarted) // 只有倒计时未开始才检测左手
+ {
+ int leftWaving = DetectLeftHandRaise(humans);
+ if (leftWaving == 5)
+ {
+ _mainWin.HumanFrameUpdated -= OnHumanFrameUpdated;
+ _mainWin.WebcamClient.StopExtract();
+
+ // 举左手逻辑,例如结束动画或退出
+ var newPage = new Home();
+ _mainWin?.SwitchPageWithMaskAnimation(newPage, true);
+ return; // 提前退出
+ }
+ }
+
+ int rightWaving = DetectRightHandRaise(humans);
+ if (rightWaving >= 3)
+ {
+ switch (rightWaving)
+ {
+ case (int)WavingAction.FirstHand:
+ StartCountdown(3);
+ _isCountdownStarted = true; // 倒计时开始,停止左手检测
+ break;
+ case (int)WavingAction.Raising:
+ UpdateCountdown();
+ break;
+ case (int)WavingAction.RaiseHand:
+ FinishCountdown();
+ _currentGameState = GameState.Running; // 倒计时完成 → 游戏开始
+ break;
+ }
+ }
+ break;
+
+ case GameState.Running: // 游戏进行中
+ UpdateCircleCounts(humans);
+ break;
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("OnFrameExtracted error: " + ex.Message);
+ }
+ }
+
+ private double _currentCountdown = 3600;
+ private DateTime _lastUpdateTime = DateTime.Now;
+ private void StartCountdown(int start = 3)
+ {
+ _mainWin.ShowCountDownAnimation();
+
+ Utils.PlayBackgroundMusic("countdown_3.mp3", false);
+
+ //开始人脸识别=============================================
+ //Action handler = null;
+
+ //handler = async (frame) =>
+ //{
+ // var buffer = frame.GetImageBuffer(ImageFormat.Jpeg).ToArray();
+ // double[] xValues = [.. _groupJumpRopeContext.CirclePositions.Select(p => p.XNorm)];
+
+ // var studentList = Utils.FacialRecognition(buffer, xValues);
+
+ // if (studentList != null && studentList.Count > 0)
+ // {
+ // // 解绑事件
+ // _mainWin.FacialRecognitionEvent -= handler;
+
+ // for (int i = 0; i < studentList.Count; i++)
+ // {
+ // var student = studentList[i];
+ // if (student != null)
+ // {
+ // _groupJumpRopeContext.UserList[i].DisplayText = student.StudentName;
+ // }
+ // }
+
+ // }
+ //};
+
+ //// 绑定事件
+ //_mainWin.FacialRecognitionEvent += handler;
+ }
+
+ private void UpdateCountdown()
+ {
+ if ((DateTime.Now - _lastUpdateTime).TotalMilliseconds >= 600)
+ {
+ _lastUpdateTime = DateTime.Now;
+ _currentCountdown -= 600;
+
+ if (_currentCountdown > 0)
+ {
+ countdownText.Text = _currentCountdown.ToString();
+ }
+ else
+ {
+ FinishCountdown();
+ }
+ }
+ }
+
+ private async void FinishCountdown()
+ {
+ countdownText.Text = "GO!";
+ countdownGrid.Visibility = Visibility.Hidden;
+
+ // 播放背景音乐(循环)
+ Utils.PlayBackgroundMusic("homeprojectselected1.mp3", true);
+ // 启动60秒倒计时(独立任务)
+ StartGameCountdown(60);
+ }
+ private async void StartGameCountdown(int seconds)
+ {
+ countdownGrid.Visibility = Visibility.Visible;
+
+ for (int i = seconds; i >= 0; i--)
+ {
+ countdownText.Text = i.ToString();
+ await Task.Delay(1000);
+ }
+
+ countdownGrid.Visibility = Visibility.Hidden;
+
+ _groupJumpRopeContext.UserList.ForEach(x =>
+ {
+ x.ImageState = "1";
+ });
+
+ _mainWin.HumanFrameUpdated -= OnHumanFrameUpdated;
+ _mainWin.WebcamClient.StopExtract();
+
+ RankingItemList = _groupJumpRopeContext.UpdateRankList();
+ ShowRankingBoard(RankingItemList);
+ Utils.StopBackgroundMusic();
+
+ _currentGameState = GameState.NotStarted;
+
+ _isCountdownStarted = false;
+ _mainWin.HumanFrameUpdated += OnHumanFrameUpdated;
+ _mainWin.WebcamClient.StartExtract();
+ }
+
+ private DateTime? _raiseStartTime;
+ private bool _firstHandTriggered;
+ private int _lastCountdownSecond = 3;
+ private DateTime? _countdownStartTime;
+ public int DetectRightHandRaise(List humans)
+ {
+ if (humans == null || humans.Count == 0)
+ return (int)WavingAction.None;
+
+ foreach (var human in humans)
+ {
+ if (human?.Keypoints == null)
+ continue;
+
+ // --- 筛选右脚踝坐标 ---
+ var rightAnkle = human.Keypoints.FirstOrDefault(k => k.Name == "right_ankle");
+ if (rightAnkle == null)
+ continue;
+
+ double xNorm = rightAnkle.X / 1920;
+ double yNorm = rightAnkle.Y / 1080;
+
+ // 仅检测中心区域内的人
+ if (!(xNorm >= 0.44 && xNorm <= 0.57 && yNorm >= 0.81))
+ continue;
+
+ // --- 获取右臂关键点 ---
+ var rightWrist = human.Keypoints.FirstOrDefault(k => k.Name == "right_wrist");
+ var rightElbow = human.Keypoints.FirstOrDefault(k => k.Name == "right_elbow");
+
+ const double raiseThreshold = 60; // 举手阈值
+ const double holdDuration = 1; // 持续时间(秒)
+ const int countdownSeconds = 3; // 倒计时长度
+
+ bool handRaised = false;
+
+ if (rightWrist != null && rightElbow != null)
+ {
+ double verticalRise = rightElbow.Y - rightWrist.Y;
+ handRaised = verticalRise >= raiseThreshold;
+ }
+
+ // ---------- 第一步:持续举手触发倒计时 ----------
+ if (!_firstHandTriggered)
+ {
+ if (handRaised)
+ {
+ _raiseStartTime ??= DateTime.Now;
+ var holdElapsed = (DateTime.Now - _raiseStartTime.Value).TotalSeconds;
+ if (holdElapsed >= holdDuration)
+ {
+ // 举手达到指定时间,启动倒计时
+ _firstHandTriggered = true;
+ _countdownStartTime = DateTime.Now;
+ _lastCountdownSecond = countdownSeconds;
+ return (int)WavingAction.FirstHand;
+ }
+ }
+ else
+ {
+ // 手放下,重置举手开始时间
+ _raiseStartTime = DateTime.Now;
+ }
+
+ continue; // 本人未触发,检测下一个人
+ }
+
+ // ---------- 第二步:倒计时逻辑 ----------
+ var countdownElapsed = (DateTime.Now - _countdownStartTime.Value).TotalSeconds;
+ int currentSecond = countdownSeconds - (int)Math.Floor(countdownElapsed);
+
+ if (currentSecond > 0 && currentSecond != _lastCountdownSecond)
+ {
+ _lastCountdownSecond = currentSecond;
+ Console.WriteLine($"倒计时:{currentSecond}");
+ return (int)WavingAction.Raising; // 倒计时中
+ }
+
+ if (countdownElapsed >= countdownSeconds)
+ {
+ ResetRaiseState();
+ return (int)WavingAction.RaiseHand; // 举手完成
+ }
+
+ return (int)WavingAction.Raising;
+ }
+
+ // 没有任何中心区域内的人举手
+ return (int)WavingAction.None;
+ }
+ public int DetectLeftHandRaise(List humans)
+ {
+ if (humans == null || humans.Count == 0)
+ return (int)WavingAction.None;
+
+
+ foreach (var human in humans)
+ {
+ if (human?.Keypoints == null)
+ continue;
+
+ // --- 筛选右脚踝坐标 ---
+ var rightAnkle = human.Keypoints.FirstOrDefault(k => k.Name == "right_ankle");
+ if (rightAnkle == null)
+ continue;
+ double xNorm = rightAnkle.X / 1920;
+ double yNorm = rightAnkle.Y / 1080;
+ // 仅检测中心区域内的人
+ if (!(xNorm >= 0.44 && xNorm <= 0.57 && yNorm >= 0.81))
+ continue;
+
+ // 获取左手关键点
+ var leftWrist = human.Keypoints.FirstOrDefault(k => k.Name == "left_wrist");
+ var leftElbow = human.Keypoints.FirstOrDefault(k => k.Name == "left_elbow");
+
+ if (leftWrist == null || leftElbow == null)
+ continue;
+
+ const double raiseThreshold = 60; // 举手阈值
+
+ // 判断左手是否举起
+ double verticalRise = leftElbow.Y - leftWrist.Y;
+ if (verticalRise >= raiseThreshold)
+ {
+ return (int)WavingAction.RaiseHand; // 一旦检测到左手举起,立即返回
+ }
+ }
+
+ return (int)WavingAction.None; // 没有检测到举手
+ }
+
+ private void ResetRaiseState()
+ {
+ _raiseStartTime = null;
+ _countdownStartTime = null;
+ _firstHandTriggered = false;
+ _lastCountdownSecond = 3;
+ }
+ private void DrawCirclesWithText()
+ {
+ userBox.Children.Clear();
+ _groupJumpRopeContext.Sports.Clear();
+ _groupJumpRopeContext.UserList.Clear();
+ _groupJumpRopeContext.UserNumberList.Clear();
+
+ double imgWidth = userBox.ActualWidth;
+ double imgHeight = userBox.ActualHeight;
+
+ for (int i = 0; i < _groupJumpRopeContext.CirclePositions.Count; i++)
+ {
+ var pos = _groupJumpRopeContext.CirclePositions[i];
+ double x = pos.XNorm * imgWidth;
+ double y = pos.YNorm * imgHeight;
+
+ // 绘制发光圆
+ var userItem = AddUserItem(x, y, i);
+
+ // 绑定运动对象
+
+ var sport = SportBase.Create("jumping-jack");
+
+ //Optimizes.Optimizeing(sport);
+
+ //var sport = SportBase.Create("jumping-jack");
+
+ int indexCopy = i;
+ var currentItem = userItem;
+
+ // 订阅事件
+ sport.OnTicked += (count, times) =>
+ {
+ // 更新UI
+ userItem.NumberText = count.ToString();
+ // 更新数字源
+ _groupJumpRopeContext.UserNumberList[indexCopy] = count.ToString();
+ // 改变状态为“跳绳中”
+ if (userItem.ImageState != "2")
+ userItem.ImageState = "2";
+ };
+
+ sport.Start();
+ _groupJumpRopeContext.Sports.Add(sport);
+ }
+ }
+ private void UpdateCircleCounts(List humans)
+ {
+ // 放宽一点的圈半径(归一化)
+ double radiusNormX = 0.10;
+ double radiusNormY = 0.14;
+
+ for (int i = 0; i < _groupJumpRopeContext.CirclePositions.Count; i++)
+ {
+ var circleX = _groupJumpRopeContext.CirclePositions[i].XNorm;
+ var circleY = _groupJumpRopeContext.CirclePositions[i].YNorm;
+
+ Human humanInCircle = null;
+
+ 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;
+
+ bool rightInCircle = false;
+ bool leftInCircle = false;
+
+ // 右脚判断
+ if (rightFoot != null)
+ {
+ double xRightNorm = rightFoot.X / userBox.ActualWidth;
+ double yRightNorm = rightFoot.Y / userBox.ActualHeight;
+
+ rightInCircle =
+ xRightNorm >= (circleX - radiusNormX) &&
+ xRightNorm <= (circleX + radiusNormX) &&
+ yRightNorm >= (circleY - radiusNormY) &&
+ yRightNorm <= (circleY + radiusNormY);
+ }
+
+ // 左脚判断
+ if (leftFoot != null)
+ {
+ double xLeftNorm = leftFoot.X / userBox.ActualWidth;
+ double yLeftNorm = leftFoot.Y / userBox.ActualHeight;
+
+ leftInCircle =
+ xLeftNorm >= (circleX - radiusNormX) &&
+ xLeftNorm <= (circleX + radiusNormX) &&
+ yLeftNorm >= (circleY - radiusNormY) &&
+ yLeftNorm <= (circleY + radiusNormY);
+ }
+
+ // ✅ 只要有一只脚在圈内
+ if (rightInCircle || leftInCircle)
+ {
+ humanInCircle = hu;
+ break;
+ }
+ }
+
+ bool hasHuman = humanInCircle != null;
+
+ lock (_updateLock)
+ {
+ _groupJumpRopeContext.UserList[i].ImageState =
+ GetJumpState(i, hasHuman);
+ }
+
+ if (hasHuman)
+ {
+ _groupJumpRopeContext.Sports[i].Pushing(humanInCircle);
+ }
+ }
+ }
+
+
+ private string GetJumpState(int circleIndex, bool humanInCircle)
+ {
+ if (!humanInCircle)
+ {
+ // 无人 → 出圈
+ return "3";
+ }
+
+ string currentNumber = _groupJumpRopeContext.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 >= 0.8)
+ {
+ // 超过 2 秒未变化 → 停止
+ _jumpStatus[circleIndex] = (currentNumber, lastChangeTime, "1");
+ return "1";
+ }
+ // 维持上次状态
+ return lastState;
+ }
+
+ private SportUserItem AddUserItem(double centerX, double centerY, int index)
+ {
+ var userItem = new SportUserItem();
+ userItem.Width = 270;
+ userItem.Height = 560;
+ userItem.DisplayText = _groupJumpRopeContext.UseNameList[index];
+ 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);
+ _groupJumpRopeContext.UserList.Add(userItem);
+ _groupJumpRopeContext.UserNumberList.Add("0");
+ return userItem; //
+ }
+
+ public void ShowRankingBoard(List list)
+ {
+ var scoreGrid = FindName("ScoreGrid") as Grid;
+ name1.Text = list[0].Name;
+ name2.Text = list[1].Name;
+ name3.Text = list[2].Name;
+ number1.Text = list[0].Number.ToString();
+ number2.Text = list[1].Number.ToString();
+ number3.Text = list[2].Number.ToString();
+ foreach (var item in list)
+ {
+ var grid = new Grid
+ {
+ Width = 1344,
+ Height = 71,
+ HorizontalAlignment = HorizontalAlignment.Center,
+ VerticalAlignment = VerticalAlignment.Top,
+ Margin = new Thickness(0, 69 * item.Rank, 0, 0)
+ };
+ var border = new Border
+ {
+ Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#fff"))
+ };
+ grid.Children.Add(border);
+ var rankText = new TextBlock
+ {
+ Text = item.Rank.ToString(),
+ FontSize = 24,
+ FontWeight = FontWeights.Bold,
+ Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#999999")),
+ HorizontalAlignment = HorizontalAlignment.Left,
+ VerticalAlignment = VerticalAlignment.Center,
+ TextAlignment = TextAlignment.Center,
+ Width = 200
+ };
+ grid.Children.Add(rankText);
+
+ var positionText = new TextBlock
+ {
+ Text = item.Name,
+ FontSize = 24,
+ FontWeight = FontWeights.Bold,
+ Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#999999")),
+ HorizontalAlignment = HorizontalAlignment.Center,
+ VerticalAlignment = VerticalAlignment.Center
+ };
+ grid.Children.Add(positionText);
+
+ var scoreText = new TextBlock
+ {
+ Text = item.Number.ToString(),
+ FontSize = 24,
+ FontWeight = FontWeights.Bold,
+ Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#999999")),
+ HorizontalAlignment = HorizontalAlignment.Right,
+ VerticalAlignment = VerticalAlignment.Center,
+ TextAlignment = TextAlignment.Center,
+ Width = 200
+ };
+ grid.Children.Add(scoreText);
+ ScoreGrid.Children.Add(grid);
+ }
+ showElement("RankingGrid");
+ //var rankingGrid = FindName("RankingGrid") as Grid;
+ //if (rankingGrid == null) return;
+
+ //rankingGrid.Visibility = Visibility.Visible;
+ //var fadeIn = new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(600));
+ //rankingGrid.BeginAnimation(UIElement.OpacityProperty, fadeIn);
+ }
+
+ /*
+ * 控制元素隐藏(渐隐动画
+ * time: 动画持续时间(毫秒)
+ * name: 元素名称
+ */
+ public void HideElement(string name, int time)
+ {
+ var Element = FindName(name) as Grid;
+ if (Element == null) return;
+
+ var fadeOut = new DoubleAnimation(1, 0, TimeSpan.FromMilliseconds(time));
+ fadeOut.Completed += (s, e) => Element.Visibility = Visibility.Collapsed;
+ Element.BeginAnimation(UIElement.OpacityProperty, fadeOut);
+ }
+
+ /*
+ * 控制元素限时(渐隐动画
+ * time: 动画持续时间(毫秒)
+ * name: 元素名称
+ */
+ public void showElement(string name, int time = 600)
+ {
+ var Element = FindName(name) as FrameworkElement;
+ if (Element == null) return;
+
+ Element.Visibility = Visibility.Visible;
+ var fadeIn = new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(time));
+ Element.BeginAnimation(UIElement.OpacityProperty, fadeIn);
}
}
}
+