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.

438 lines
17 KiB

using System;
using System.Collections.Generic;
using System.ComponentModel;
using Xamarin.Forms;
using SkiaSharp;
using SkiaSharp.Views.Forms;
using TouchTracking;
using Xamarin.Essentials;
using OrderStacks.viewmodel;
using OrderStacks.Resx;
using OrderStacks.Interface;
namespace OrderStacks.view
{
/**
* Classe qui permet de gérer la vue du jeu
*/
[DesignTimeVisible(false)]
public partial class MainPage : ContentPage
{
private Main viewmodel;
private List<string> playersNames = new List<string>();
private int nbPile;
private int nbCard;
private int indexMode;
List<TouchManipulationCard> textCollection = new List<TouchManipulationCard>();
List<TouchManipulationCard> stackCollection = new List<TouchManipulationCard>();
Dictionary<long, TouchManipulationCard> textDictionary = new Dictionary<long, TouchManipulationCard>();
private SKCanvas canvas;
/**
* <param name="playersNames">Liste des pseudos des joueurs</param>
* <param name="nbPile">Nombre de piles pour jouer</param>
* <param name="indexMode">Version du jeu pour jouer</param>
* <param name="nbCard">Nombre de cartes pour jouer</param>
*
* Constructeur
*/
public MainPage(List<string> playersNames, int nbPile, int indexMode, int nbCard)
{
this.nbPile = nbPile;
this.nbCard = nbCard;
this.indexMode = indexMode;
Random random = new Random();
int r = random.Next(0, playersNames.Count);
int size = playersNames.Count;
for (int i = 0; i < size; i++)
{
this.playersNames.Add(playersNames[r]);
playersNames.RemoveAt(r);
r = random.Next(0, playersNames.Count);
}
InitializeComponent();
NavigationPage.SetHasNavigationBar(this, false);
EndTurnButton.Text = AppResources.StrEndTurn;
viewmodel = new Main(this.playersNames, nbPile, nbCard, indexMode);
viewmodel.EndGame += OnEndGame;
viewmodel.AlertChanged += OnAlertChanged;
pseudo.SetBinding(Label.TextProperty, new Binding("Pseudo", source: viewmodel));
InflateStack();
InflateHand();
}
/**
* <param name="sender">Instance qui envoi l'événement</param>
* <param name="args">Argument(s) de l'événement</param>
*
* Evénement permettant d'afficher les messages d'alertes générés dans le model
*/
private void OnAlertChanged(object sender, EventArgs args)
{
if (viewmodel.Alert != "")
{
DependencyService.Get<IMessage>().ShortAlert(viewmodel.Alert);
viewmodel.Alert = "";
}
}
/**
* <param name="sender">Instance qui envoi l'événement</param>
* <param name="args">Arguments de l'événement</param>
*
* Evénement permettant de peindre la surface du canvas
*/
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);
}
else
{
stackCollection[i].Paint(canvas);
}
}
foreach (TouchManipulationCard textPaint in textCollection)
{
textPaint.Paint(canvas);
}
}
/**
* <param name="sender">Instance qui envoi l'événement</param>
* <param name="args">Arguments de l'événement</param>
*
* 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.
*/
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))
{
bool isStackable = false;
TouchManipulationCard card = textDictionary[args.Id];
point.Y -= 120;
point.X -= 50;
foreach (TouchManipulationCard stack in stackCollection)
{
SKPoint pointVisuCard = new SKPoint(point.X, point.Y - 120);
if (stack.HitTest(point) || stack.HitTest(pointVisuCard))
{
card.Color = stack.Color;
isStackable = true;
}
}
if (!isStackable)
{
card.Color = SKColors.SkyBlue;
}
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;
card.Color = stack.Color;
stackCollection[stackCollection.IndexOf(stack)] = card;
textCollection.RemoveAt(textCollection.Count - 1);
find = true;
}
break;
}
}
if (!find)
{
card.ProcessTouchEvent(args.Id, TouchActionType.Moved, card.InitialPoint);
card.Color = SKColors.SkyBlue;
}
card.ProcessTouchEvent(args.Id, args.Type, point);
textDictionary.Remove(args.Id);
canvasView.InvalidateSurface();
}
break;
}
}
/**
* Fonction permettant de placer les piles (piles non dessinées)
*/
private void InflateStack()
{
stackCollection.Clear();
SKPaint textPaint = new SKPaint();
float inflateWidth = 0.024f * (float)(DeviceDisplay.MainDisplayInfo.Width - 20);
SKPoint position = new SKPoint((float)((DeviceDisplay.MainDisplayInfo.Width * 0.92f - 20f - inflateWidth * 2f) / (viewmodel.getListOrderedStacks().Count * 2)) + (float)DeviceDisplay.MainDisplayInfo.Width * 0.04f + 10f, (float)((DeviceDisplay.MainDisplayInfo.Height * 0.1) + (DeviceDisplay.MainDisplayInfo.Height * 0.85) * 0.01 + 2 * (0.05f * (float)DeviceDisplay.MainDisplayInfo.Width * textPaint.TextSize / textPaint.MeasureText("001"))));
position.X -= inflateWidth;
for (int i = 0; i < viewmodel.getListOrderedStacks().Count; i++)
{
textPaint = new SKPaint();
float textWidth;
if (viewmodel.getListOrderedStacks()[i].Peek().GetType() == typeof(FractionCardVM))
{
string displayMax = ((FractionCardVM)viewmodel.getListOrderedStacks()[i].Peek()).getDisplayMax();
textWidth = textPaint.MeasureText(displayMax);
}
else
{
textWidth = textPaint.MeasureText("00");
}
textPaint.TextSize = 0.03f * (float)(DeviceDisplay.MainDisplayInfo.Width - 20) * textPaint.TextSize / textPaint.MeasureText("00");
position.X -= textWidth * 0.5f;
SKColor color;
if (i < (viewmodel.getListOrderedStacks().Count * 0.5))
{
color = new SKColor(33, 255, 40);
}
else
{
color = SKColors.Red;
}
stackCollection.Add(new TouchManipulationCard(textPaint, viewmodel.getListOrderedStacks()[i].Peek(), inflateWidth)
{
Matrix = SKMatrix.MakeTranslation(position.X, position.Y),
InitialMatrix = SKMatrix.MakeTranslation(position.X, position.Y),
InitialPoint = position,
Color = color
});
position.X += (float)((DeviceDisplay.MainDisplayInfo.Width * 0.92f - 20f - inflateWidth * 2f) / viewmodel.getListOrderedStacks().Count) + textWidth * 0.5f;
}
}
/**
* Fonction permettant de placer les cartes contenues dans la main du joueur actif (cartes non dessinées)
*/
private void InflateHand()
{
SKPaint textPaint = new SKPaint();
float inflateWidth = 0.024f * (float)(DeviceDisplay.MainDisplayInfo.Width - 20);
SKPoint position = new SKPoint((float)((DeviceDisplay.MainDisplayInfo.Width * 0.92f - 20f - inflateWidth * 2f) / (viewmodel.CurrentHand.Count * 2)) + (float)DeviceDisplay.MainDisplayInfo.Width * 0.04f + 10f, (float)((DeviceDisplay.MainDisplayInfo.Height * 0.85) * 0.5 - (0.05f * (float)(DeviceDisplay.MainDisplayInfo.Width - 20) * textPaint.TextSize / textPaint.MeasureText("001"))) + (float)((DeviceDisplay.MainDisplayInfo.Height * 0.1) + (DeviceDisplay.MainDisplayInfo.Height * 0.85) * 0.01 + 2 * (0.05f * (float)DeviceDisplay.MainDisplayInfo.Width * textPaint.TextSize / textPaint.MeasureText("001"))));
position.X -= inflateWidth;
for (int i = 0; i < viewmodel.CurrentHand.Count; i++)
{
textPaint = new SKPaint();
float textWidth;
if (viewmodel.CurrentHand[i].GetType() == typeof(FractionCardVM))
{
string displayMax = ((FractionCardVM)viewmodel.CurrentHand[i]).getDisplayMax();
textWidth = textPaint.MeasureText(displayMax);
}
else
{
textWidth = textPaint.MeasureText("00");
}
textPaint.TextSize = 0.03f * (float)(DeviceDisplay.MainDisplayInfo.Width - 20) * textPaint.TextSize / textPaint.MeasureText("00");
position.X -= textWidth * 0.5f;
textCollection.Add(new TouchManipulationCard(textPaint, viewmodel.CurrentHand[i], inflateWidth)
{
Matrix = SKMatrix.MakeTranslation(position.X, position.Y),
InitialMatrix = SKMatrix.MakeTranslation(position.X, position.Y),
InitialPoint = position,
Color = SKColors.SkyBlue
});
position.X += (float)((DeviceDisplay.MainDisplayInfo.Width * 0.92f - 20f - inflateWidth * 2f) / viewmodel.CurrentHand.Count) + textWidth * 0.5f;
}
}
/**
* <param name="sender">Instance qui envoi l'événement</param>
* <param name="args">Argument(s) de l'événement</param>
*
* Evénement traitant la fin du jeu
*/
private void OnEndGame(object sender, EventArgs args)
{
gameOption.Children.Clear();
Button retryButton = new Button()
{
Text = AppResources.StrRetry,
CornerRadius = 10,
BackgroundColor = (Color)Application.Current.Resources["Gold"],
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.End,
Padding = 10
};
retryButton.Clicked += Retry;
gameOption.Children.Add(retryButton);
}
/**
* <param name="numStack">Index de la pile joué</param>
* <param name="value">Valeur de la carte joué</param>
*
* Fonction permettant de tenter de jouer une carte
*
* <returns>Booléen qui indique si la carte a pu être joué</returns>
*/
private bool Played(int numStack, decimal value)
{
if (!viewmodel.played(numStack, value))
{
return false;
}
progressBar.Progress -= ((100f / nbCard) / 100f);
return true;
}
/**
* <param name="sender">Instance qui envoi l'événement</param>
* <param name="args">Argument(s) de l'événement</param>
*
* Evénement permettant de relancer le jeu avec les mêmes paramètres
*/
private void Retry(object sender, EventArgs args)
{
viewmodel = new Main(playersNames, nbPile, nbCard, indexMode);
viewmodel.EndGame += OnEndGame;
viewmodel.AlertChanged += OnAlertChanged;
pseudo.SetBinding(Label.TextProperty, new Binding("Pseudo", source: viewmodel));
textCollection.Clear();
textDictionary.Clear();
canvasView.InvalidateSurface();
InflateStack();
InflateHand();
progressBar.Progress = 1f;
gameOption.Children.Clear();
Button button = new Button()
{
Padding = 10,
Text = AppResources.StrEndTurn,
BackgroundColor = (Color)Application.Current.Resources["Gold"],
CornerRadius = 10,
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.End
};
button.Clicked += EndTurn;
gameOption.Children.Add(button);
}
/**
* <param name="sender">Instance qui envoi l'événement</param>
* <param name="args">Argument(s) de l'événement</param>
*
* Evénement permettant de lancer la fin du tour d'un joueur
*/
private async void EndTurn(object sender, EventArgs args)
{
if (!viewmodel.endTurn())
{
textCollection.Clear();
textDictionary.Clear();
stackCollection.Clear();
canvasView.InvalidateSurface();
InflateStack();
if (playersNames.Count > 1)
{
await DisplayAlert("C'est à " + viewmodel.Pseudo + " de jouer", null, "OK");
}
InflateHand();
canvasView.InvalidateSurface();
}
}
/**
* <param name="sender">Instance qui envoi l'événement</param>
* <param name="args">Argument(s) de l'événement</param>
*
* Evénement permettant de naviguer entre les différentes pages de l'application
*/
private async void PlayToHome(object sender, EventArgs args)
{
await Navigation.PopToRootAsync();
}
}
}