多人跳绳

This commit is contained in:
tanglong 2025-10-14 20:23:16 +08:00
parent bb74b1f82f
commit 69453a1baa
2 changed files with 60 additions and 58 deletions

View File

@ -9,13 +9,30 @@ namespace Dto
{ {
public class GroupJumpRopeContext public class GroupJumpRopeContext
{ {
public int Index { get; set; } public List<(double XNorm, double YNorm)> CirclePositions { get; private set; }
public List<(double XNorm, double YNorm)> CirclePositions { get; set; } public List<SportUserItem> UserList { get; private set; }
public List<SportBase> Sports{ get; set; } public List<string> UserNumberList { get; private set; }
public List<SportUserItem> User { get; set; } public List<SportBase> Sports { get; private set; }
public List<string> UseNameList { get; private set; } = new()
{
"一号位", "四号位", "二号位", "五号位", "三号位", "六号位"
};
public GroupJumpRopeContext()
{
CirclePositions = new List<(double XNorm, double YNorm)>
{
(0.21, 0.88 ),
(0.36, 0.68 ),
(0.50, 0.88),
(0.64, 0.68 ),
(0.78, 0.88),
(0.92, 0.68 )
};
UserList = new List<SportUserItem>();
UserNumberList = new List<string>();
Sports = new List<SportBase>();
public string LastNumberText { get; set; } = ""; }
public DateTime LastJumpTime { get; set; } = DateTime.MinValue;
public DateTime LastUIUpdateTime { get; set; } = DateTime.MinValue;
} }
} }

View File

