using System; using System.Collections.Generic; using System.ComponentModel; using Xamarin.Forms; using TheGameExtreme.viewmodel; using SkiaSharp; using SkiaSharp.Views.Forms; using TouchTracking; using Xamarin.Essentials; using System.IO; using System.Reflection; namespace TheGameExtreme.view { /** * Classe qui permet de gérer la vue du jeu */ [DesignTimeVisible(false)] public partial class MainPage : ContentPage { private Main viewmodel; private List playersNames; private int nbPile; private int nbCard; private int indexMode; List textCollection = new List(); List stackCollection = new List(); Dictionary textDictionary = new Dictionary(); private SKCanvas canvas; private SKBitmap logo; private SKPoint logoPoint; /** * Liste des pseudos des joueurs * Nombre de piles pour jouer * Version du jeu joué */ public MainPage(List playersNames, int nbPile, int indexMode, int nbCard) { this.playersNames = playersNames; this.nbPile = nbPile; this.nbCard = nbCard; this.indexMode = indexMode; InitializeComponent(); NavigationPage.SetHasNavigationBar(this, false); EndTurnButton.Text = AppRessource.StrEndTurn; // Trouver le moyen d'avoir du binding viewmodel = new Main(playersNames, nbPile, nbCard, indexMode); viewmodel.EndGame += OnEndGame; viewmodel.AlertChanged += OnAlertChanged; pseudo.SetBinding(Label.TextProperty, new Binding("Pseudo", source: viewmodel)); InflateStack(); InflateHand(); string ressourceID; if (DeviceDisplay.MainDisplayInfo.Height > 1500) { ressourceID = "TheGameExtreme.Media.TrierImageBMax.png"; } else { ressourceID = "TheGameExtreme.Media.TrierImageBMin.png"; } using (Stream stream = GetType().GetTypeInfo().Assembly.GetManifestResourceStream(ressourceID)) { logo = SKBitmap.Decode(stream); } logoPoint = new SKPoint((float)DeviceDisplay.MainDisplayInfo.Width * 0.5f - logo.Width, (float)(DeviceDisplay.MainDisplayInfo.Height * 0.9) * 0.5f - logo.Height * 0.5f); } /** * Evénement permettant d'afficher les messages d'alertes générés dans le model * Instance qui envoi l'événement * Argument(s) de l'événement */ private void OnAlertChanged(object sender, EventArgs args) { if (viewmodel.Alert != null) { DisplayAlert("😆", viewmodel.Alert, "OK"); viewmodel.Alert = null; } } /** * Evénement permettant de peindre la surface du canvas * Instance qui envoi l'événement * Arguments de l'événement */ public void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args) { canvas = args.Surface.Canvas; canvas.Clear(); for (int i = 0; i < stackCollection.Count; i++) { if (i < (stackCollection.Count * 0.5)) { stackCollection[i].Paint(canvas, SKColors.Green); } else { stackCollection[i].Paint(canvas, SKColors.Red); } } foreach (TouchManipulationCard textPaint in textCollection) { textPaint.Paint(canvas, SKColors.SkyBlue); } canvas.DrawBitmap(logo, logoPoint); } /** * Evénement qui permet de gérer le Drag and Drop. * Il permet de traiter le clic, le mouvement, le relachement du clic et la fin de traitement d'un clic. * Instance qui envoi l'événement * Arguments de l'événement */ public void OnTouchEffectAction(object sender, TouchActionEventArgs args) { TouchTrackingPoint pt = args.Location; SKPoint point = new SKPoint((float)(canvasView.CanvasSize.Width * pt.X / canvasView.Width), (float)(canvasView.CanvasSize.Height * pt.Y / canvasView.Height)); switch (args.Type) { case TouchActionType.Pressed: for (int i = textCollection.Count - 1; i >= 0; i--) { TouchManipulationCard textPaint = textCollection[i]; if (textPaint.HitTest(point)) { // Move card to end of collection textCollection.Remove(textPaint); textCollection.Add(textPaint); // Do the touch processing textDictionary.Add(args.Id, textPaint); textPaint.ProcessTouchEvent(args.Id, args.Type, point); canvasView.InvalidateSurface(); break; } } break; case TouchActionType.Moved: if (textDictionary.ContainsKey(args.Id)) { TouchManipulationCard card = textDictionary[args.Id]; point.Y -= 120; point.X -= 50; card.ProcessTouchEvent(args.Id, args.Type, point); canvasView.InvalidateSurface(); } break; case TouchActionType.Released: case TouchActionType.Cancelled: if (textDictionary.ContainsKey(args.Id)) { TouchManipulationCard card = textDictionary[args.Id]; bool find = false; foreach (TouchManipulationCard stack in stackCollection) { SKPoint pointVisuCard = new SKPoint(point.X, point.Y - 120); if (stack.HitTest(point) || stack.HitTest(pointVisuCard)) { int indexPile = stackCollection.IndexOf(stack); if (Played(indexPile, card.Value.Value)) { card.ProcessTouchEvent(args.Id, TouchActionType.Moved, stack.InitialPoint); card.InitialPoint = stackCollection[stackCollection.IndexOf(stack)].InitialPoint; stackCollection[stackCollection.IndexOf(stack)] = card; textCollection.RemoveAt(textCollection.Count - 1); find = true; } break; } } if (!find) { card.ProcessTouchEvent(args.Id, TouchActionType.Moved, card.InitialPoint); } card.ProcessTouchEvent(args.Id, args.Type, point); textDictionary.Remove(args.Id); canvasView.InvalidateSurface(); } break; } } /** * Fonction permettant de déployer visuellement les piles */ private void InflateStack() { stackCollection.Clear(); SKPaint textPaint = new SKPaint(); float textWidth = textPaint.MeasureText("001"); float textSize = 0.05f * (float)DeviceDisplay.MainDisplayInfo.Width * textPaint.TextSize / textWidth; SKPoint position = new SKPoint((float)((DeviceDisplay.MainDisplayInfo.Width * 0.9) / (viewmodel.getListOrderedStacks().Count * 2)) - textPaint.MeasureText("01") * 0.5f, (float)((DeviceDisplay.MainDisplayInfo.Height * 0.1) + (DeviceDisplay.MainDisplayInfo.Height * 0.9) * 0.01 + 2 * textSize)); for (int i = 0; i < viewmodel.getListOrderedStacks().Count; i++) { textPaint = new SKPaint(); textPaint.TextSize = textSize; stackCollection.Add(new TouchManipulationCard(textPaint, viewmodel.getListOrderedStacks()[i].Peek()) { Matrix = SKMatrix.MakeTranslation(position.X, position.Y), InitialMatrix = SKMatrix.MakeTranslation(position.X, position.Y), InitialPoint = position }); position.X += (float)((DeviceDisplay.MainDisplayInfo.Width * 0.9) / viewmodel.getListOrderedStacks().Count); } } /** * Fonction permettant de déployer visuellement les cartes contenues dans la main du joueur actif */ private void InflateHand() { SKPaint textPaint = new SKPaint(); float textWidth = textPaint.MeasureText("001"); float textSize = 0.05f * (float)DeviceDisplay.MainDisplayInfo.Width * textPaint.TextSize / textWidth; SKPoint position = new SKPoint((float)((DeviceDisplay.MainDisplayInfo.Width * 0.9) / (viewmodel.CurrentHand.Count * 2)) - textPaint.MeasureText("01") * 0.5f + (float)(DeviceDisplay.MainDisplayInfo.Width * 0.01), (float)((DeviceDisplay.MainDisplayInfo.Height * 0.9) - (DeviceDisplay.MainDisplayInfo.Height * 0.9) * 0.1 - 2 * textSize)); for (int i = 0; i < viewmodel.CurrentHand.Count; i++) { textPaint = new SKPaint(); textPaint.TextSize = textSize; position.X -= (float)(textWidth * 0.5); textCollection.Add(new TouchManipulationCard(textPaint, viewmodel.CurrentHand[i]) { Matrix = SKMatrix.MakeTranslation(position.X, position.Y), InitialMatrix = SKMatrix.MakeTranslation(position.X, position.Y), InitialPoint = position }); position.X += (float)((DeviceDisplay.MainDisplayInfo.Width * 0.9) / viewmodel.CurrentHand.Count); } } /** * Evénement traitant la fin du jeu * Instance qui envoi l'événement * Argument(s) de l'événement */ private void OnEndGame(object sender, EventArgs args) { gameOption.Children.Clear(); Button retryButton = new Button(); retryButton.Text = "Retry"; retryButton.Clicked += Retry; retryButton.BackgroundColor = (Color)Application.Current.Resources["SkyBlueColor"]; gameOption.Children.Add(retryButton); } /** * Fonction permettant de lancer le déplacement d'une carte sur une pile * Index de la pile joué * Valeur de la carte joué * Booléen qui indique si la carte a pu être joué */ private bool Played(int numStack, decimal value) { if (!viewmodel.played(numStack, value)) { return false; } return true; } /** * Evénement permettant de relancer le jeu avec les mêmes paramètres de jeu * Instance qui envoi l'événement * Argument de l'événement */ private void Retry(object sender, EventArgs args) { viewmodel = new Main(playersNames, nbPile, nbCard, indexMode); viewmodel.EndGame += OnEndGame; pseudo.SetBinding(Label.TextProperty, new Binding("Pseudo", source: viewmodel)); textCollection.Clear(); textDictionary.Clear(); canvasView.InvalidateSurface(); InflateStack(); InflateHand(); gameOption.Children.Clear(); Button button = new Button(); button.Text = AppRessource.StrEndTurn; button.Clicked += Retry; button.BackgroundColor = (Color)Application.Current.Resources["SkyBlueColor"]; gameOption.Children.Add(button); } /** * Evénement permettant de lancer la fin du tour d'un joueur * Instance qui envoi l'événement * Argument de l'événement */ private void EndTurn(object sender, EventArgs args) { if (!viewmodel.endTurn()) { textCollection.Clear(); textDictionary.Clear(); stackCollection.Clear(); canvasView.InvalidateSurface(); InflateStack(); InflateHand(); } } /** * Evénement permettant de naviguer entre les différentes pages de l'application * Instance qui envoi l'événement * Argument de l'événement */ private async void PlayToHome(object sender, EventArgs args) { await Navigation.PopToRootAsync(); } } }