1
+ /* *********************************************************************************************
2
+ *
3
+ * raylib-extras, examples-cpp * examples for Raylib in C++
4
+ *
5
+ * pew * an example of movement and shots
6
+ *
7
+ * LICENSE: MIT
8
+ *
9
+ * Copyright (c) 2021 Jeffery Myers
10
+ *
11
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ * of this software and associated documentation files (the "Software"), to deal
13
+ * in the Software without restriction, including without limitation the rights
14
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ * copies of the Software, and to permit persons to whom the Software is
16
+ * furnished to do so, subject to the following conditions:
17
+ *
18
+ * The above copyright notice and this permission notice shall be included in all
19
+ * copies or substantial portions of the Software.
20
+ *
21
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ * SOFTWARE.
28
+ *
29
+ **********************************************************************************************/
30
+
31
+ #include " raylib.h"
32
+ #include " raymath.h"
33
+
34
+ #include < vector>
35
+ #include < list>
36
+
37
+ Texture CardBack;
38
+
39
+ enum class CardSuit
40
+ {
41
+ Circle,
42
+ Square,
43
+ Diamond,
44
+ Cross,
45
+ };
46
+
47
+ // represents a single unique card
48
+ class Card
49
+ {
50
+ public:
51
+ Vector2 Position;
52
+ CardSuit Suit = CardSuit::Circle;
53
+ int Value = 0 ;
54
+
55
+ bool FaceUp = false ;
56
+
57
+ Color GetCardColor ()
58
+ {
59
+ switch (Suit)
60
+ {
61
+ case CardSuit::Circle:
62
+ return RED;
63
+ case CardSuit::Square:
64
+ return BLUE;
65
+ default :
66
+ return BLACK;
67
+ }
68
+ }
69
+
70
+ void Draw ()
71
+ {
72
+ if (FaceUp)
73
+ {
74
+ Rectangle baseRect = Rectangle{ Position.x -2 , Position.y -2 , (float )CardBack.width +2 , (float )CardBack.height +2 };
75
+ DrawRectangleRec (baseRect, BLACK);
76
+ baseRect = Rectangle{ Position.x , Position.y , (float )CardBack.width , (float )CardBack.height };
77
+ DrawRectangleRec (baseRect, RAYWHITE);
78
+
79
+ Vector2 center = { Position.x + CardBack.width / 2 , Position.y + CardBack.height / 2 };
80
+
81
+ DrawText (TextFormat (" %d" , Value), (int )center.x , (int )center.y + 55 , 40 , GetCardColor ());
82
+
83
+ switch (Suit)
84
+ {
85
+ case CardSuit::Circle:
86
+ DrawCircle ((int )center.x , (int )center.y - 40 , 40 , GetCardColor ());
87
+ break ;
88
+ case CardSuit::Square:
89
+ DrawRectangle ((int )center.x -20 , (int )center.y - 60 , 40 , 40 , GetCardColor ());
90
+ break ;
91
+ }
92
+ }
93
+ else
94
+ {
95
+ DrawTexture (CardBack, (int )Position.x , (int )Position.y , WHITE);
96
+ }
97
+ }
98
+
99
+ bool PointIn (const Vector2& pos)
100
+ {
101
+ return CheckCollisionPointRec (pos, Rectangle{ Position.x , Position.y , (float )CardBack.width , (float )CardBack.height });
102
+ }
103
+ };
104
+
105
+ // owns a set of unique cards
106
+ class Deck
107
+ {
108
+ public:
109
+ std::vector<Card> Cards;
110
+
111
+ Deck ()
112
+ {
113
+ for (int i = 0 ; i < 20 ; i++)
114
+ {
115
+ Cards.emplace_back (Card{ Vector2Zero (),CardSuit::Circle,i + 1 , false });
116
+ Cards.emplace_back (Card{ Vector2Zero (),CardSuit::Square,i + 1 , false });
117
+ }
118
+ }
119
+ };
120
+
121
+ // a stack of card pointers, used for things like draw decks and things that draw as card stack.
122
+ class Stack
123
+ {
124
+ public:
125
+ Vector2 Pos = { 0 };
126
+
127
+ std::vector<Card*> Cards;
128
+
129
+ void FromDeck (Deck& deck)
130
+ {
131
+ Cards.clear ();
132
+ for (auto & card : deck.Cards )
133
+ Cards.push_back (&card);
134
+ }
135
+
136
+ void Swap (size_t a, size_t b)
137
+ {
138
+ Card* t = Cards[a];
139
+ Cards[a] = Cards[b];
140
+ Cards[b] = t;
141
+ }
142
+
143
+ void Shuffle ( size_t factor = 4 )
144
+ {
145
+ size_t count = Cards.size () * factor;
146
+
147
+ for (size_t i = 0 ; i < count; i++)
148
+ {
149
+ size_t a = (size_t )GetRandomValue (0 , (int )Cards.size () - 1 );
150
+ size_t b = (size_t )GetRandomValue (0 , (int )Cards.size () - 1 );
151
+
152
+ Swap (a, b);
153
+ }
154
+ }
155
+
156
+ Card* PeekTop ()
157
+ {
158
+ Card* topCard = nullptr ;
159
+ if (!Cards.empty ())
160
+ topCard = Cards[Cards.size () - 1 ];
161
+
162
+ return topCard;
163
+ }
164
+
165
+ Card* PopTop ()
166
+ {
167
+ if (Cards.empty ())
168
+ return nullptr ;
169
+
170
+ Card* topCard = Cards[Cards.size () - 1 ];
171
+ Cards.erase (Cards.begin () + (Cards.size ()-1 ));
172
+
173
+ return topCard;
174
+ }
175
+
176
+ void Draw ()
177
+ {
178
+ Card* topCard = PeekTop ();
179
+
180
+ Rectangle baseRect = Rectangle{ Pos.x ,Pos.y , (float )CardBack.width , (float )CardBack.height };
181
+
182
+ DrawRectangleRec (baseRect, DARKGRAY);
183
+
184
+ if (topCard != nullptr )
185
+ {
186
+ topCard->Position .x = baseRect.x + 6 ;
187
+ topCard->Position .y = baseRect.y - 6 ;
188
+ topCard->Draw ();
189
+ }
190
+ }
191
+ };
192
+
193
+ class Hand : public Stack
194
+ {
195
+ public:
196
+ std::list<Card*> Cards;
197
+
198
+ Card* SelectedCard = nullptr ;
199
+
200
+ void AddCard (Card* card, bool selected = true )
201
+ {
202
+ Cards.emplace_back (card);
203
+ if (selected)
204
+ Select (card);
205
+ }
206
+
207
+ void Select (Card* card)
208
+ {
209
+ Deselect ();
210
+ if (card == nullptr )
211
+ return ;
212
+
213
+ SelectedCard = card;
214
+
215
+ // make it look like we picked up the card
216
+ SelectedCard->Position .x -= 3 ;
217
+ SelectedCard->Position .y -= 3 ;
218
+ }
219
+
220
+ void Deselect ()
221
+ {
222
+ if (SelectedCard != nullptr )
223
+ {
224
+ SelectedCard->Position .x += 4 ;
225
+ SelectedCard->Position .y += 4 ;
226
+ }
227
+ SelectedCard = nullptr ;
228
+ }
229
+
230
+ void Draw ()
231
+ {
232
+ for (Card* card : Cards)
233
+ card->Draw ();
234
+ }
235
+ };
236
+
237
+ void main ()
238
+ {
239
+ SetConfigFlags (FLAG_VSYNC_HINT);
240
+ InitWindow (1280 , 800 , " Card Sample" );
241
+ SetTargetFPS (144 );
242
+
243
+ Image img = GenImageChecked (100 , 200 , 25 , 25 , RED, MAROON);
244
+ CardBack = LoadTextureFromImage (img);
245
+ UnloadImage (img);
246
+
247
+ Deck cards;
248
+
249
+ Stack DrawDeck{ 30 ,20 };
250
+
251
+ DrawDeck.FromDeck (cards);
252
+ DrawDeck.Shuffle ();
253
+
254
+ Hand PlayerHand;
255
+
256
+ while (!WindowShouldClose ())
257
+ {
258
+ bool handled = false ;
259
+
260
+ // check to see if we are dragging a card
261
+ if (PlayerHand.SelectedCard != nullptr )
262
+ {
263
+ if (PlayerHand.SelectedCard ->PointIn (GetMousePosition ()))
264
+ {
265
+ if (IsMouseButtonDown (MOUSE_LEFT_BUTTON))
266
+ PlayerHand.SelectedCard ->Position = Vector2Add (PlayerHand.SelectedCard ->Position , GetMouseDelta ());
267
+ else
268
+ PlayerHand.Deselect ();
269
+ handled = true ;
270
+ }
271
+ }
272
+ else if (IsMouseButtonPressed (MOUSE_LEFT_BUTTON)) // check to see if we are selecting a card from the hand
273
+ {
274
+ for (Card* card : PlayerHand.Cards )
275
+ {
276
+ if (card->PointIn (GetMousePosition ()))
277
+ {
278
+ PlayerHand.Select (card);
279
+ break ;
280
+ }
281
+ }
282
+ }
283
+
284
+ // check to see if we are interacting with the draw deck
285
+ if (!handled)
286
+ {
287
+ Card* deckTop = DrawDeck.PeekTop ();
288
+ if (deckTop != nullptr )
289
+ {
290
+ if (deckTop->PointIn (GetMousePosition ()))
291
+ {
292
+ if (IsMouseButtonPressed (MOUSE_RIGHT_BUTTON))
293
+ {
294
+ // show the top card
295
+ deckTop->FaceUp = true ;
296
+ }
297
+ else if (IsMouseButtonPressed (MOUSE_LEFT_BUTTON) && PlayerHand.SelectedCard == nullptr )
298
+ {
299
+ // take the card into a hand and start dragging it.
300
+ PlayerHand.AddCard (DrawDeck.PopTop ());
301
+
302
+ // always look at drawn cards
303
+ PlayerHand.SelectedCard ->FaceUp = true ;
304
+ }
305
+ }
306
+ }
307
+
308
+ }
309
+
310
+ BeginDrawing ();
311
+ ClearBackground (DARKGREEN);
312
+
313
+ DrawDeck.Draw ();
314
+ PlayerHand.Draw ();
315
+
316
+ EndDrawing ();
317
+ }
318
+
319
+ CloseWindow ();
320
+ }
0 commit comments