Files
Solitaire/Entities/Card.cs
NikolajDanger d9e27910cf
2021-11-02 00:05:00 +01:00

308 lines
11 KiB
C#

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<IGameEntity> 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);
}
}
}