using System.Linq; using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System.Collections.Generic; using Solitaire.Graphics; namespace Solitaire.Entities { public class Card: CardPosition { const int SelectedOffset = 3; public int DefaultX; public Sprite Sprite {get; private set;} public Sprite BackSprite {get; private set;} public Sprite FrontSprite {get; private set;} public int Value; public bool Hidden {get; private set;} private bool Selected; public CardPosition parent = null; private double lastClicked; public void setSprite() { if (Hidden) { Sprite = BackSprite; } else { Sprite = FrontSprite; } } public Card(int value, bool hidden, Vector2 position, Texture2D spriteSheet): base(position) { Offset = 13; Value = value; Hidden = hidden; if (Hidden) { Offset = 8; } Position = position; DefaultX = (int)position.X; Stationary = true; BackSprite = new Sprite(spriteSheet, 320, 192, 32, 48); FrontSprite = new Sprite( spriteSheet, (value % 11) * 32, (value / 11) * 48, 32, 48 ); setSprite(); } public void NewPosition(Vector2 position) { Position = position; DefaultX = (int)position.X; } public void Hide() { Hidden = true; setSprite(); } public void UnHide() { Hidden = false; setSprite(); } public override void Draw(SpriteBatch spriteBatch, GameTime gameTime) { Sprite.Draw(spriteBatch, Position); } private bool inRectangle(Vector2 point, Rectangle rectangle) { return ( point.X >= rectangle.Left && point.X <= rectangle.Right && point.Y > rectangle.Top && point.Y < rectangle.Bottom ); } public void SetSelected(Vector2 mPosition, bool mHolding) { int height = 40; if (child != null) { height = Offset; } else if (Selected) { height += SelectedOffset; } Rectangle spritePosition = new Rectangle( (int)Position.X, (int)Position.Y, 32, height ); if ((!Hidden || child == null) && !mHolding && !Following && inRectangle(mPosition, spritePosition) && !Selected && (child == null || !((Card)child).Selected) && (Offset > 0 || child == null)) { Selected = true; } else if (!inRectangle(mPosition, spritePosition) && Selected) { Selected = false; if (child != null) { ((Card)child).SetSelected(mPosition, mHolding); if (((Card)child).Selected) { ((Card)child).SetPosition(mPosition); } } if (parent != null) { if (parent is Card) { ((Card)parent).SetSelected(mPosition, mHolding); if (((Card)parent).Selected) { ((Card)parent).SetPosition(mPosition); } } } } } public void SetPosition(Vector2 mPosition) { int X; int Y; if (Following) { X = (int)mPosition.X - 16; Y = (int)mPosition.Y - 16; } else { X = (int)parent.Position.X; Y = (int)parent.Position.Y + parent.Offset; } if (Selected && !Following) { Y -= SelectedOffset; } Position = new Vector2(X, Y); } public void SetStationary(bool stationary) { Stationary = stationary; if (child != null) { ((Card)child).SetStationary(stationary); } } private bool IsCloser(CardPosition other, CardPosition closest) { return ( other.Stationary && other.child == null && ( closest == null || Vector2.Distance(closest.Position, Position) > Vector2.Distance(other.Position, Position) ) && ValidPlacement(other) ); } private bool ValidPlacement(CardPosition other) { return ( other == parent || ( !(other is Card) && ( ( !other.TopPile && ( ( Deck && other.Deck ) || ( !other.Deck && Value % 13 == 12 ) ) ) || ( other.TopPile && Value % 13 == 0 ) ) ) || ( other is Card && ( ( !other.Deck && ( ( other.TopPile && Value / 13 == ((Card)other).Value / 13 && Value - 1 == ((Card)other).Value ) || ( (Value % 13 + 1 == ((Card)other).Value % 13) && ((Value / 13) % 2 != (((Card)other).Value / 13) % 2) ) ) ) || ( Deck && other.Deck && !((Card)other).Hidden ) ) ) ); } public override void Update(GameTime gameTime, Vector2 mPosition, bool mReleased, bool mHolding, List entities) { SetSelected(mPosition, mHolding); if (parent != null && !Following) { DrawOrder = parent.DrawOrder + 1; } else if (!Following) { DrawOrder = 1; } if (Selected && mReleased && !Following) { if (!Hidden) { lastClicked = gameTime.TotalGameTime.TotalSeconds; Following = true; SetStationary(false); Selected = false; DrawOrder = 1000; } else { UnHide(); if (Deck) { parent.child = null; Selected = false; SolitaireGame.logic.DeckRevealed.Last().child = this; parent = SolitaireGame.logic.DeckRevealed.Last(); SolitaireGame.logic.DeckRevealed.Add(this); SolitaireGame.logic.DeckHidden.Remove(this); parent.Offset = 0; } } } else if (Following && mReleased) { CardPosition closest = null; CardPosition oldPosition = parent; parent.child = null; foreach (IGameEntity entity in entities) { if (entity is CardPosition) { if (IsCloser((CardPosition)entity, closest)) { closest = (CardPosition)entity; } } } if (closest != null && Vector2.Distance(closest.Position, Position) < 50) { if (ValidPlacement(closest)) { Following = false; SetStationary(true); closest.child = this; parent = closest; if (parent is Card && !((Card)parent).Hidden){ parent.Offset = 13; } if (parent.TopPile) { TopPile = true; parent.Offset = 0; } else { TopPile = false; } if (Deck && !closest.Deck) { Deck = false; SolitaireGame.logic.DeckRevealed.Remove(this); } if (Deck) { parent.Offset = 0; } } } else { Following = false; SetStationary(true); oldPosition.child = this; parent = oldPosition; } if (gameTime.TotalGameTime.TotalSeconds - lastClicked < 0.3 && parent == oldPosition) { foreach (IGameEntity entity in SolitaireGame.entities) { if (entity is CardPosition && ((CardPosition)entity).TopPile && ((CardPosition)entity).child == null) { if ( (entity is Card && ((Card)entity).Value % 13 == Value % 13 - 1 && ((Card)entity).Value / 13 == Value / 13) || (!(entity is Card) && Value % 13 == 0) ) { parent.child = null; ((CardPosition)entity).child = this; parent = ((CardPosition)entity); TopPile = true; parent.Offset = 0; if (Deck) { Deck = false; SolitaireGame.logic.DeckRevealed.Remove(this); } break; } } } } } else if (Following && (mPosition.X < 0 || mPosition.X > SolitaireGame.gameWidth || mPosition.Y < 0 || mPosition.Y > SolitaireGame.gameHeight)) { Following = false; SetStationary(true); } SetPosition(mPosition); } } }