card.cpp 19 KB

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