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.
229 lines
6.1 KiB
229 lines
6.1 KiB
#define OLC_PGE_APPLICATION
|
|
#include "pixelGameEngine.h"
|
|
#include <random>
|
|
|
|
using namespace olc;
|
|
|
|
const float PI = 3.14159f;
|
|
const vi2d CARD_SIZE = vi2d{32,48};
|
|
|
|
class Solitaire;
|
|
Solitaire*game;
|
|
|
|
class Solitaire : public olc::PixelGameEngine
|
|
{
|
|
std::default_random_engine generator;
|
|
Renderable club_spr, spade_spr, diamond_spr, heart_spr;
|
|
enum Suit {
|
|
CLUB,
|
|
DIAMOND,
|
|
HEART,
|
|
SPADE,
|
|
FACEDOWN,
|
|
};
|
|
|
|
enum SlotType {
|
|
PLAYDECK,
|
|
ACTIVE_PLAYDECK,
|
|
HOME,
|
|
FIELD
|
|
};
|
|
|
|
struct Card {
|
|
Suit s;
|
|
int number;
|
|
};
|
|
|
|
Decal*GetSprite(Suit s) {
|
|
switch (s) {
|
|
case CLUB: {
|
|
return club_spr.Decal();
|
|
}break;
|
|
case DIAMOND: {
|
|
return diamond_spr.Decal();
|
|
}break;
|
|
case HEART: {
|
|
return heart_spr.Decal();
|
|
}break;
|
|
case SPADE: {
|
|
return spade_spr.Decal();
|
|
}break;
|
|
}
|
|
}
|
|
|
|
struct CardSlot {
|
|
vf2d pos;
|
|
SlotType type;
|
|
std::vector<Card> faceDownCards;
|
|
std::vector<Card> faceUpCards;
|
|
std::vector<Card> flippedOverCards; //Just for active play deck. Face up cards will contain the rest of the pile.
|
|
void RenderCard(vf2d pos, Suit s, int number) {
|
|
if (s == FACEDOWN) {
|
|
game->FillRectDecal(pos, CARD_SIZE, DARK_CYAN);
|
|
game->DrawRectDecal(pos, CARD_SIZE, BLACK);
|
|
}
|
|
else {
|
|
game->FillRectDecal(pos, CARD_SIZE, WHITE);
|
|
game->DrawStringDecal(pos + vf2d{ 2,2 }, number == 1 ? "A" : number == 13 ? "K" : number == 12 ? "Q" : number == 11 ? "J" : std::to_string(number), s == CLUB || s == SPADE ? BLACK : DARK_RED, number == 10 ? vf2d{ 0.6,1 } : vf2d{ 1,1 });
|
|
game->DrawDecal(pos + vf2d{ 2,12 }, game->GetSprite(s), { 0.25,0.25 });
|
|
game->DrawRotatedStringDecal(pos + CARD_SIZE - vf2d{ 2,2 }, number == 1 ? "A" : number == 13 ? "K" : number == 12 ? "Q" : number == 11 ? "J" : std::to_string(number), PI, { 0,0 }, s == CLUB || s == SPADE ? BLACK : DARK_RED, number == 10 ? vf2d{ 0.6,1 } : vf2d{ 1,1 });
|
|
game->DrawRotatedDecal(pos + CARD_SIZE - vf2d{ 2,12 }, game->GetSprite(s), PI, { 0,0 }, { 0.25, 0.25 });
|
|
game->DrawRectDecal(pos, CARD_SIZE, BLACK);
|
|
}
|
|
}
|
|
void RenderCards() {
|
|
game->DrawRectDecal(pos, CARD_SIZE, BLACK);
|
|
switch (type) {
|
|
case PLAYDECK: {
|
|
if (faceDownCards.size() > 6*3) {
|
|
RenderCard(pos+vi2d{-2,-2}, FACEDOWN, 0);
|
|
RenderCard(pos + vi2d{ -1,-1 }, FACEDOWN, 0);
|
|
RenderCard(pos, FACEDOWN, 0);
|
|
} else
|
|
if (faceDownCards.size() > 3 * 3) {
|
|
RenderCard(pos + vi2d{ -1,-1 }, FACEDOWN, 0);
|
|
RenderCard(pos, FACEDOWN, 0);
|
|
}
|
|
else {
|
|
RenderCard(pos, FACEDOWN, 0);
|
|
}
|
|
}break;
|
|
case ACTIVE_PLAYDECK: {
|
|
if (flippedOverCards.size() > 0) {
|
|
for (int i = 0; i < flippedOverCards.size(); i++) {
|
|
Card& c = flippedOverCards[i];
|
|
RenderCard(pos + vi2d{ i * 12,0 }, c.s, c.number);
|
|
}
|
|
} else {
|
|
if (faceUpCards.size() > 0) {
|
|
Card& c = faceUpCards[faceUpCards.size() - 1];
|
|
RenderCard(pos, c.s, c.number);
|
|
}
|
|
}
|
|
}break;
|
|
case HOME: {
|
|
if (faceUpCards.size() > 2) {
|
|
Card& c = faceUpCards[faceUpCards.size() - 1];
|
|
RenderCard(pos+vi2d{-2,-2}, c.s, c.number);
|
|
c = faceUpCards[faceUpCards.size() - 2];
|
|
RenderCard(pos + vi2d{ -1,-1 }, c.s, c.number);
|
|
c = faceUpCards[faceUpCards.size() - 3];
|
|
RenderCard(pos, c.s, c.number);
|
|
} else
|
|
if (faceUpCards.size() > 1) {
|
|
Card& c = faceUpCards[faceUpCards.size() - 1];
|
|
RenderCard(pos + vi2d{ -1,-1 }, c.s, c.number);
|
|
c = faceUpCards[faceUpCards.size() - 2];
|
|
RenderCard(pos, c.s, c.number);
|
|
}
|
|
else
|
|
if (faceUpCards.size() == 1) {
|
|
Card& c = faceUpCards[faceUpCards.size() - 1];
|
|
RenderCard(pos, c.s, c.number);
|
|
}
|
|
}break;
|
|
case FIELD: {
|
|
int cardSpacing = 16;
|
|
int totalCards = faceDownCards.size() + faceUpCards.size();
|
|
int spaceTakenUp = CARD_SIZE.y + totalCards * cardSpacing;
|
|
while (spaceTakenUp + pos.y > game->ScreenHeight()) {
|
|
cardSpacing--;
|
|
spaceTakenUp = CARD_SIZE.y + totalCards * cardSpacing;
|
|
}
|
|
for (int i = 0; i < faceDownCards.size(); i++) {
|
|
RenderCard(pos + vi2d{ 0,i * cardSpacing },FACEDOWN, 0);
|
|
}
|
|
if (faceUpCards.size() > 0) {
|
|
for (int i = 0; i < faceUpCards.size(); i++) {
|
|
Card& c = faceUpCards[i];
|
|
RenderCard(pos + vi2d{ 0,(i+(int)faceDownCards.size()) * cardSpacing }, c.s, c.number);
|
|
}
|
|
}
|
|
}break;
|
|
}
|
|
}
|
|
};
|
|
|
|
public:
|
|
|
|
Solitaire()
|
|
{
|
|
sAppName = "Solitaire";
|
|
game = this;
|
|
}
|
|
|
|
public:
|
|
std::vector<Card> cardDeck;
|
|
CardSlot PlayDeck{ {16,8},PLAYDECK };
|
|
CardSlot ActivePlayDeck{ {56,8},ACTIVE_PLAYDECK };
|
|
std::array<CardSlot, 4> Home;
|
|
std::array<CardSlot, 7> Field;
|
|
|
|
Card DrawCard() {
|
|
std::uniform_int_distribution<int> distribution(0, cardDeck.size()-1);
|
|
int dice_roll = distribution(generator);
|
|
//std::cout << dice_roll << std::endl;
|
|
Card drawnCard = cardDeck[dice_roll];
|
|
cardDeck.erase(cardDeck.begin() + dice_roll);
|
|
return drawnCard;
|
|
}
|
|
bool OnUserCreate() override
|
|
{
|
|
generator.seed(time(NULL));
|
|
; for (int i = 0; i <= SPADE; i++) {
|
|
for (int j = 1; j < 14; j++) {
|
|
cardDeck.push_back({ (Suit)i,j });
|
|
}
|
|
}
|
|
Clear(VERY_DARK_GREEN);
|
|
club_spr.Load("assets/club.png");
|
|
diamond_spr.Load("assets/diamond.png");
|
|
heart_spr.Load("assets/heart.png");
|
|
spade_spr.Load("assets/spade.png");
|
|
for (int i = 0; i < Field.size(); i++) {
|
|
for (int j = 0; j < i; j++) {
|
|
Field[i].faceDownCards.push_back(DrawCard());
|
|
}
|
|
Field[i].faceUpCards.push_back(DrawCard());
|
|
}
|
|
for (int i = 0; i < Home.size();i++) {
|
|
CardSlot&c = Home[i];
|
|
c.pos = vi2d{ 136 + i * 40,8 };
|
|
c.type = SlotType::HOME;
|
|
}
|
|
for (int i = 0; i < Field.size(); i++) {
|
|
CardSlot&c = Field[i];
|
|
c.pos = vi2d{ 16 + i * 40,64 };
|
|
c.type = SlotType::FIELD;
|
|
}
|
|
while (cardDeck.size()>0) {
|
|
PlayDeck.faceDownCards.push_back(DrawCard());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool OnUserUpdate(float fElapsedTime) override
|
|
{
|
|
// called once per frame
|
|
//RenderCard({ 48,48 }, HEART, 7);
|
|
PlayDeck.RenderCards();
|
|
ActivePlayDeck.RenderCards();
|
|
for (CardSlot& c : Home) {
|
|
c.RenderCards();
|
|
}
|
|
for (CardSlot& c : Field) {
|
|
c.RenderCards();
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
|
|
int main()
|
|
{
|
|
Solitaire demo;
|
|
if (demo.Construct(312, 200, 4, 4))
|
|
demo.Start();
|
|
|
|
return 0;
|
|
} |