1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        card.cpp
3 // Purpose:     Forty Thieves patience game
4 // Author:      Chris Breeze
5 // Modified by:
6 // Created:     21/07/97
7 // RCS-ID:      $Id: card.cpp 39615 2006-06-07 13:26:00Z ABX $
8 // Copyright:   (c) 1993-1998 Chris Breeze
9 // Licence:     wxWindows licence
10 //---------------------------------------------------------------------------
11 // Last modified: 22nd July 1998 - ported to wxWidgets 2.0
12 /////////////////////////////////////////////////////////////////////////////
13 //+-------------------------------------------------------------+
14 //| Description
15 //| A class for drawing playing cards.
16 //| Currently assumes that the card symbols have been
17 //| loaded into hbmap_symbols and the pictures for the
18 //| Jack, Queen and King have been loaded into
19 //| hbmap_pictures.
20 //+-------------------------------------------------------------+
21 
22 // For compilers that support precompilation, includes "wx/wx.h".
23 #include "wx/wxprec.h"
24 
25 #ifdef __BORLANDC__
26 #pragma hdrstop
27 #endif
28 
29 #ifndef WX_PRECOMP
30 #include "wx/wx.h"
31 #endif
32 
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include "forty.h"
37 #include "card.h"
38 
39 #include "pictures.xpm"
40 #include "symbols.xpm"
41 
42 wxBitmap* Card::m_pictureBmap = 0;
43 wxBitmap* Card::m_symbolBmap = 0;
44 
45 double Card::m_scale = 1.0;
46 int Card::m_width = 50;
47 int Card::m_height = 70;
48 
49 //+-------------------------------------------------------------+
50 //| Card::Card()                                                |
51 //+-------------------------------------------------------------+
52 //| Description:                                                |
53 //| Constructor for a playing card.                             |
54 //| Checks that the value is in the range 1..52 and then        |
55 //| initialises the suit, colour, pipValue and wayUp.           |
56 //+-------------------------------------------------------------+
Card(int value,WayUp way_up)57 Card::Card(int value, WayUp way_up) :
58       m_wayUp(way_up)
59 {
60     if (!m_symbolBmap)
61     {
62         m_symbolBmap = new wxBitmap(symbols_xpm);
63         if (!m_symbolBmap->Ok())
64         {
65             ::wxMessageBox(_T("Failed to load bitmap CardSymbols"), _T("Error"));
66         }
67     }
68     if (!m_pictureBmap)
69     {
70         m_pictureBmap = new wxBitmap(Pictures);
71         if (!m_pictureBmap->Ok())
72         {
73             ::wxMessageBox(_T("Failed to load bitmap CardPictures"), _T("Error"));
74         }
75     }
76 
77     if (value >= 1 && value <= PackSize)
78     {
79         switch ((value - 1) / 13)
80         {
81             case 0:
82                 m_suit = clubs;
83                 m_colour = black;
84                 break;
85             case 1:
86                 m_suit = diamonds;
87                 m_colour = red;
88                 break;
89             case 2:
90                 m_suit = hearts;
91                 m_colour = red;
92                 break;
93             case 3:
94                 m_suit = spades;
95                 m_colour = black;
96                 break;
97         }
98         m_pipValue = 1 + (value - 1) % 13;
99         m_status = true;
100     }
101     else
102     {
103         m_status = false;
104     }
105 } // Card::Card()
106 
107 
108 //+-------------------------------------------------------------+
109 //| Card::SetScale()                                            |
110 //+-------------------------------------------------------------+
111 //| Description:                                                |
112 //|     Scales the cards                                        |
113 //+-------------------------------------------------------------+
SetScale(double scale)114 void Card::SetScale(double scale)
115 {
116     m_scale = scale;
117     m_width = int(50*scale);
118     m_height = int(70*scale);
119 }
120 
121 //+-------------------------------------------------------------+
122 //| Card::Erase()                                               |
123 //+-------------------------------------------------------------+
124 //| Description:                                                |
125 //| Erase the card at (x, y) by drawing a rectangle in the      |
126 //| background colour.                                          |
127 //+-------------------------------------------------------------+
Erase(wxDC & dc,int x,int y)128 void Card::Erase(wxDC& dc, int x, int y)
129 {
130     wxPen* pen = wxThePenList->FindOrCreatePen(
131                         FortyApp::BackgroundColour(),
132                         1,
133                         wxSOLID
134                         );
135     dc.SetPen(* pen);
136     dc.SetBrush(FortyApp::BackgroundBrush());
137         dc.DrawRectangle(x, y, m_width, m_height);
138 } // Card::Erase()
139 
140 
141 //+-------------------------------------------------------------+
142 //| Card::Draw()                                                |
143 //+-------------------------------------------------------------+
144 //| Description:                                                |
145 //| Draw the card at (x, y).                                    |
146 //| If the card is facedown draw the back of the card.          |
147 //| If the card is faceup draw the front of the card.           |
148 //| Cards are not held in bitmaps, instead they are drawn       |
149 //| from their constituent parts when required.                 |
150 //| hbmap_symbols contains large and small suit symbols and     |
151 //| pip values. These are copied to the appropriate part of     |
152 //| the card. Picture cards use the pictures defined in         |
153 //| hbmap_pictures. Note that only one picture is defined       |
154 //| for the Jack, Queen and King, unlike a real pack where      |
155 //| each suit is different.                                     |
156 //|                                                             |
157 //| WARNING:                                                    |
158 //| The locations of these symbols is 'hard-wired' into the     |
159 //| code. Editing the bitmaps or the numbers below will         |
160 //| result in the wrong symbols being displayed.                |
161 //+-------------------------------------------------------------+
Draw(wxDC & dc,int x,int y)162 void Card::Draw(wxDC& dc, int x, int y)
163 {
164     wxBrush backgroundBrush( dc.GetBackground() );
165     dc.SetBrush(* wxWHITE_BRUSH);
166     dc.SetPen(* wxBLACK_PEN);
167         dc.DrawRoundedRectangle(x, y, m_width, m_height, 4);
168     if (m_wayUp == facedown)
169     {
170         dc.SetBackground(* wxRED_BRUSH);
171         dc.SetBackgroundMode(wxSOLID);
172         wxBrush* brush = wxTheBrushList->FindOrCreateBrush(
173                             *wxBLACK, wxCROSSDIAG_HATCH
174                             );
175         dc.SetBrush(* brush);
176 
177         dc.DrawRoundedRectangle(
178                 x + 4, y + 4,
179                 m_width - 8, m_height - 8,
180                 2
181                 );
182     }
183     else
184     {
185         wxMemoryDC memoryDC;
186 
187         memoryDC.SelectObject(*m_symbolBmap);
188 
189 //        dc.SetBackgroundMode(wxTRANSPARENT);
190 
191         dc.SetTextBackground(*wxWHITE);
192         switch (m_suit)
193         {
194             case spades:
195             case clubs:
196                 dc.SetTextForeground(*wxBLACK);
197                 break;
198             case diamonds:
199             case hearts:
200                 dc.SetTextForeground(*wxRED);
201                 break;
202         }
203 
204         int symsize = 11;
205         int sympos = 14;
206         int sympos2 = 25;
207         int symdist = 5;
208         int symdist2 = 6;
209 
210         int pipsize,pippos,valueheight,valuewidth;
211         int valuepos;
212         if (m_scale > 1.2)
213         {
214             pipsize = symsize;
215             pippos = sympos;
216             valueheight = 10;
217             valuewidth = 9;
218             valuepos = 50;
219         }
220         else
221         {
222             pipsize = 7;
223             pippos = 0;
224             valueheight = 7;
225             valuewidth = 6;
226             valuepos = 36;
227         }
228 
229         // Draw the value
230         dc.Blit((wxCoord)(x + m_scale*3),
231                 (wxCoord)(y + m_scale*3),
232                 valuewidth,
233                 valueheight,
234                 &memoryDC,
235                 valuewidth * (m_pipValue - 1),
236                 valuepos,
237                 wxCOPY);
238         dc.Blit((wxCoord)(x + m_width - m_scale*3 - valuewidth),
239                 (wxCoord)(y + m_height - valueheight - m_scale*3),
240                 valuewidth,
241                 valueheight,
242                 &memoryDC,
243                 valuewidth * (m_pipValue - 1),
244                 valuepos+valueheight,
245                 wxCOPY);
246 
247         // Draw the pips
248         dc.Blit((wxCoord)(x + m_scale*3 + valuewidth+2),
249                 (wxCoord)(y + m_scale*3),
250                 pipsize,
251                 pipsize,
252                 &memoryDC,
253                 pipsize * m_suit,
254                 pippos,
255                 wxCOPY);
256         dc.Blit((wxCoord)(x + m_width - m_scale*3-valuewidth-pipsize-2),
257                 (wxCoord)(y + m_height - pipsize - m_scale*3),
258                 pipsize,
259                 pipsize,
260                 &memoryDC,
261                 pipsize * m_suit,
262                 pipsize+pippos,
263                 wxCOPY);
264 
265         switch (m_pipValue)
266         {
267         case 1:
268             dc.Blit((wxCoord)(x - symdist + m_width / 2),
269                     (wxCoord)(y - m_scale*5 + m_height / 2),
270                     symsize,
271                     symsize,
272                     &memoryDC,
273                     symsize * m_suit,
274                     sympos,
275                     wxCOPY);
276             break;
277 
278         case 3:
279             dc.Blit((wxCoord)(x - symdist + m_width / 2),
280                     (wxCoord)(y - symdist + m_height / 2),
281                     symsize,
282                     symsize,
283                     &memoryDC,
284                     symsize * m_suit,
285                     sympos,
286                     wxCOPY);
287         case 2:
288             dc.Blit((wxCoord)(x - symdist + m_width / 2),
289                     (wxCoord)(y - symdist + m_height / 4),
290                     symsize,
291                     symsize,
292                     &memoryDC,
293                     symsize * m_suit,
294                     sympos,
295                     wxCOPY);
296             dc.Blit((wxCoord)(x - symdist + m_width / 2),
297                     (wxCoord)(y - symdist + 3 * m_height / 4),
298                     symsize,
299                     symsize,
300                     &memoryDC,
301                     symsize * m_suit,
302                     sympos2,
303                     wxCOPY);
304             break;
305 
306         case 5:
307             dc.Blit((wxCoord)(x - symdist + m_width / 2),
308                     (wxCoord)(y - symdist + m_height / 2),
309                     symsize,
310                     symsize,
311                     &memoryDC,
312                     symsize * m_suit,
313                     sympos,
314                     wxCOPY);
315         case 4:
316             dc.Blit((wxCoord)(x - symdist +  m_width / 4),
317                     (wxCoord)(y - symdist + m_height / 4),
318                     symsize,
319                     symsize,
320                     &memoryDC,
321                     symsize * m_suit,
322                     sympos,
323                     wxCOPY);
324             dc.Blit((wxCoord)(x - symdist + m_width / 4),
325                     (wxCoord)(y - symdist + 3 * m_height / 4),
326                     symsize,
327                     symsize,
328                     &memoryDC,
329                     symsize * m_suit,
330                     sympos2,
331                     wxCOPY);
332             dc.Blit((wxCoord)(x - symdist + 3 * m_width / 4),
333                     (wxCoord)(y - symdist + m_height / 4),
334                     symsize,
335                     symsize,
336                     &memoryDC,
337                     symsize * m_suit,
338                     sympos,
339                     wxCOPY);
340             dc.Blit((wxCoord)(x - symdist + 3 * m_width / 4),
341                     (wxCoord)(y - symdist + 3 * m_height / 4),
342                     symsize,
343                     symsize,
344                     &memoryDC,
345                     symsize * m_suit,
346                     sympos2,
347                     wxCOPY);
348             break;
349 
350         case 8:
351             dc.Blit((wxCoord)(x - symdist + 5 * m_width / 10),
352                     (wxCoord)(y - symdist + 5 * m_height / 8),
353                     symsize,
354                     symsize,
355                     &memoryDC,
356                     symsize * m_suit,
357                     sympos2,
358                     wxCOPY);
359         case 7:
360             dc.Blit((wxCoord)(x - symdist + 5 * m_width / 10),
361                     (wxCoord)(y - symdist + 3 * m_height / 8),
362                     symsize,
363                     symsize,
364                     &memoryDC,
365                     symsize * m_suit,
366                     sympos,
367                     wxCOPY);
368         case 6:
369             dc.Blit((wxCoord)(x - symdist + m_width / 4),
370                     (wxCoord)(y - symdist + m_height / 4),
371                     symsize,
372                     symsize,
373                     &memoryDC, symsize * m_suit, sympos, wxCOPY);
374             dc.Blit((wxCoord)(x - symdist + m_width / 4),
375                     (wxCoord)(y - symdist + m_height / 2),
376                     symsize,
377                     symsize,
378                     &memoryDC,
379                     symsize * m_suit,
380                     sympos,
381                     wxCOPY);
382             dc.Blit((wxCoord)(x - symdist + m_width / 4),
383                     (wxCoord)(y - symdist + 3 * m_height / 4),
384                     symsize,
385                     symsize,
386                     &memoryDC,
387                     symsize * m_suit,
388                     sympos2,
389                     wxCOPY);
390             dc.Blit((wxCoord)(x - symdist + 3 * m_width / 4),
391                     (wxCoord)(y - symdist + m_height / 4),
392                     symsize,
393                     symsize,
394                     &memoryDC,
395                     symsize * m_suit,
396                     sympos,
397                     wxCOPY);
398             dc.Blit((wxCoord)(x - symdist + 3 * m_width / 4),
399                     (wxCoord)(y - symdist + m_height / 2),
400                     symsize,
401                     symsize,
402                     &memoryDC,
403                     symsize * m_suit,
404                     sympos,
405                     wxCOPY);
406             dc.Blit((wxCoord)(x - symdist + 3 * m_width / 4),
407                     (wxCoord)(y - symdist + 3 * m_height / 4),
408                     symsize,
409                     symsize,
410                     &memoryDC,
411                     symsize * m_suit,
412                     sympos2,
413                     wxCOPY);
414             break;
415 
416         case 10:
417             dc.Blit((wxCoord)(x - symdist + m_width / 2),
418                     (wxCoord)(y - symdist + 2 * m_height / 3),
419                     symsize,
420                     symsize,
421                     &memoryDC,
422                     symsize * m_suit,
423                     sympos2,
424                     wxCOPY);
425         case 9:
426             dc.Blit((wxCoord)(x - symdist + m_width / 4),
427                     (wxCoord)(y - symdist2 + m_height / 4),
428                     symsize,
429                     symsize,
430                     &memoryDC,
431                     symsize * m_suit,
432                     sympos,
433                     wxCOPY);
434             dc.Blit((wxCoord)(x - symdist + m_width / 4),
435                     (wxCoord)(y - symdist2 + 5 * m_height / 12),
436                     symsize,
437                     symsize,
438                     &memoryDC,
439                     symsize * m_suit,
440                     sympos,
441                     wxCOPY);
442             dc.Blit((wxCoord)(x - symdist + m_width / 4),
443                     (wxCoord)(y - symdist + 7 * m_height / 12),
444                     symsize,
445                     symsize,
446                     &memoryDC,
447                     symsize * m_suit,
448                     sympos2,
449                     wxCOPY);
450             dc.Blit((wxCoord)(x - symdist + m_width / 4),
451                     (wxCoord)(y - symdist + 3 * m_height / 4),
452                     symsize,
453                     symsize,
454                     &memoryDC,
455                     symsize * m_suit,
456                     sympos2,
457                     wxCOPY);
458 
459             dc.Blit((wxCoord)(x - symdist + 3 * m_width / 4),
460                     (wxCoord)(y - symdist2 + m_height / 4),
461                     symsize,
462                     symsize,
463                     &memoryDC,
464                     symsize * m_suit,
465                     sympos,
466                     wxCOPY);
467             dc.Blit((wxCoord)(x - symdist + 3 * m_width / 4),
468                     (wxCoord)(y - symdist2 + 5 * m_height / 12),
469                     symsize,
470                     symsize,
471                     &memoryDC,
472                     symsize * m_suit,
473                     sympos,
474                     wxCOPY);
475             dc.Blit((wxCoord)(x - symdist + 3 * m_width / 4),
476                     (wxCoord)(y - symdist + 7 * m_height / 12),
477                     symsize,
478                     symsize,
479                     &memoryDC,
480                     symsize * m_suit,
481                     sympos2,
482                     wxCOPY);
483             dc.Blit((wxCoord)(x - symdist + 3 * m_width / 4),
484                     (wxCoord)(y - symdist + 3 * m_height / 4),
485                     symsize,
486                     symsize,
487                     &memoryDC,
488                     symsize * m_suit,
489                     sympos2,
490                     wxCOPY);
491             dc.Blit((wxCoord)(x - symdist + m_width / 2),
492                     (wxCoord)(y - symdist + m_height / 3),
493                     symsize,
494                     symsize,
495                     &memoryDC,
496                     symsize * m_suit,
497                     sympos,
498                     wxCOPY);
499             break;
500         case 11:
501         case 12:
502         case 13:
503             memoryDC.SelectObject(*m_pictureBmap);
504             int picwidth = 40,picheight = 45;
505             dc.Blit((wxCoord)(x + (m_width-picwidth)/2),
506                     (wxCoord)(y - picheight/2 + m_height/2),
507                     picwidth,
508                     picheight,
509                     &memoryDC,
510                     picwidth * (m_pipValue - 11),
511                     0,
512                     wxCOPY);
513 
514             memoryDC.SelectObject(*m_symbolBmap);
515             dc.Blit((wxCoord)(x + m_width-(m_width-picwidth)/2-symsize-3),
516                     (wxCoord)(y - picheight/2+m_height/2+1),
517                     symsize,
518                     symsize,
519                     &memoryDC,
520                     symsize * m_suit,
521                     sympos,
522                     wxCOPY);
523             dc.Blit((wxCoord)(x + (m_width-picwidth)/2+2),
524                     (wxCoord)(y + picheight/2 + m_height/2-symsize),
525                     symsize,
526                     symsize,
527                     &memoryDC,
528                     symsize * m_suit,
529                     sympos2,
530                     wxCOPY);
531             break;
532         }
533 
534     }
535     dc.SetBackground( backgroundBrush );
536 } // Card:Draw()
537 
538 
539 //+-------------------------------------------------------------+
540 //| Card::DrawNullCard()                                        |
541 //+-------------------------------------------------------------+
542 //| Description:                                                |
543 //| Draws the outline of a card at (x, y).                      |
544 //| Used to draw place holders for empty piles of cards.        |
545 //+-------------------------------------------------------------+
DrawNullCard(wxDC & dc,int x,int y)546 void Card::DrawNullCard(wxDC& dc, int x, int y)
547 {
548     wxPen* pen = wxThePenList->FindOrCreatePen(FortyApp::TextColour(), 1, wxSOLID);
549     dc.SetBrush(FortyApp::BackgroundBrush());
550     dc.SetPen(*pen);
551     dc.DrawRoundedRectangle(x, y, m_width, m_height, 4);
552 } // Card::DrawNullCard()
553