update:打地鼠
This commit is contained in:
parent
c6c50f3d6a
commit
fd638d91cd
@ -26,12 +26,12 @@ namespace Dto
|
||||
{
|
||||
CirclePositions = new List<(double XNorm, double YNorm)>
|
||||
{
|
||||
(0.21, 0.88 ),
|
||||
(0.36, 0.58 ),
|
||||
(0.50, 0.88),
|
||||
(0.64, 0.58 ),
|
||||
(0.78, 0.88),
|
||||
(0.92, 0.58 )
|
||||
(403.2, 950.4 ),
|
||||
(691.2, 626.4 ),
|
||||
(960, 950.4 ),
|
||||
(1228.8, 626.4 ),
|
||||
(1497.6, 950.4),
|
||||
(1766.4, 626.4)
|
||||
};
|
||||
|
||||
UserList = new List<WhackAMoleUserControl>();
|
||||
|
||||
@ -6,11 +6,13 @@
|
||||
xmlns:local="clr-namespace:Wpf_AiSportsMicrospace.MyUserControl"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:gif="http://wpfanimatedgif.codeplex.com">
|
||||
<Grid >
|
||||
<Grid Width="410" Height="580">
|
||||
<Image gif:ImageBehavior.AnimatedSource="/Resources/Img/play_img/whack_mole/mole_u.gif"
|
||||
x:Name="image1"
|
||||
gif:ImageBehavior.AutoStart="False"
|
||||
gif:ImageBehavior.RepeatBehavior="Forever"
|
||||
gif:ImageBehavior.RepeatBehavior="1x"
|
||||
gif:ImageBehavior.AnimateInDesignMode="True"
|
||||
gif:ImageBehavior.AnimationSpeedRatio="0.82"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top"
|
||||
Width="420"
|
||||
@ -36,7 +38,7 @@
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top"
|
||||
Width="420"
|
||||
Visibility="Visible"/>
|
||||
Visibility="Hidden"/>
|
||||
|
||||
|
||||
<Image gif:ImageBehavior.AnimatedSource="/Resources/Img/play_img/whack_mole/rabbit_hit_u.gif"
|
||||
@ -48,34 +50,22 @@
|
||||
Width="420"
|
||||
Visibility="Hidden"/>
|
||||
|
||||
<TextBlock x:Name="TimerText"
|
||||
Text="q"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
FontSize="5"
|
||||
FontWeight="Bold"
|
||||
Foreground="White"
|
||||
Visibility="Collapsed">
|
||||
<TextBlock.Effect>
|
||||
<DropShadowEffect Color="#497600" BlurRadius="1" ShadowDepth="4"/>
|
||||
</TextBlock.Effect>
|
||||
</TextBlock>
|
||||
<Image
|
||||
Source="/Resources/Img/play_img/whack_mole/score-bg.png"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Width="145"
|
||||
Margin="234,511,0,0"
|
||||
/>
|
||||
Source="/Resources/Img/play_img/whack_mole/score-bg.png"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Width="145"
|
||||
Margin="234,511,0,0"
|
||||
/>
|
||||
<Image
|
||||
Source="/Resources/Img/play_img/whack_mole/name-bot.png"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Width="406"
|
||||
Margin="0,571,0,0"
|
||||
/>
|
||||
<TextBlock x:Name="NumberText"
|
||||
Text="0"
|
||||
Source="/Resources/Img/play_img/whack_mole/name-bot.png"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Width="150"
|
||||
Margin="40,571,0,0"
|
||||
/>
|
||||
<TextBlock
|
||||
Text="{Binding NumberText, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
Width="135"
|
||||
TextAlignment="Center"
|
||||
HorizontalAlignment="Left"
|
||||
@ -89,8 +79,7 @@
|
||||
</TextBlock.Effect>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock x:Name="name"
|
||||
Text="Name"
|
||||
<TextBlock Text="{Binding NameText, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
FontSize="45"
|
||||
|
||||
@ -18,671 +18,143 @@ namespace Wpf_AiSportsMicrospace.MyUserControl
|
||||
/// <summary>
|
||||
/// 打地鼠用户控件
|
||||
/// </summary>
|
||||
public partial class WhackAMoleUserControl : UserControl, INotifyPropertyChanged
|
||||
public partial class WhackAMoleUserControl : UserControl
|
||||
{
|
||||
#region 依赖属性
|
||||
|
||||
/// <summary>
|
||||
/// 玩家索引
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IndexProperty =
|
||||
DependencyProperty.Register(nameof(Index), typeof(int), typeof(WhackAMoleUserControl),
|
||||
new PropertyMetadata(0, OnIndexChanged));
|
||||
|
||||
/// <summary>
|
||||
/// 是否激活游戏
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsActiveProperty =
|
||||
DependencyProperty.Register(nameof(IsActive), typeof(bool), typeof(WhackAMoleUserControl),
|
||||
new PropertyMetadata(false, OnIsActiveChanged));
|
||||
|
||||
/// <summary>
|
||||
/// 触发值,用于检测打地鼠动作
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty TriggerValueProperty =
|
||||
DependencyProperty.Register(nameof(TriggerValue), typeof(double), typeof(WhackAMoleUserControl),
|
||||
new PropertyMetadata(0.0, OnTriggerValueChanged));
|
||||
|
||||
#endregion
|
||||
|
||||
#region 属性
|
||||
|
||||
/// <summary>
|
||||
/// 玩家索引
|
||||
/// </summary>
|
||||
public int Index
|
||||
{
|
||||
get => (int)GetValue(IndexProperty);
|
||||
set => SetValue(IndexProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否激活游戏
|
||||
/// </summary>
|
||||
public bool IsActive
|
||||
{
|
||||
get => (bool)GetValue(IsActiveProperty);
|
||||
set => SetValue(IsActiveProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 触发值
|
||||
/// </summary>
|
||||
public double TriggerValue
|
||||
{
|
||||
get => (double)GetValue(TriggerValueProperty);
|
||||
set => SetValue(TriggerValueProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 私有字段
|
||||
|
||||
private int _score = 0;
|
||||
private int _gameTime = 60;
|
||||
private bool _isCharacterVisible = false;
|
||||
private CharacterType _currentCharacter = CharacterType.None;
|
||||
private DateTime _characterAppearTime;
|
||||
private DispatcherTimer _gameTimer;
|
||||
private DispatcherTimer _appearanceTimer;
|
||||
private DispatcherTimer _hitDetectionTimer;
|
||||
private double _lastTriggerValue;
|
||||
private bool _isProcessingHit = false;
|
||||
private readonly Random _random = new Random();
|
||||
ImageAnimationController controller1;
|
||||
ImageAnimationController controller2;
|
||||
ImageAnimationController controller3;
|
||||
ImageAnimationController controller4;
|
||||
private bool _isInitialized = false;
|
||||
/// <summary>
|
||||
/// 外部上下文,用于更新用户分数列表
|
||||
/// 注意:需要根据实际项目调整这个引用方式
|
||||
/// </summary>
|
||||
private WhackAMoleContext _whackAMoleContext;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 事件
|
||||
|
||||
/// <summary>
|
||||
/// 分数改变事件
|
||||
/// </summary>
|
||||
public event Action<int, int> ScoreChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 游戏结束事件
|
||||
/// </summary>
|
||||
public event Action<int> GameEnded;
|
||||
|
||||
/// <summary>
|
||||
/// 属性改变事件
|
||||
/// </summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 枚举
|
||||
|
||||
/// <summary>
|
||||
/// 角色类型
|
||||
/// </summary>
|
||||
private enum CharacterType
|
||||
{
|
||||
None,
|
||||
Mole,
|
||||
Rabbit
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 构造方法
|
||||
|
||||
public WhackAMoleUserControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// 初始化计时器
|
||||
InitializeTimers();
|
||||
|
||||
// 初始化外部上下文引用
|
||||
InitializeContext();
|
||||
|
||||
//InitGif();
|
||||
ImageBehavior.AddAnimationCompletedHandler(image1, TimeDown1);
|
||||
ImageBehavior.AddAnimationCompletedHandler(image2, TimeDown);
|
||||
ImageBehavior.AddAnimationCompletedHandler(image3, TimeDown1);
|
||||
ImageBehavior.AddAnimationCompletedHandler(image4, TimeDown);
|
||||
}
|
||||
#region 依赖属性
|
||||
|
||||
public string NumberText
|
||||
{
|
||||
get => (string)GetValue(NumberTextProperty);
|
||||
set => SetValue(NumberTextProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty NumberTextProperty =
|
||||
DependencyProperty.Register(nameof(NumberText), typeof(string), typeof(WhackAMoleUserControl), new PropertyMetadata("0"));
|
||||
|
||||
public string NameText
|
||||
{
|
||||
get => (string)GetValue(NameTextProperty);
|
||||
set => SetValue(NameTextProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty NameTextProperty =
|
||||
DependencyProperty.Register(nameof(NameText), typeof(string), typeof(WhackAMoleUserControl), new PropertyMetadata("游客"));
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 私有方法
|
||||
|
||||
/// <summary>
|
||||
/// 初始化计时器
|
||||
/// </summary>
|
||||
private void InitializeTimers()
|
||||
public string ImageState
|
||||
//1 地鼠 2 地鼠打中 3 兔子 4 兔子打中
|
||||
{
|
||||
// 游戏主计时器(60秒倒计时)
|
||||
_gameTimer = new DispatcherTimer();
|
||||
_gameTimer.Interval = TimeSpan.FromSeconds(1);
|
||||
_gameTimer.Tick += GameTimer_Tick;
|
||||
get => (string)GetValue(ImageStateProperty);
|
||||
set => SetValue(ImageStateProperty, value);
|
||||
}
|
||||
public static readonly DependencyProperty ImageStateProperty =
|
||||
DependencyProperty.Register(nameof(ImageState), typeof(string), typeof(WhackAMoleUserControl), new PropertyMetadata("1", OnImageStateChanged));
|
||||
|
||||
// 角色出现计时器(随机间隔)
|
||||
_appearanceTimer = new DispatcherTimer();
|
||||
_appearanceTimer.Tick += AppearanceTimer_Tick;
|
||||
|
||||
// 打击检测计时器(200ms检测窗口)
|
||||
_hitDetectionTimer = new DispatcherTimer();
|
||||
_hitDetectionTimer.Interval = TimeSpan.FromMilliseconds(50);
|
||||
_hitDetectionTimer.Tick += HitDetectionTimer_Tick;
|
||||
|
||||
_whackAMoleContext = new WhackAMoleContext();
|
||||
private static void OnImageStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var control = (WhackAMoleUserControl)d;
|
||||
control.ShowImage((string)e.NewValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化外部上下文引用
|
||||
/// </summary>
|
||||
private void InitializeContext()
|
||||
private DispatcherTimer _imageTimer;
|
||||
private Image _currentImage;
|
||||
|
||||
private void ShowImage(string imageIndex)
|
||||
{
|
||||
// 根据项目实际情况获取_context引用
|
||||
// 这里需要根据你的项目结构调整
|
||||
try
|
||||
// 隐藏所有图片
|
||||
image1.Visibility = Visibility.Hidden;
|
||||
image2.Visibility = Visibility.Hidden;
|
||||
image3.Visibility = Visibility.Hidden;
|
||||
image4.Visibility = Visibility.Hidden;
|
||||
|
||||
// 显示指定的图片
|
||||
Image targetImage = null;
|
||||
|
||||
switch (imageIndex)
|
||||
{
|
||||
// 示例:如果存在全局上下文类
|
||||
// _groupJumpRopeContext = GlobalContext.Instance?.GetProperty("_groupJumpRopeContext");
|
||||
|
||||
// 或者通过查找父窗口/用户控件获取
|
||||
var parent = this.Parent as FrameworkElement;
|
||||
while (parent != null)
|
||||
{
|
||||
var contextProperty = parent.GetType().GetProperty("_whackAMoleContext");
|
||||
if (contextProperty != null)
|
||||
{
|
||||
_whackAMoleContext = (WhackAMoleContext)contextProperty.GetValue(parent);
|
||||
break;
|
||||
}
|
||||
parent = parent.Parent as FrameworkElement;
|
||||
}
|
||||
case "1":
|
||||
targetImage = image1;
|
||||
break;
|
||||
case "2":
|
||||
targetImage = image2;
|
||||
break;
|
||||
case "3":
|
||||
targetImage = image3;
|
||||
break;
|
||||
case "4":
|
||||
targetImage = image4;
|
||||
break;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// 忽略初始化错误,在实际使用时会再次尝试获取
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void InitImageContal()
|
||||
{
|
||||
controller1 = ImageBehavior.GetAnimationController(image1);
|
||||
controller2 = ImageBehavior.GetAnimationController(image2);
|
||||
controller3 = ImageBehavior.GetAnimationController(image3);
|
||||
controller4 = ImageBehavior.GetAnimationController(image4);
|
||||
controller2.GotoFrame(controller2.FrameCount - 1);
|
||||
controller4.GotoFrame(controller4.FrameCount - 1);
|
||||
image2.Visibility = Visibility;
|
||||
image4.Visibility = Visibility;
|
||||
if(controller1 != null && controller2 != null && controller3 != null && controller4 != null)
|
||||
{
|
||||
_isInitialized = true;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取外部上下文
|
||||
/// </summary>
|
||||
private void TryGetContext()
|
||||
{
|
||||
if (_whackAMoleContext == null)
|
||||
{
|
||||
InitializeContext();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新外部分数列表
|
||||
/// </summary>
|
||||
private void UpdateExternalScoreList()
|
||||
{
|
||||
TryGetContext();
|
||||
|
||||
if (_whackAMoleContext != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var userNumberList = _whackAMoleContext.GetType().GetProperty("UserNumberList")?.GetValue(_whackAMoleContext) as List<int>;
|
||||
if (userNumberList != null && Index >= 0 && Index < userNumberList.Count)
|
||||
{
|
||||
userNumberList[Index] = _score;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// 忽略更新错误
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开始游戏
|
||||
/// </summary>
|
||||
private void StartGame()
|
||||
{
|
||||
if (!_isInitialized) {
|
||||
InitImageContal();
|
||||
name.Text = _whackAMoleContext.UserNameList[Index];
|
||||
}
|
||||
|
||||
// 重置分数
|
||||
_score = 0;
|
||||
UpdateScoreDisplay();
|
||||
|
||||
// 重置计时器
|
||||
_gameTime = 60;
|
||||
UpdateTimerDisplay();
|
||||
|
||||
// 隐藏所有角色
|
||||
HideAllCharacters();
|
||||
|
||||
// 启动游戏计时器
|
||||
_gameTimer.Start();
|
||||
|
||||
// 启动角色出现计时器(1-3秒随机间隔)
|
||||
ScheduleNextAppearance();
|
||||
|
||||
// 启动打击检测计时器
|
||||
_hitDetectionTimer.Start();
|
||||
|
||||
// 记录初始触发值
|
||||
_lastTriggerValue = TriggerValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止游戏
|
||||
/// </summary>
|
||||
private void StopGame()
|
||||
{
|
||||
// 停止所有计时器
|
||||
_gameTimer.Stop();
|
||||
_appearanceTimer.Stop();
|
||||
_hitDetectionTimer.Stop();
|
||||
|
||||
// 隐藏所有角色
|
||||
HideAllCharacters();
|
||||
|
||||
// 重置状态
|
||||
_isCharacterVisible = false;
|
||||
_currentCharacter = CharacterType.None;
|
||||
_isProcessingHit = false;
|
||||
|
||||
// 发送游戏结束事件
|
||||
GameEnded?.Invoke(_score);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安排下一次角色出现
|
||||
/// </summary>
|
||||
private void ScheduleNextAppearance()
|
||||
{
|
||||
// 随机间隔3-5秒
|
||||
int interval = _random.Next(2000, 3501);
|
||||
_appearanceTimer.Interval = TimeSpan.FromMilliseconds(interval);
|
||||
_appearanceTimer.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示角色
|
||||
/// </summary>
|
||||
private void ShowCharacter()
|
||||
{
|
||||
if (_isProcessingHit) return;
|
||||
|
||||
// 随机决定出现地鼠还是兔子(70%地鼠,30%兔子)
|
||||
bool isMole = _random.Next(100) < 20;
|
||||
_currentCharacter = isMole ? CharacterType.Mole : CharacterType.Rabbit;
|
||||
_isCharacterVisible = true;
|
||||
_characterAppearTime = DateTime.Now;
|
||||
image2.Visibility = Visibility.Collapsed;
|
||||
image4.Visibility = Visibility.Collapsed;
|
||||
if (isMole)
|
||||
{
|
||||
image1.Visibility = Visibility.Visible;
|
||||
image3.Visibility = Visibility.Collapsed;
|
||||
|
||||
//ShowGif(controller1 , 0);
|
||||
controller1.Play();
|
||||
Task.Delay(1450).ContinueWith(_ =>
|
||||
{
|
||||
controller1.Pause();
|
||||
controller1.GotoFrame(0);
|
||||
_isCharacterVisible = false;
|
||||
}, TaskScheduler.FromCurrentSynchronizationContext());
|
||||
//image3.Visibility = Visibility.Collapsed;
|
||||
// 显示新图片
|
||||
if (targetImage != null) {
|
||||
ImageBehavior.SetRepeatBehavior(targetImage, new RepeatBehavior(2));
|
||||
ImageBehavior.SetRepeatBehavior(targetImage, new RepeatBehavior(1));
|
||||
targetImage.Visibility = Visibility.Visible;
|
||||
_currentImage = targetImage;
|
||||
ImageBehavior.GetAnimationController(targetImage).Play();
|
||||
}
|
||||
else
|
||||
{
|
||||
//ShowGif(controller2 , 0);
|
||||
image3.Visibility = Visibility.Visible;
|
||||
image1.Visibility = Visibility.Collapsed;
|
||||
controller3.Play();
|
||||
Task.Delay(1300).ContinueWith(_ =>
|
||||
{
|
||||
controller3.Pause();
|
||||
controller3.GotoFrame(0);
|
||||
_isCharacterVisible = false;
|
||||
}, TaskScheduler.FromCurrentSynchronizationContext());
|
||||
ImageBehavior.SetRepeatBehavior(image1, new RepeatBehavior(2));
|
||||
ImageBehavior.SetRepeatBehavior(image1, new RepeatBehavior(1));
|
||||
image1.Visibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏所有角色
|
||||
/// </summary>
|
||||
private void HideAllCharacters()
|
||||
{
|
||||
//image1.Visibility = Visibility.Collapsed;
|
||||
image2.Visibility = Visibility.Collapsed;
|
||||
//image3.Visibility = Visibility.Collapsed;
|
||||
image4.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理打击
|
||||
/// </summary>
|
||||
private void ProcessHit()
|
||||
{
|
||||
if (!_isCharacterVisible || _isProcessingHit) return;
|
||||
|
||||
_isProcessingHit = true;
|
||||
image1.Visibility = Visibility.Collapsed;
|
||||
image3.Visibility = Visibility.Collapsed;
|
||||
|
||||
if (_currentCharacter == CharacterType.Mole)
|
||||
{
|
||||
// 打中地鼠
|
||||
image2.Visibility = Visibility.Visible;
|
||||
image4.Visibility = Visibility.Collapsed;
|
||||
controller2.Play();
|
||||
// 分数+10
|
||||
_score += 10;
|
||||
UpdateScoreDisplay();
|
||||
UpdateExternalScoreList();
|
||||
|
||||
// 发送分数改变事件
|
||||
ScoreChanged?.Invoke(Index, _score);
|
||||
Task.Delay(1500).ContinueWith(_ =>
|
||||
{
|
||||
controller2.Pause();
|
||||
controller2.GotoFrame(controller2.FrameCount - 1);
|
||||
_isCharacterVisible = false;
|
||||
_currentCharacter = CharacterType.None;
|
||||
_isProcessingHit = false;
|
||||
|
||||
// 安排下一次出现
|
||||
ScheduleNextAppearance();
|
||||
}, TaskScheduler.FromCurrentSynchronizationContext());
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
else if (_currentCharacter == CharacterType.Rabbit)
|
||||
{
|
||||
// 打中兔子(干扰)
|
||||
image2.Visibility = Visibility.Visible;
|
||||
image4.Visibility = Visibility.Collapsed;
|
||||
controller4.Play();
|
||||
// 分数-10
|
||||
_score -= 5;
|
||||
UpdateScoreDisplay();
|
||||
UpdateExternalScoreList();
|
||||
|
||||
// 发送分数改变事件
|
||||
ScoreChanged?.Invoke(Index, _score);
|
||||
Task.Delay(1500).ContinueWith(_ =>
|
||||
{
|
||||
controller4.Pause();
|
||||
controller4.GotoFrame(controller4.FrameCount - 1);
|
||||
_isCharacterVisible = false;
|
||||
_currentCharacter = CharacterType.None;
|
||||
_isProcessingHit = false;
|
||||
|
||||
// 安排下一次出现
|
||||
ScheduleNextAppearance();
|
||||
}, TaskScheduler.FromCurrentSynchronizationContext());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 超时未打击
|
||||
/// </summary>
|
||||
private void HandleTimeout()
|
||||
{
|
||||
if (_isProcessingHit) return;
|
||||
|
||||
_isCharacterVisible = false;
|
||||
_currentCharacter = CharacterType.None;
|
||||
|
||||
HideAllCharacters();
|
||||
|
||||
// 安排下一次出现
|
||||
ScheduleNextAppearance();
|
||||
}
|
||||
|
||||
private void ShowGif(ImageAnimationController controller , double number)
|
||||
{
|
||||
//ImageBehavior.SetRepeatBehavior(gif, new RepeatBehavior(2));
|
||||
//ImageBehavior.SetRepeatBehavior(gif, new RepeatBehavior(1));
|
||||
//ImageBehavior.SetAutoStart(gif, true);
|
||||
////播放完成跳转到第一个画面
|
||||
//Task.Delay(2000).ContinueWith(_ => {
|
||||
// gif.Dispatcher.Invoke(() =>
|
||||
// {
|
||||
// var controller = ImageBehavior.GetAnimationController(gif);
|
||||
// //ImageBehavior.SetAutoStart(gif, false);
|
||||
|
||||
// controller.GotoFrame(0);
|
||||
// });
|
||||
|
||||
//});
|
||||
|
||||
|
||||
controller.Play();
|
||||
Task.Delay(1500).ContinueWith(_ =>
|
||||
}
|
||||
|
||||
//当状态为2或4时候 不处理
|
||||
private void TimeDown1(object? sender, RoutedEventArgs? e)
|
||||
{
|
||||
//MessageBox.Show("播放完啦");// 弹提示框22
|
||||
if(ImageState == "2" || ImageState == "4" )
|
||||
{
|
||||
controller.Pause();
|
||||
if(number == 0)
|
||||
{
|
||||
controller.GotoFrame(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
controller.GotoFrame(controller.FrameCount - 1);
|
||||
}
|
||||
}, TaskScheduler.FromCurrentSynchronizationContext());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新分数显示
|
||||
/// </summary>
|
||||
private void UpdateScoreDisplay()
|
||||
{
|
||||
NumberText.Text = _score.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新计时器显示
|
||||
/// </summary>
|
||||
private void UpdateTimerDisplay()
|
||||
{
|
||||
TimerText.Text = _gameTime.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查触发值变化
|
||||
/// </summary>
|
||||
private bool CheckTriggerValueChanged()
|
||||
{
|
||||
// 检测触发值是否发生变化
|
||||
// 根据实际需求调整检测逻辑
|
||||
double currentValue = TriggerValue;
|
||||
bool hasChanged = Math.Abs(currentValue - _lastTriggerValue) > 0.001;
|
||||
|
||||
if (hasChanged)
|
||||
{
|
||||
_lastTriggerValue = currentValue;
|
||||
return;
|
||||
}
|
||||
|
||||
return hasChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否在有效打击窗口内
|
||||
/// </summary>
|
||||
private bool IsWithinHitWindow()
|
||||
{
|
||||
if (!_isCharacterVisible) return false;
|
||||
|
||||
TimeSpan elapsed = DateTime.Now - _characterAppearTime;
|
||||
return elapsed.TotalMilliseconds <= 2100;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 事件处理
|
||||
|
||||
/// <summary>
|
||||
/// Index属性改变回调
|
||||
/// </summary>
|
||||
private static void OnIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var control = d as WhackAMoleUserControl;
|
||||
control?.OnPropertyChanged(nameof(Index));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// IsActive属性改变回调
|
||||
/// </summary>
|
||||
private static void OnIsActiveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var control = d as WhackAMoleUserControl;
|
||||
if (control != null)
|
||||
else
|
||||
{
|
||||
if ((bool)e.NewValue)
|
||||
{
|
||||
control.StartGame();
|
||||
}
|
||||
else
|
||||
{
|
||||
control.StopGame();
|
||||
}
|
||||
Task.Delay(1300);
|
||||
ImageBehavior.GetAnimationController(image1).Pause();
|
||||
ImageBehavior.GetAnimationController(image2).Pause();
|
||||
ImageBehavior.GetAnimationController(image3).Pause();
|
||||
ImageBehavior.GetAnimationController(image4).Pause();
|
||||
ImageBehavior.SetRepeatBehavior(image1, new RepeatBehavior(2));
|
||||
ImageBehavior.SetRepeatBehavior(image1, new RepeatBehavior(1));
|
||||
image1.Visibility = Visibility.Visible;
|
||||
image2.Visibility = Visibility.Hidden;
|
||||
image3.Visibility = Visibility.Hidden;
|
||||
image4.Visibility = Visibility.Hidden;
|
||||
ImageState = "0";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TriggerValue属性改变回调
|
||||
/// </summary>
|
||||
private static void OnTriggerValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
private void TimeDown(object? sender, RoutedEventArgs? e)
|
||||
{
|
||||
var control = d as WhackAMoleUserControl;
|
||||
control?.OnTriggerValueChangedHandler();
|
||||
//MessageBox.Show("播放完啦");// 弹提示框22
|
||||
Task.Delay(1300);
|
||||
ImageBehavior.GetAnimationController(image1).Pause();
|
||||
ImageBehavior.GetAnimationController(image2).Pause();
|
||||
ImageBehavior.GetAnimationController(image3).Pause();
|
||||
ImageBehavior.GetAnimationController(image4).Pause();
|
||||
ImageBehavior.SetRepeatBehavior(image1, new RepeatBehavior(2));
|
||||
ImageBehavior.SetRepeatBehavior(image1, new RepeatBehavior(1));
|
||||
image1.Visibility = Visibility.Visible;
|
||||
image2.Visibility = Visibility.Hidden;
|
||||
image3.Visibility = Visibility.Hidden;
|
||||
image4.Visibility = Visibility.Hidden;
|
||||
ImageState = "0";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 触发值改变处理
|
||||
/// </summary>
|
||||
private void OnTriggerValueChangedHandler()
|
||||
{
|
||||
// 当检测到触发值变化且在有效窗口内时处理打击
|
||||
if (IsActive && IsWithinHitWindow())
|
||||
{
|
||||
ProcessHit();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 游戏计时器tick
|
||||
/// </summary>
|
||||
private void GameTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
_gameTime--;
|
||||
UpdateTimerDisplay();
|
||||
|
||||
if (_gameTime <= 0)
|
||||
{
|
||||
StopGame();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 角色出现计时器tick
|
||||
/// </summary>
|
||||
private void AppearanceTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
_appearanceTimer.Stop();
|
||||
|
||||
if (IsActive && !_isCharacterVisible && !_isProcessingHit)
|
||||
{
|
||||
ShowCharacter();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打击检测计时器tick
|
||||
/// </summary>
|
||||
private void HitDetectionTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
// 检测是否超时未打击
|
||||
if (_isCharacterVisible && !_isProcessingHit)
|
||||
{
|
||||
TimeSpan elapsed = DateTime.Now - _characterAppearTime;
|
||||
if (elapsed.TotalMilliseconds > 2100)
|
||||
{
|
||||
HandleTimeout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 属性改变通知
|
||||
/// </summary>
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 公共方法
|
||||
|
||||
/// <summary>
|
||||
/// 手动开始游戏
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 手动停止游戏
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
IsActive = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置分数
|
||||
/// </summary>
|
||||
public void ResetScore()
|
||||
{
|
||||
_score = 0;
|
||||
UpdateScoreDisplay();
|
||||
UpdateExternalScoreList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置外部上下文
|
||||
/// </summary>
|
||||
/// <param name="context">外部上下文对象</param>
|
||||
public void SetContext(dynamic context)
|
||||
{
|
||||
_whackAMoleContext = context;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
BIN
Wpf_AiSportsMicrospace/Resources/Img/play_img/whack_mole.png
Normal file
BIN
Wpf_AiSportsMicrospace/Resources/Img/play_img/whack_mole.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 237 KiB |
@ -60,7 +60,8 @@ namespace Wpf_AiSportsMicrospace
|
||||
});
|
||||
coverFlow.Images.Add(new CoverFlowItem
|
||||
{
|
||||
ImageUri = GetResourceUri("Album/home_history.png"),
|
||||
//ImageUri = GetResourceUri("Album/home_history.png"),
|
||||
ImageUri = GetResourceUri("play_img/whack_mole.png"),
|
||||
ProgressColor1 = "#e73d42",
|
||||
ProgressColor2 = "#215bc7"
|
||||
});
|
||||
@ -164,7 +165,6 @@ namespace Wpf_AiSportsMicrospace
|
||||
//mainWin?.SwitchPageWithMaskAnimation(newPage, true);
|
||||
|
||||
//var newPage = new BambooDragonfly();
|
||||
//var newPage = new WhackAMole();
|
||||
mainWin?.SwitchPageWithMaskAnimation(newPage, true);
|
||||
}
|
||||
else if (coverFlow.SelectedIndex == 1)
|
||||
@ -175,8 +175,8 @@ namespace Wpf_AiSportsMicrospace
|
||||
else
|
||||
{
|
||||
//var newPage = new TrainingRecords();
|
||||
//var newPage = new WhackAMole();
|
||||
var newPage = new StandingLeap();
|
||||
var newPage = new WhackAMole();
|
||||
//var newPage = new StandingLeap();
|
||||
mainWin?.SwitchPageWithMaskAnimation(newPage, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,37 +246,37 @@ namespace Wpf_AiSportsMicrospace.Views.JumpRope
|
||||
//UpdateCountdown();
|
||||
|
||||
//开始人脸识别=============================================
|
||||
Action<VideoFrame> handler = null;
|
||||
//Action<VideoFrame> handler = null;
|
||||
|
||||
handler = async (frame) =>
|
||||
{
|
||||
double[] xValues = [.. _musicJumpRopeContext.CirclePositions.Select(p => p.XNorm)];
|
||||
var buffer = frame.GetImageBuffer(ImageFormat.Jpeg).ToArray();
|
||||
var studentList = Utils.FacialRecognition(buffer, xValues);
|
||||
//handler = async (frame) =>
|
||||
//{
|
||||
// double[] xValues = [.. _musicJumpRopeContext.CirclePositions.Select(p => p.XNorm)];
|
||||
// var buffer = frame.GetImageBuffer(ImageFormat.Jpeg).ToArray();
|
||||
// var studentList = Utils.FacialRecognition(buffer, xValues);
|
||||
|
||||
if (studentList != null && studentList.Count > 0)
|
||||
{
|
||||
// 解绑事件
|
||||
_mainWin.FacialRecognitionEvent -= handler;
|
||||
name1.Text = studentList[0]?.StudentName ?? "一号玩家";
|
||||
name2.Text = studentList[1]?.StudentName ?? "二号玩家";
|
||||
if (studentList.Count > 1 && studentList[0].Photo != "")
|
||||
{
|
||||
await LoadImageFromUrlAsync(studentList[0]?.Photo ?? "", avatar1);
|
||||
}
|
||||
if (studentList.Count > 2 && studentList[1].Photo != "")
|
||||
{
|
||||
await LoadImageFromUrlAsync(studentList[1]?.Photo ?? "", avatar2);
|
||||
}
|
||||
// if (studentList != null && studentList.Count > 0)
|
||||
// {
|
||||
// // 解绑事件
|
||||
// _mainWin.FacialRecognitionEvent -= handler;
|
||||
// name1.Text = studentList[0]?.StudentName ?? "一号玩家";
|
||||
// name2.Text = studentList[1]?.StudentName ?? "二号玩家";
|
||||
// if (studentList.Count > 1 && studentList[0].Photo != "")
|
||||
// {
|
||||
// await LoadImageFromUrlAsync(studentList[0]?.Photo ?? "", avatar1);
|
||||
// }
|
||||
// if (studentList.Count > 2 && studentList[1].Photo != "")
|
||||
// {
|
||||
// await LoadImageFromUrlAsync(studentList[1]?.Photo ?? "", avatar2);
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
// 这里可以继续处理 studentList
|
||||
};
|
||||
// // 这里可以继续处理 studentList
|
||||
//};
|
||||
|
||||
//// 绑定事件
|
||||
_mainWin.FacialRecognitionEvent += handler;
|
||||
////// 绑定事件
|
||||
//_mainWin.FacialRecognitionEvent += handler;
|
||||
|
||||
await Task.Delay(3000);
|
||||
FinishCountdown();
|
||||
|
||||
@ -36,9 +36,12 @@
|
||||
</LinearGradientBrush>
|
||||
</TextBlock.Foreground>
|
||||
</TextBlock>-->
|
||||
<Grid Height="1080" Width="1920" x:Name="userBox"/>
|
||||
|
||||
<Grid Width="200" Height="120" VerticalAlignment="Top" HorizontalAlignment="Center" Margin="00,150,0,0" Visibility="Visible" x:Name="countdownGrid">
|
||||
<!--<Grid Height="1080" Width="1920" x:Name="userBox"/>-->
|
||||
<Grid Height="1080" Width="1920" x:Name="userListBox">
|
||||
|
||||
|
||||
</Grid>
|
||||
<Grid Width="200" Height="120" VerticalAlignment="Top" HorizontalAlignment="Center" Margin="00,150,0,0" Visibility="Hidden" x:Name="countdownGrid">
|
||||
<Border Background="#000" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CornerRadius="30" Opacity="0.6" />
|
||||
<TextBlock x:Name="countdownText"
|
||||
Text="60"
|
||||
@ -95,7 +98,7 @@
|
||||
Margin="0,168"
|
||||
/>
|
||||
|
||||
<Grid Width="1346" Height="520" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,331,0,0" x:Name="ScoreGrid">
|
||||
<Grid Width="1346" Height="550" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,331,0,0" x:Name="ScoreGrid">
|
||||
<Border Background="#FEDE50" CornerRadius="0,0,20,20"/>
|
||||
<Grid HorizontalAlignment="Center" VerticalAlignment="Top" Width="1344" Height="71">
|
||||
<Border Background="#f7f7f7"/>
|
||||
|
||||
@ -7,6 +7,7 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using SportExpand;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows;
|
||||
@ -53,7 +54,7 @@ namespace Views.SquatFu
|
||||
_WhackAMoleContext = new WhackAMoleContext();
|
||||
}
|
||||
|
||||
private async void UserControl_Loaded(object sender, RoutedEventArgs e)
|
||||
private async void UserControl_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 使用局部变量保存事件处理方法,以便解绑
|
||||
Action<VideoFrame> handler = null;
|
||||
@ -78,9 +79,10 @@ namespace Views.SquatFu
|
||||
_WhackAMoleContext.CirclePositions = pointlist;
|
||||
|
||||
DrawCirclesWithText();
|
||||
|
||||
// 播放音乐
|
||||
PlayMusic("raisehand.mp3");
|
||||
_mainWin.HumanFrameUpdated += OnHumanFrameUpdated;
|
||||
|
||||
}
|
||||
|
||||
private void UserControl_Unloaded(object sender, RoutedEventArgs e)
|
||||
@ -106,9 +108,11 @@ namespace Views.SquatFu
|
||||
ShowCenterTip(imgPath, TimeSpan.FromSeconds(3));
|
||||
|
||||
// 监听播放完成事件
|
||||
_mediaPlayer.MediaEnded += MediaPlayer_MediaEnded;
|
||||
_mediaPlayer.MediaEnded += MediaPlayer_MediaEnded;
|
||||
//_mainWin.WebcamClient.StartExtract();
|
||||
_mediaPlayer.Play();
|
||||
_mainWin.HumanFrameUpdated += OnHumanFrameUpdated;
|
||||
|
||||
}
|
||||
private void ShowCenterTip(string imagePath, TimeSpan duration)
|
||||
{
|
||||
@ -126,7 +130,7 @@ namespace Views.SquatFu
|
||||
tipImage.Height = 1080 * 0.6; // 高度为 Canvas 高度的 60%
|
||||
|
||||
// 将图片添加到 Overlay Canvas
|
||||
userBox.Children.Add(tipImage);
|
||||
userListBox.Children.Add(tipImage);
|
||||
|
||||
// 渐变出现动画
|
||||
var fadeInAnimation = new DoubleAnimation
|
||||
@ -157,7 +161,7 @@ namespace Views.SquatFu
|
||||
// 完成后移除图片
|
||||
fadeOutAnimation.Completed += (s, e) =>
|
||||
{
|
||||
userBox.Children.Remove(tipImage);
|
||||
userListBox.Children.Remove(tipImage);
|
||||
};
|
||||
});
|
||||
});
|
||||
@ -178,7 +182,7 @@ namespace Views.SquatFu
|
||||
try
|
||||
{
|
||||
if (humans == null || humans.Count == 0) return;
|
||||
|
||||
|
||||
switch (_currentGameState)
|
||||
{
|
||||
case GameState.NotStarted: // 未开始
|
||||
@ -198,7 +202,7 @@ namespace Views.SquatFu
|
||||
}
|
||||
|
||||
int rightWaving = sportOperate.VerifyRightWavingAction(humans);
|
||||
if (rightWaving >= 3)
|
||||
if (rightWaving >= 3 && RankingGrid.Visibility != Visibility.Visible)
|
||||
{
|
||||
switch (rightWaving)
|
||||
{
|
||||
@ -206,13 +210,13 @@ namespace Views.SquatFu
|
||||
StartCountdown(3);
|
||||
_isCountdownStarted = true; // 倒计时开始,停止左手检测
|
||||
break;
|
||||
case (int)WavingAction.Raising:
|
||||
UpdateCountdown();
|
||||
break;
|
||||
case (int)WavingAction.RaiseHand:
|
||||
FinishCountdown();
|
||||
_currentGameState = GameState.Running; // 倒计时完成 → 游戏开始
|
||||
break;
|
||||
//case (int)WavingAction.Raising:
|
||||
// UpdateCountdown();
|
||||
// break;
|
||||
//case (int)WavingAction.RaiseHand:
|
||||
// FinishCountdown();
|
||||
// _currentGameState = GameState.Running; // 倒计时完成 → 游戏开始
|
||||
// break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -220,6 +224,19 @@ namespace Views.SquatFu
|
||||
case GameState.Running: // 游戏进行中
|
||||
UpdateCircleCounts(humans);
|
||||
break;
|
||||
case GameState.Finished: // 游戏结束
|
||||
int leftWave = sportOperate.VerifyLeftWavingAction(humans);
|
||||
if (leftWave == 5)
|
||||
{
|
||||
_mainWin.HumanFrameUpdated -= OnHumanFrameUpdated;
|
||||
_mainWin.WebcamClient.StopExtract();
|
||||
|
||||
// 举左手逻辑,例如结束动画或退出
|
||||
var newPage = new Home();
|
||||
_mainWin?.SwitchPageWithMaskAnimation(newPage, true);
|
||||
return; // 提前退出
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -230,19 +247,21 @@ namespace Views.SquatFu
|
||||
|
||||
private double _currentCountdown = 3600;
|
||||
private DateTime _lastUpdateTime = DateTime.Now;
|
||||
private void StartCountdown(int start = 3)
|
||||
private async void StartCountdown(int start = 3)
|
||||
{
|
||||
_currentGameState = GameState.Running;
|
||||
|
||||
_mainWin.ShowCountDownAnimation();
|
||||
|
||||
Utils.PlayBackgroundMusic("countdown_3.mp3", false);
|
||||
|
||||
//开始人脸识别=============================================
|
||||
//Action<VideoFrame> handler = null;
|
||||
//开始人脸识别 =============================================
|
||||
//Action < VideoFrame > handler = null;
|
||||
|
||||
//handler = async (frame) =>
|
||||
//{
|
||||
// var buffer = frame.GetImageBuffer(ImageFormat.Jpeg).ToArray();
|
||||
// double[] xValues = [.. _groupJumpRopeContext.CirclePositions.Select(p => p.XNorm)];
|
||||
// double[] xValues = [.. _WhackAMoleContext.CirclePositions.Select(p => p.XNorm)];
|
||||
|
||||
// var studentList = Utils.FacialRecognition(buffer, xValues);
|
||||
|
||||
@ -256,15 +275,17 @@ namespace Views.SquatFu
|
||||
// var student = studentList[i];
|
||||
// if (student != null)
|
||||
// {
|
||||
// _groupJumpRopeContext.UserList[i].DisplayText = student.StudentName;
|
||||
// _WhackAMoleContext.UserList[i].NameText = student.StudentName;
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
//};
|
||||
|
||||
//// 绑定事件
|
||||
// 绑定事件
|
||||
//_mainWin.FacialRecognitionEvent += handler;
|
||||
await Task.Delay(3000);
|
||||
FinishCountdown();
|
||||
}
|
||||
|
||||
private void UpdateCountdown()
|
||||
@ -285,19 +306,62 @@ namespace Views.SquatFu
|
||||
}
|
||||
}
|
||||
|
||||
private System.Timers.Timer _gameTimer;
|
||||
private Random _random = new Random();
|
||||
|
||||
private async void FinishCountdown()
|
||||
{
|
||||
countdownText.Text = "GO!";
|
||||
countdownGrid.Visibility = Visibility.Hidden;
|
||||
_WhackAMoleContext.UserList.ForEach(x =>
|
||||
{
|
||||
x.Start();
|
||||
});
|
||||
|
||||
|
||||
// 播放背景音乐(循环)
|
||||
Utils.PlayBackgroundMusic("homeprojectselected1.mp3", true);
|
||||
// 启动60秒倒计时(独立任务)
|
||||
StartGameCountdown(60);
|
||||
|
||||
// 开始游戏定时器,每2-3秒随机选取用户出现地鼠或兔子
|
||||
StartGameTimer();
|
||||
}
|
||||
|
||||
private void StartGameTimer()
|
||||
{
|
||||
_gameTimer = new System.Timers.Timer();
|
||||
_gameTimer.Elapsed += OnGameTimerElapsed;
|
||||
_gameTimer.AutoReset = true;
|
||||
|
||||
// 设置第一次触发时间为2-3秒之间的随机值
|
||||
int firstInterval = _random.Next(2000, 3000);
|
||||
_gameTimer.Interval = firstInterval;
|
||||
_gameTimer.Start();
|
||||
}
|
||||
|
||||
private void OnGameTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
// 随机选取2-4个用户
|
||||
int userCount = _random.Next(2, 5); // 2-4个
|
||||
int actualCount = Math.Min(userCount, _WhackAMoleContext.UserList.Count);
|
||||
|
||||
// 获取所有用户索引
|
||||
var allIndices = Enumerable.Range(0, _WhackAMoleContext.UserList.Count).ToList();
|
||||
// 随机打乱顺序
|
||||
var shuffled = allIndices.OrderBy(x => _random.Next()).Take(actualCount).ToList();
|
||||
|
||||
foreach (var index in shuffled)
|
||||
{
|
||||
// 随机决定是地鼠(1)还是兔子(3)
|
||||
int imageState = _random.Next(2) == 0 ? 1 : 3;
|
||||
if(_WhackAMoleContext.UserList[index].ImageState == "0")
|
||||
{
|
||||
_WhackAMoleContext.UserList[index].ImageState = imageState.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
// 设置下一次触发时间为2-3秒之间的随机值
|
||||
_gameTimer.Interval = _random.Next(2000, 3000);
|
||||
});
|
||||
}
|
||||
double Tiggle = 1;
|
||||
private async void StartGameCountdown(int seconds)
|
||||
@ -311,11 +375,11 @@ namespace Views.SquatFu
|
||||
}
|
||||
|
||||
countdownGrid.Visibility = Visibility.Hidden;
|
||||
|
||||
_gameTimer.Stop();
|
||||
_WhackAMoleContext.UserList.ForEach(x =>
|
||||
{
|
||||
Tiggle += 1;
|
||||
x.TriggerValue = Tiggle;
|
||||
//x.TriggerValue = Tiggle;
|
||||
});
|
||||
|
||||
_mainWin.HumanFrameUpdated -= OnHumanFrameUpdated;
|
||||
@ -325,13 +389,13 @@ namespace Views.SquatFu
|
||||
ShowRankingBoard(RankingItemList);
|
||||
Utils.StopBackgroundMusic();
|
||||
|
||||
_currentGameState = GameState.NotStarted;
|
||||
_currentGameState = GameState.Finished;
|
||||
|
||||
_isCountdownStarted = false;
|
||||
_mainWin.HumanFrameUpdated += OnHumanFrameUpdated;
|
||||
_mainWin.WebcamClient.StartExtract();
|
||||
}
|
||||
|
||||
|
||||
private DateTime? _raiseStartTime;
|
||||
private bool _firstHandTriggered;
|
||||
private int _lastCountdownSecond = 3;
|
||||
@ -346,7 +410,7 @@ namespace Views.SquatFu
|
||||
}
|
||||
private void DrawCirclesWithText()
|
||||
{
|
||||
userBox.Children.Clear();
|
||||
userListBox.Children.Clear();
|
||||
_WhackAMoleContext.Sports.Clear();
|
||||
_WhackAMoleContext.UserList.Clear();
|
||||
_WhackAMoleContext.UserNumberList.Clear();
|
||||
@ -355,32 +419,59 @@ namespace Views.SquatFu
|
||||
for (int i = 0; i < _WhackAMoleContext.CirclePositions.Count; i++)
|
||||
{
|
||||
var pos = _WhackAMoleContext.CirclePositions[i];
|
||||
double x = pos.XNorm ;
|
||||
double y = pos.YNorm ;
|
||||
double x = pos.XNorm;
|
||||
double y = pos.YNorm;
|
||||
|
||||
// 绘制发光圆
|
||||
var userItem = AddUserItem(x, y, i);
|
||||
AddUserItem(x, y, i);
|
||||
|
||||
// 绑定运动对象
|
||||
var sport = new FrontSquat();
|
||||
|
||||
Debug.WriteLine($"userListBox长度:{userListBox.Children.Count}");
|
||||
//Optimizes.Optimizeing(sport);
|
||||
|
||||
//var sport = SportBase.Create("rope-skipping");
|
||||
|
||||
int indexCopy = i;
|
||||
var currentItem = userItem;
|
||||
//var currentItem = userItem;
|
||||
|
||||
// 订阅事件
|
||||
// 订阅事件
|
||||
sport.OnTicked += (count, times) =>
|
||||
{
|
||||
// 更新UI
|
||||
//userItem.NumberText = count.ToString();
|
||||
// 更新数字源
|
||||
_WhackAMoleContext.UserNumberList[indexCopy] = count.ToString();
|
||||
// 改变状态为“跳绳中”
|
||||
if (userItem.TriggerValue != 2)
|
||||
userItem.TriggerValue = 2;
|
||||
// 获取当前用户的ImageState
|
||||
var imageState = _WhackAMoleContext.UserList[indexCopy].ImageState;
|
||||
|
||||
// 获取当前分数
|
||||
int currentScore = 0;
|
||||
int.TryParse(_WhackAMoleContext.UserNumberList[indexCopy], out currentScore);
|
||||
|
||||
// 根据ImageState判断加分还是减分
|
||||
if (imageState == "1") // 地鼠:加10分
|
||||
{
|
||||
currentScore += 10;
|
||||
}
|
||||
else if (imageState == "3") // 兔子:减5分
|
||||
{
|
||||
currentScore -= 5;
|
||||
// 分数不能为负数
|
||||
//if (currentScore < 0) currentScore = 0;
|
||||
}
|
||||
|
||||
// 更新分数
|
||||
string newScore = currentScore.ToString();
|
||||
_WhackAMoleContext.UserNumberList[indexCopy] = newScore;
|
||||
_WhackAMoleContext.UserList[indexCopy].NumberText = newScore;
|
||||
|
||||
// 如果打中地鼠或兔子,重置ImageState为0
|
||||
if (imageState == "1")
|
||||
{
|
||||
_WhackAMoleContext.UserList[indexCopy].ImageState = "2";
|
||||
}
|
||||
else if(imageState == "3")
|
||||
{
|
||||
_WhackAMoleContext.UserList[indexCopy].ImageState = "4";
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
sport.Start();
|
||||
@ -424,24 +515,39 @@ namespace Views.SquatFu
|
||||
}
|
||||
}
|
||||
|
||||
private WhackAMoleUserControl AddUserItem(double centerX, double centerY, int index)
|
||||
void AddUserItem(double centerX, double centerY, int index)
|
||||
{
|
||||
var userItem = new WhackAMoleUserControl();
|
||||
userItem.Width = 400;
|
||||
userItem.Height = 600;
|
||||
//userItem.DisplayText = _groupJumpRopeContext.UseNameList[index]; //名字
|
||||
userItem.VerticalAlignment = VerticalAlignment.Top;
|
||||
userItem.HorizontalAlignment = HorizontalAlignment.Left;
|
||||
userItem.Index = index;
|
||||
//var userItem = new WhackAMoleUserControl();
|
||||
//userItem.Width = 400;
|
||||
//userItem.Height = 600;
|
||||
//userItem.NameText = _WhackAMoleContext.UserNameList[index]; //名字
|
||||
//userItem.VerticalAlignment = VerticalAlignment.Top;
|
||||
//userItem.HorizontalAlignment = HorizontalAlignment.Left;
|
||||
//userItem.Index = index;
|
||||
//userItem.ImageState = "1";
|
||||
//userItem.Margin = new Thickness(centerX - (index == 0 ? 80 : index == 6 ? 190 : 135), centerY - 540, 0, 0);
|
||||
userItem.Margin = new Thickness(centerX , centerY - 600 - 50, 0, 0);
|
||||
userBox.Children.Add(userItem);
|
||||
var userItem = new WhackAMoleUserControl
|
||||
{
|
||||
Width = 410,
|
||||
Height = 580,
|
||||
NameText = _WhackAMoleContext.UserNameList[index],
|
||||
VerticalAlignment = VerticalAlignment.Top,
|
||||
HorizontalAlignment = HorizontalAlignment.Left,
|
||||
ImageState = "0"
|
||||
};
|
||||
|
||||
var top = (centerX - 200) > 0 ? (centerX - 200) : 0;
|
||||
|
||||
|
||||
userItem.Margin = new Thickness(top, centerY - 570, 0, 0);
|
||||
userListBox.Children.Add(userItem);
|
||||
_WhackAMoleContext.UserList.Add(userItem);
|
||||
_WhackAMoleContext.UserNumberList.Add("0");
|
||||
return userItem; //
|
||||
//return userItem; //
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void ShowRankingBoard(List<RankItem> list)
|
||||
{
|
||||
var scoreGrid = FindName("ScoreGrid") as Grid;
|
||||
|
||||
@ -69,13 +69,16 @@
|
||||
<None Remove="Resources\Img\play_img\play_jump.png" />
|
||||
<None Remove="Resources\Img\play_img\play_music.png" />
|
||||
<None Remove="Resources\Img\play_img\play_vs.png" />
|
||||
<None Remove="Resources\Img\play_img\whack_mole.png" />
|
||||
<None Remove="Resources\Img\play_img\whack_mole\+10.gif" />
|
||||
<None Remove="Resources\Img\play_img\whack_mole\-10.gif" />
|
||||
<None Remove="Resources\Img\play_img\whack_mole\hit_u.gif" />
|
||||
<None Remove="Resources\Img\play_img\whack_mole\mole_u.gif" />
|
||||
<None Remove="Resources\Img\play_img\whack_mole\name-bot.png" />
|
||||
<None Remove="Resources\Img\play_img\whack_mole\play_bg.png" />
|
||||
<None Remove="Resources\Img\play_img\whack_mole\rabbit_hit_u.gif" />
|
||||
<None Remove="Resources\Img\play_img\whack_mole\rabbit_u.gif" />
|
||||
<None Remove="Resources\Img\play_img\whack_mole\score-bg.png" />
|
||||
<None Remove="Resources\Img\play_img\whack_mole\title.png" />
|
||||
<None Remove="Resources\Img\play_img\whack_mole\title_bg.png" />
|
||||
<None Remove="Resources\Img\test_img\jump_long\bottom.png" />
|
||||
@ -138,6 +141,9 @@
|
||||
<Resource Include="Resources\app.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\Img\play_img\whack_mole.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\Img\play_img\whack_mole\+10.gif">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
@ -150,6 +156,9 @@
|
||||
<Resource Include="Resources\Img\play_img\whack_mole\mole_u.gif">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\Img\play_img\whack_mole\name-bot.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\Img\play_img\whack_mole\play_bg.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
@ -159,6 +168,9 @@
|
||||
<Resource Include="Resources\Img\play_img\whack_mole\rabbit_u.gif">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\Img\play_img\whack_mole\score-bg.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\Img\play_img\whack_mole\title.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user