@ -1,4 +1,5 @@
using Emgu.CV.Flann; using Dto;
using Emgu.CV.Flann;
using HandyControl.Controls; using HandyControl.Controls;
using SharpDX.Direct3D9; using SharpDX.Direct3D9;
using System; using System;
@ -41,24 +42,18 @@ namespace Wpf_AiSportsMicrospace.Views
/// </summary> /// </summary>
public partial class GroupJumpRope : UserControl public partial class GroupJumpRope : UserControl
{ {
private List<SportBase> sports = new();
private List<TextBlock> circleTexts = new();
private List<SportUserItem> userList = new();
private List<string> userNumberList = ["0", "0", "0", "0", "0", "0"];
private Main _mainWin => Application.Current.MainWindow as Main; private Main _mainWin => Application.Current.MainWindow as Main;
private List<(double XNorm, double YNorm)> circlePositions = new();
private MediaPlayer _mediaPlayer = new MediaPlayer(); private MediaPlayer _mediaPlayer = new MediaPlayer();
private bool IsGameStarted = false; private bool IsGameStarted = false;
List<string> _useName = ["一号位", "四号位", "二号位", "五号位", "三号位", "六号位",];
private readonly object _updateLock = new object(); private readonly object _updateLock = new object();
private readonly Dictionary<int, (string lastNumber, DateTime lastChangeTime, string currentState)> _jumpStatus = new Dictionary<int, (string, DateTime, string)>(); private readonly Dictionary<int, (string lastNumber, DateTime lastChangeTime, string currentState)> _jumpStatus = new Dictionary<int, (string, DateTime, string)>();
private GroupJumpRopeContext _groupJumpRopeContext;
public GroupJumpRope() public GroupJumpRope()
{ {
InitializeComponent(); InitializeComponent();
Loaded += UserControl_Loaded; Loaded += UserControl_Loaded;
Unloaded += UserControl_Unloaded; Unloaded += UserControl_Unloaded;
_groupJumpRopeContext = new GroupJumpRopeContext();
} }
private async void UserControl_Loaded(object sender, RoutedEventArgs e) private async void UserControl_Loaded(object sender, RoutedEventArgs e)
@ -263,7 +258,7 @@ namespace Wpf_AiSportsMicrospace.Views
countdownGrid.Visibility = Visibility.Hidden; countdownGrid.Visibility = Visibility.Hidden;
userList.ForEach(x => _groupJumpRopeContext.UserList.ForEach(x =>
{ {
x.ImageState = "1"; x.ImageState = "1";
}); });
@ -348,29 +343,17 @@ namespace Wpf_AiSportsMicrospace.Views
private void DrawCirclesWithText() private void DrawCirclesWithText()
{ {
userBox.Children.Clear(); userBox.Children.Clear();
sports.Clear(); _groupJumpRopeContext.Sports.Clear();
circleTexts.Clear(); _groupJumpRopeContext.UserList.Clear();
userList.Clear(); // 清空用户控件列表 _groupJumpRopeContext.UserNumberList.Clear();
double imgWidth = userBox.ActualWidth; double imgWidth = userBox.ActualWidth;
double imgHeight = userBox.ActualHeight; double imgHeight = userBox.ActualHeight;
double radius = 100; double radius = 100;
// 每个圆的位置X 和 Y 都归一化 0~1 for (int i = 0; i < _groupJumpRopeContext.CirclePositions.Count; i++)
circlePositions = new List<(double XNorm, double YNorm)>
{ {
//(0.07, 0.58), var pos = _groupJumpRopeContext.CirclePositions[i];
(0.21, 0.88 ),
(0.36, 0.68 ),
(0.50, 0.88),
(0.64, 0.68 ),
(0.78, 0.88),
(0.92, 0.68 )
};
for (int i = 0; i < circlePositions.Count; i++)
{
var pos = circlePositions[i];
double x = pos.XNorm * imgWidth; double x = pos.XNorm * imgWidth;
double y = pos.YNorm * imgHeight; double y = pos.YNorm * imgHeight;
@ -385,15 +368,17 @@ namespace Wpf_AiSportsMicrospace.Views
// 订阅事件 // 订阅事件
sport.OnTicked += (count, times) => sport.OnTicked += (count, times) =>
{ {
currentItem.NumberText = count.ToString(); // 更新UI
userItem.NumberText = count.ToString();
if (currentItem.ImageState != "2") // 更新数字源
{ _groupJumpRopeContext.UserNumberList[indexCopy] = count.ToString();
currentItem.ImageState = "2"; // 改变状态为“跳绳中”
} if (userItem.ImageState != "2")
userItem.ImageState = "2";
}; };
sport.Start(); sport.Start();
sports.Add(sport); _groupJumpRopeContext.Sports.Add(sport);
} }
} }
private void UpdateCircleCounts(List<Human> humans) private void UpdateCircleCounts(List<Human> humans)
@ -401,10 +386,10 @@ namespace Wpf_AiSportsMicrospace.Views
double radiusNormX = 0.07; double radiusNormX = 0.07;
double radiusNormY = 0.14; double radiusNormY = 0.14;
for (int i = 0; i < circlePositions.Count; i++) for (int i = 0; i < _groupJumpRopeContext.CirclePositions.Count; i++)
{ {
var circleX = circlePositions[i].XNorm; var circleX = _groupJumpRopeContext.CirclePositions[i].XNorm;
var circleY = circlePositions[i].YNorm; var circleY = _groupJumpRopeContext.CirclePositions[i].YNorm;
Human humanInCircle = null; Human humanInCircle = null;
@ -438,12 +423,12 @@ namespace Wpf_AiSportsMicrospace.Views
bool hasHuman = humanInCircle != null; bool hasHuman = humanInCircle != null;
lock (_updateLock) lock (_updateLock)
{ {
userList[i].ImageState = GetJumpState(i, hasHuman); _groupJumpRopeContext.UserList[i].ImageState = GetJumpState(i, hasHuman);
} }
// 推送计数 // 推送计数
if (hasHuman) if (hasHuman)
sports[i].Pushing(humanInCircle); _groupJumpRopeContext.Sports[i].Pushing(humanInCircle);
} }
} }
private string GetJumpState(int circleIndex, bool humanInCircle) private string GetJumpState(int circleIndex, bool humanInCircle)
@ -454,26 +439,25 @@ namespace Wpf_AiSportsMicrospace.Views
return "3"; return "3";
} }
string currentNumber = userNumberList[circleIndex]; string currentNumber = _groupJumpRopeContext.UserNumberList[circleIndex];
if (!_jumpStatus.ContainsKey(circleIndex)) if (!_jumpStatus.ContainsKey(circleIndex))
{ {
_jumpStatus[circleIndex] = (currentNumber, DateTime.Now, "1"); // 初始状态先为停止 _jumpStatus[circleIndex] = (currentNumber, DateTime.Now, "1"); // 初始状态先为停止
return "1"; return "1";
} }
var (lastNumber, lastChangeTime, lastState) = _jumpStatus[circleIndex]; var (lastNumber, lastChangeTime, lastState) = _jumpStatus[circleIndex];
//if (currentNumber != lastNumber) if (currentNumber != lastNumber)
//{ {
// // 数字变化 → 跳绳中 // 数字变化 → 跳绳中
// _jumpStatus[circleIndex] = (currentNumber, DateTime.Now, "2"); _jumpStatus[circleIndex] = (currentNumber, DateTime.Now, "2");
// return "2"; return "2";
//} }
// 数字未变化,判断是否超过 2 秒 // 数字未变化,判断是否超过 2 秒
double elapsed = (DateTime.Now - lastChangeTime).TotalSeconds; double elapsed = (DateTime.Now - lastChangeTime).TotalSeconds;
if (elapsed >= 2) if (elapsed >= 0.8)
{ {
// 超过 2 秒未变化 → 停止 // 超过 2 秒未变化 → 停止
_jumpStatus[circleIndex] = (currentNumber, lastChangeTime, "1"); _jumpStatus[circleIndex] = (currentNumber, lastChangeTime, "1");
@ -491,14 +475,15 @@ namespace Wpf_AiSportsMicrospace.Views
var userItem = new SportUserItem(); var userItem = new SportUserItem();
userItem.Width = 270; userItem.Width = 270;
userItem.Height = 560; userItem.Height = 560;
userItem.DisplayText = _useName[index]; userItem.DisplayText = _groupJumpRopeContext.UseNameList[index];
userItem.VerticalAlignment = VerticalAlignment.Top; userItem.VerticalAlignment = VerticalAlignment.Top;
userItem.HorizontalAlignment = HorizontalAlignment.Left; userItem.HorizontalAlignment = HorizontalAlignment.Left;
userItem.ImageState = "1"; userItem.ImageState = "1";
//userItem.Margin = new Thickness(centerX - (index == 0 ? 80 : index == 6 ? 190 : 135), centerY - 540, 0, 0); //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); userItem.Margin = new Thickness(centerX - 265, centerY - 500, 0, 0);
userBox.Children.Add(userItem); userBox.Children.Add(userItem);
userList.Add(userItem); _groupJumpRopeContext.UserList.Add(userItem);
_groupJumpRopeContext.UserNumberList.Add("0");
return userItem; // return userItem; //
} }
} }