You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
428 lines
15 KiB
428 lines
15 KiB
using KinectUtils;
|
|
using Lib;
|
|
using Microsoft.Kinect;
|
|
using MyGesturesBank;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Data;
|
|
using System.Windows.Documents;
|
|
using System.Windows.Ink;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Imaging;
|
|
using System.Windows.Navigation;
|
|
using System.Windows.Shapes;
|
|
using System.Windows.Threading;
|
|
|
|
|
|
namespace WpfApp
|
|
{
|
|
/// <summary>
|
|
/// Logique d'interaction pour MainWindow.xaml
|
|
/// </summary>
|
|
public partial class MainWindow : Window, INotifyPropertyChanged
|
|
{
|
|
// Déclaration des variables nécessaires
|
|
private int score = 0;
|
|
private string feedback = "";
|
|
private DispatcherTimer gameTimer;
|
|
private MediaPlayer mediaPlayer = new MediaPlayer();
|
|
private DispatcherTimer circleTimer;
|
|
private double circleSize = 100; // Taille initiale du cercle
|
|
private Random random = new Random();
|
|
private const double someThreshold = 50.0; // Par exemple, 50 pixels
|
|
|
|
private const int MaxCircles = 5; // Maximum de 5 cercles à l'écran
|
|
private const double CircleStartSize = 50.0; // Taille initiale du cercle
|
|
private const double ReductionAmount = 2.0; // De combien le cercle réduit à chaque tick
|
|
private const double MinimumCircleSize = 5.0; // Taille minimale avant de disparaître
|
|
|
|
private KinectManager kinectManager;
|
|
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
|
|
public KinectManager KinectManager
|
|
{
|
|
get { return kinectManager; }
|
|
set { kinectManager = value; }
|
|
}
|
|
private KinectStream _currentKinectStream;
|
|
public KinectStream CurrentKinectStream
|
|
{
|
|
get { return _currentKinectStream; }
|
|
set
|
|
{
|
|
_currentKinectStream = value;
|
|
OnPropertyChanged(nameof(CurrentKinectStream));
|
|
}
|
|
}
|
|
|
|
// Propriétés pour le score et le feedback
|
|
public int Score
|
|
{
|
|
get => score;
|
|
set
|
|
{
|
|
score = value;
|
|
OnPropertyChanged(nameof(Score));
|
|
scoreText.Text = score.ToString(); // Mise à jour de l'interface utilisateur
|
|
}
|
|
}
|
|
|
|
public string Feedback
|
|
{
|
|
get => feedback;
|
|
set
|
|
{
|
|
feedback = value;
|
|
OnPropertyChanged(nameof(Feedback));
|
|
feedbackText.Text = feedback; // Mise à jour de l'interface utilisateur
|
|
}
|
|
}
|
|
|
|
public void OnPropertyChanged(string propertyName)
|
|
{
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
}
|
|
|
|
private KinectStreamsFactory _factory;
|
|
public KinectStreamsFactory Factory
|
|
{
|
|
get { return _factory; }
|
|
set { _factory = value; }
|
|
}
|
|
|
|
public MainWindow()
|
|
{
|
|
InitializeComponent();
|
|
this.DataContext = this;
|
|
|
|
// Ajout d'un gestionnaire d'erreurs média
|
|
mediaPlayer.MediaFailed += MediaFailed;
|
|
|
|
KinectManager = new KinectManager();
|
|
|
|
Factory = new KinectStreamsFactory(KinectManager, skeletonCanvas);
|
|
CurrentKinectStream = Factory[KinectStreams.Color];
|
|
CurrentKinectStream.Start();
|
|
|
|
InitializeGame();
|
|
|
|
// Abonnement à l'événement GestureRecognized
|
|
// GestureManager.GestureRecognized += OnGestureRecognized;
|
|
}
|
|
|
|
private void InitializeGame()
|
|
{
|
|
// Configuration initiale de Kinect et préparation de l'UI
|
|
KinectManager = new KinectManager();
|
|
Factory = new KinectStreamsFactory(KinectManager, skeletonCanvas);
|
|
CurrentKinectStream = Factory[KinectStreams.Color];
|
|
CurrentKinectStream.Start();
|
|
|
|
// Initialisation des gestes Kinect ici
|
|
AllGesturesFactory allGesturesFactory = new AllGesturesFactory();
|
|
GestureManager.AddGestures(allGesturesFactory);
|
|
|
|
// Préparation des timers sans les démarrer
|
|
gameTimer = new DispatcherTimer();
|
|
gameTimer.Interval = TimeSpan.FromMilliseconds(50);
|
|
gameTimer.Tick += GameTimer_Tick;
|
|
// Ne pas démarrer le timer ici avec gameTimer.Start();
|
|
|
|
circleTimer = new DispatcherTimer();
|
|
circleTimer.Interval = TimeSpan.FromMilliseconds(100);
|
|
circleTimer.Tick += CircleTimer_Tick;
|
|
// Ne pas démarrer le timer ici avec circleTimer.Start();
|
|
|
|
// D'autres configurations initiales peuvent être ajoutées ici
|
|
}
|
|
|
|
|
|
private void MainWindow_Closing(object sender, CancelEventArgs e)
|
|
{
|
|
Debug.WriteLine(CurrentKinectStream.KinectManager.StatusText);
|
|
CurrentKinectStream.Stop();
|
|
}
|
|
|
|
private void ToColorImageStream(object sender, RoutedEventArgs e)
|
|
{
|
|
CurrentKinectStream.Stop();
|
|
CurrentKinectStream = Factory[KinectStreams.Color];
|
|
Debug.WriteLine(CurrentKinectStream.GetType().Name);
|
|
CurrentKinectStream.Start();
|
|
}
|
|
|
|
private void ToDepthImageStream(object sender, RoutedEventArgs e)
|
|
{
|
|
CurrentKinectStream.Stop();
|
|
CurrentKinectStream = Factory[KinectStreams.Depth];
|
|
Debug.WriteLine(CurrentKinectStream.GetType().Name);
|
|
CurrentKinectStream.Start();
|
|
}
|
|
|
|
private void ToInfraredImageStream(object sender, RoutedEventArgs e)
|
|
{
|
|
CurrentKinectStream.Stop();
|
|
CurrentKinectStream = Factory[KinectStreams.IR];
|
|
Debug.WriteLine(CurrentKinectStream.GetType().Name);
|
|
CurrentKinectStream.Start();
|
|
}
|
|
|
|
private void ToBodyImageStream(object sender, RoutedEventArgs e)
|
|
{
|
|
CurrentKinectStream.Stop();
|
|
CurrentKinectStream = Factory[KinectStreams.Body];
|
|
Debug.WriteLine(CurrentKinectStream.GetType().Name);
|
|
CurrentKinectStream.Start();
|
|
}
|
|
|
|
private void ToColorAndBodyImageStream(object sender, RoutedEventArgs e)
|
|
{
|
|
CurrentKinectStream.Stop();
|
|
CurrentKinectStream = Factory[KinectStreams.ColorAndBody];
|
|
Debug.WriteLine(CurrentKinectStream.GetType().Name);
|
|
CurrentKinectStream.Start();
|
|
}
|
|
|
|
private void GameTimer_Tick(object sender, EventArgs e)
|
|
{
|
|
// C'est ici que vous pouvez appeler CreateRandomCircle à des intervalles réguliers
|
|
CreateRandomCircle();
|
|
}
|
|
|
|
private void CircleTimer_Tick(object sender, EventArgs e)
|
|
{
|
|
// Réduisez la taille du cercle pour donner l'impression qu'il se "ferme"
|
|
if (circleSize > 0)
|
|
{
|
|
circleSize -= 2; // Ajustez cette valeur pour modifier la vitesse de réduction du cercle
|
|
clapCircle.Width = circleSize;
|
|
clapCircle.Height = circleSize;
|
|
}
|
|
else
|
|
{
|
|
// Si le cercle est trop petit, réinitialisez-le pour le prochain clap
|
|
ResetClapCircle();
|
|
}
|
|
}
|
|
|
|
private void CheckClapTiming()
|
|
{
|
|
// Supposons que le timing parfait est lorsque le cercle est entre 40 et 60 de taille
|
|
if (circleSize >= 40 && circleSize <= 60)
|
|
{
|
|
UpdateGameStatus("Parfait!", 100);
|
|
}
|
|
else if (circleSize > 60 && circleSize <= 80)
|
|
{
|
|
UpdateGameStatus("Bien", 50);
|
|
}
|
|
else
|
|
{
|
|
UpdateGameStatus("Raté", 0);
|
|
}
|
|
|
|
// Réinitialisez la taille du cercle pour le prochain clap
|
|
ResetClapCircle();
|
|
}
|
|
|
|
private void GameCanvas_Loaded(object sender, RoutedEventArgs e)
|
|
{
|
|
CenterClapCircle();
|
|
}
|
|
|
|
private void CenterClapCircle()
|
|
{
|
|
if (gameCanvas.ActualWidth == 0 || gameCanvas.ActualHeight == 0) return;
|
|
|
|
double centerX = (gameCanvas.ActualWidth - clapCircle.Width) / 2;
|
|
double centerY = (gameCanvas.ActualHeight - clapCircle.Height) / 2;
|
|
|
|
Canvas.SetLeft(clapCircle, centerX);
|
|
Canvas.SetTop(clapCircle, centerY);
|
|
}
|
|
|
|
private void ResetClapCircle()
|
|
{
|
|
circleSize = 100; // Réinitialiser la taille
|
|
clapCircle.Width = circleSize;
|
|
clapCircle.Height = circleSize;
|
|
circleTimer.Start(); // Redémarrer le timer pour réduire le cercle
|
|
}
|
|
|
|
private void UpdateGameStatus(string feedback, int points)
|
|
{
|
|
Feedback = feedback; // "Parfait!", "Bien", "Raté", etc.
|
|
Score += points; // Mettre à jour le score basé sur le feedback
|
|
}
|
|
|
|
private void StartGame()
|
|
{
|
|
try
|
|
{
|
|
// Chemin relatif au répertoire de sortie de l'application
|
|
mediaPlayer.Open(new Uri("Tutti-Frutti.mp3", UriKind.Relative));
|
|
mediaPlayer.MediaOpened += MediaOpened;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"Erreur lors de l'ouverture du fichier de musique : {ex.Message}");
|
|
}
|
|
|
|
// Configurez et démarrez le timer pour le cercle qui se réduit
|
|
circleTimer = new DispatcherTimer();
|
|
circleTimer.Interval = TimeSpan.FromMilliseconds(100); // Ajustez selon le rythme de la musique
|
|
circleTimer.Tick += CircleTimer_Tick;
|
|
circleTimer.Start();
|
|
GestureManager.StartAcquiringFrames(KinectManager);
|
|
}
|
|
|
|
public void OnGestureRecognizedHandler(object sender, GestureRecognizedEventArgs e)
|
|
{
|
|
// Ici, vous mettez le code pour traiter l'événement.
|
|
// Par exemple, afficher le nom du geste reconnu.
|
|
Console.WriteLine($"Geste reconnu : {e.GestureName}");
|
|
}
|
|
|
|
private void MediaOpened(object sender, EventArgs e)
|
|
{
|
|
mediaPlayer.Play();
|
|
|
|
ResetClapCircle();
|
|
CenterClapCircle(); // Appelez cette méthode pour centrer le cercle
|
|
|
|
Score = 0;
|
|
Feedback = "";
|
|
|
|
if (!gameTimer.IsEnabled) gameTimer.Start();
|
|
if (!circleTimer.IsEnabled) circleTimer.Start();
|
|
}
|
|
|
|
private void StopGame()
|
|
{
|
|
mediaPlayer.Stop();
|
|
gameTimer.Stop(); // Arrêter le timer du jeu
|
|
circleTimer.Stop(); // Arrêter le timer du cercle
|
|
Feedback = "Jeu terminé"; // Mettre à jour le feedback
|
|
}
|
|
|
|
private void RemoveCircleAtPosition(double x, double y)
|
|
{
|
|
Ellipse circleToRemove = null;
|
|
double minDistance = double.MaxValue;
|
|
|
|
foreach (Ellipse circle in gameCanvas.Children.OfType<Ellipse>())
|
|
{
|
|
double centerX = Canvas.GetLeft(circle) + circle.Width / 2;
|
|
double centerY = Canvas.GetTop(circle) + circle.Height / 2;
|
|
double distance = Math.Sqrt(Math.Pow(centerX - x, 2) + Math.Pow(centerY - y, 2));
|
|
|
|
if (distance < minDistance)
|
|
{
|
|
minDistance = distance;
|
|
circleToRemove = circle;
|
|
}
|
|
}
|
|
|
|
if (circleToRemove != null && minDistance < someThreshold)
|
|
{
|
|
gameCanvas.Children.Remove(circleToRemove);
|
|
}
|
|
}
|
|
|
|
// Vous pouvez lier cette méthode à un bouton dans l'interface utilisateur pour démarrer le jeu
|
|
private void StartGameButton_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
StartGame();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"Une erreur s'est produite : {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private void MediaFailed(object sender, ExceptionEventArgs e)
|
|
{
|
|
MessageBox.Show($"Échec de la lecture de la musique : {e.ErrorException.Message}");
|
|
}
|
|
|
|
// Optionnel: Ajouter un bouton d'arrêt dans l'interface utilisateur et lier cette méthode
|
|
private void StopGameButton_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
StopGame();
|
|
}
|
|
|
|
private void CreateRandomCircle()
|
|
{
|
|
// Vérifier si nous avons déjà le nombre maximum de cercles à l'écran
|
|
if (gameCanvas.Children.OfType<Ellipse>().Count() < MaxCircles)
|
|
{
|
|
// Générer une position aléatoire dans les limites du Canvas
|
|
double x = random.NextDouble() * (gameCanvas.ActualWidth - CircleStartSize);
|
|
double y = random.NextDouble() * (gameCanvas.ActualHeight - CircleStartSize);
|
|
|
|
// Créer un nouveau cercle
|
|
Ellipse newCircle = new Ellipse
|
|
{
|
|
Width = CircleStartSize,
|
|
Height = CircleStartSize,
|
|
Fill = Brushes.Red,
|
|
Opacity = 0.5
|
|
};
|
|
|
|
// Ajouter le cercle au Canvas
|
|
gameCanvas.Children.Add(newCircle);
|
|
Canvas.SetLeft(newCircle, x);
|
|
Canvas.SetTop(newCircle, y);
|
|
|
|
// Créer et démarrer un timer pour ce cercle
|
|
DispatcherTimer circleTimer = new DispatcherTimer
|
|
{
|
|
Interval = TimeSpan.FromMilliseconds(100)
|
|
};
|
|
circleTimer.Tick += (sender, e) => ReduceCircleSize(sender, e, newCircle);
|
|
circleTimer.Start();
|
|
}
|
|
}
|
|
|
|
private void ReduceCircleSize(object sender, EventArgs e, Ellipse circle)
|
|
{
|
|
if (circle.Width > MinimumCircleSize && circle.Height > MinimumCircleSize)
|
|
{
|
|
circle.Width -= ReductionAmount;
|
|
circle.Height -= ReductionAmount;
|
|
}
|
|
else
|
|
{
|
|
DispatcherTimer timer = sender as DispatcherTimer;
|
|
timer.Stop(); // Arrêter le timer
|
|
gameCanvas.Children.Remove(circle); // Supprimer le cercle du Canvas
|
|
}
|
|
}
|
|
|
|
|
|
private void OnGestureRecognized(object sender, GestureRecognizedEventArgs e)
|
|
{
|
|
if (e.GestureName == "Clap Hands")
|
|
{
|
|
// Ici, vous devez récupérer les coordonnées de la main de l'utilisateur via Kinect
|
|
// double handX = ...; // Coordonnée X de la main
|
|
// double handY = ...; // Coordonnée Y de la main
|
|
|
|
// RemoveCircleAtPosition(handX, handY);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|