]> git.saurik.com Git - wxWidgets.git/blob - demos/forty/pile.cpp
Fix a crash in wxExecute() in wxMSW too.
[wxWidgets.git] / demos / forty / pile.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: pile.cpp
3 // Purpose: Forty Thieves patience game
4 // Author: Chris Breeze
5 // Modified by:
6 // Created: 21/07/97
7 // RCS-ID: $Id$
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 //| The base class for holding piles of playing cards. |
16 //+-------------------------------------------------------------+
17
18 // For compilers that support precompilation, includes "wx/wx.h".
19 #include "wx/wxprec.h"
20
21 #ifdef __BORLANDC__
22 #pragma hdrstop
23 #endif
24
25 #ifndef WX_PRECOMP
26 #include "wx/wx.h"
27 #endif
28
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <time.h>
32 #include <string.h>
33 #include "card.h"
34 #include "pile.h"
35 #include "forty.h"
36 #include "canvas.h"
37
38 #include "wx/app.h"
39
40 //+-------------------------------------------------------------+
41 //| Pile::Pile() |
42 //+-------------------------------------------------------------+
43 //| Description: |
44 //| Initialise the pile to be empty of cards. |
45 //+-------------------------------------------------------------+
46 Pile::Pile(int x, int y, int dx, int dy)
47 {
48 m_x = x;
49 m_y = y;
50 m_dx = dx;
51 m_dy = dy;
52 for (m_topCard = 0; m_topCard < NumCards; m_topCard++)
53 {
54 m_cards[m_topCard] = 0;
55 }
56 m_topCard = -1; // i.e. empty
57 }
58
59
60 //+-------------------------------------------------------------+
61 //| Pile::Redraw() |
62 //+-------------------------------------------------------------+
63 //| Description: |
64 //| Redraw the pile on the screen. If the pile is empty |
65 //| just draw a NULL card as a place holder for the pile. |
66 //| Otherwise draw the pile from the bottom up, starting |
67 //| at the origin of the pile, shifting each subsequent |
68 //| card by the pile's x and y offsets. |
69 //+-------------------------------------------------------------+
70 void Pile::Redraw(wxDC& dc )
71 {
72 FortyFrame *frame = (FortyFrame*) wxTheApp->GetTopWindow();
73 wxWindow *canvas = (wxWindow *) NULL;
74 if (frame)
75 {
76 canvas = frame->GetCanvas();
77 }
78
79 if (m_topCard >= 0)
80 {
81 if (m_dx == 0 && m_dy == 0)
82 {
83 if ((canvas) && (canvas->IsExposed(m_x,m_y,(int)(Card::GetScale()*60),(int)(Card::GetScale()*200))))
84 m_cards[m_topCard]->Draw(dc, m_x, m_y);
85 }
86 else
87 {
88 int x = m_x;
89 int y = m_y;
90 for (int i = 0; i <= m_topCard; i++)
91 {
92 if ((canvas) && (canvas->IsExposed(x,y,(int)(Card::GetScale()*60),(int)(Card::GetScale()*200))))
93 m_cards[i]->Draw(dc, x, y);
94 x += (int)Card::GetScale()*m_dx;
95 y += (int)Card::GetScale()*m_dy;
96 }
97 }
98 }
99 else
100 {
101 if ((canvas) && (canvas->IsExposed(m_x,m_y,(int)(Card::GetScale()*60),(int)(Card::GetScale()*200))))
102 Card::DrawNullCard(dc, m_x, m_y);
103 }
104 }
105
106
107 //+-------------------------------------------------------------+
108 //| Pile::GetTopCard() |
109 //+-------------------------------------------------------------+
110 //| Description: |
111 //| Return a pointer to the top card in the pile or NULL |
112 //| if the pile is empty. |
113 //| NB: Gets a copy of the card without removing it from the |
114 //| pile. |
115 //+-------------------------------------------------------------+
116 Card* Pile::GetTopCard()
117 {
118 Card* card = 0;
119
120 if (m_topCard >= 0)
121 {
122 card = m_cards[m_topCard];
123 }
124 return card;
125 }
126
127
128 //+-------------------------------------------------------------+
129 //| Pile::RemoveTopCard() |
130 //+-------------------------------------------------------------+
131 //| Description: |
132 //| If the pile is not empty, remove the top card from the |
133 //| pile and return the pointer to the removed card. |
134 //| If the pile is empty return a NULL pointer. |
135 //+-------------------------------------------------------------+
136 Card* Pile::RemoveTopCard()
137 {
138 Card* card = 0;
139
140 if (m_topCard >= 0)
141 {
142 card = m_cards[m_topCard--];
143 }
144 return card;
145 }
146
147
148 //+-------------------------------------------------------------+
149 //| Pile::RemoveTopCard() |
150 //+-------------------------------------------------------------+
151 //| Description: |
152 //| As RemoveTopCard() but also redraw the top of the pile |
153 //| after the card has been removed. |
154 //| NB: the offset allows for the redrawn area to be in a |
155 //| bitmap ready for 'dragging' cards acrosss the screen. |
156 //+-------------------------------------------------------------+
157 Card* Pile::RemoveTopCard(wxDC& dc, int xOffset, int yOffset)
158 {
159 int topX, topY, x, y;
160
161 GetTopCardPos(topX, topY);
162 Card* card = RemoveTopCard();
163
164 if (card)
165 {
166 card->Erase(dc, topX - xOffset, topY - yOffset);
167 GetTopCardPos(x, y);
168 if (m_topCard < 0)
169 {
170 Card::DrawNullCard(dc, x - xOffset, y - yOffset);
171 }
172 else
173 {
174 m_cards[m_topCard]->Draw(dc, x - xOffset, y - yOffset);
175 }
176 }
177
178 return card;
179 }
180
181
182 void Pile::GetTopCardPos(int& x, int& y)
183 {
184 if (m_topCard < 0)
185 {
186 x = m_x;
187 y = m_y;
188 }
189 else
190 {
191 x = m_x + (int)Card::GetScale()*m_dx * m_topCard;
192 y = m_y + (int)Card::GetScale()*m_dy * m_topCard;
193 }
194 }
195
196 void Pile::AddCard(Card* card)
197 {
198 if (m_topCard < -1) m_topCard = -1;
199
200 m_cards[++m_topCard] = card;
201 }
202
203 void Pile::AddCard(wxDC& dc, Card* card)
204 {
205 AddCard(card);
206 int x, y;
207 GetTopCardPos(x, y);
208 card->Draw(dc, x, y);
209 }
210
211 // Can the card leave this pile.
212 // If it is a member of the pile then the answer is yes.
213 // Derived classes may override this behaviour to incorporate
214 // the rules of the game
215 bool Pile::CanCardLeave(Card* card)
216 {
217 for (int i = 0; i <= m_topCard; i++)
218 {
219 if (card == m_cards[i]) return true;
220 }
221 return false;
222 }
223
224 // Calculate how far x, y is from top card in the pile
225 // Returns the square of the distance
226 int Pile::CalcDistance(int x, int y)
227 {
228 int cx, cy;
229 GetTopCardPos(cx, cy);
230 return ((cx - x) * (cx - x) + (cy - y) * (cy - y));
231 }
232
233
234 // Return the card at x, y. Check the top card first, then
235 // work down the pile. If a card is found then return a pointer
236 // to the card, otherwise return NULL
237 Card* Pile::GetCard(int x, int y)
238 {
239 int cardX;
240 int cardY;
241 GetTopCardPos(cardX, cardY);
242
243 for (int i = m_topCard; i >= 0; i--)
244 {
245 if (x >= cardX && x <= cardX + Card::GetWidth() &&
246 y >= cardY && y <= cardY + Card::GetHeight())
247 {
248 return m_cards[i];
249 }
250 cardX -= (int)Card::GetScale()*m_dx;
251 cardY -= (int)Card::GetScale()*m_dy;
252 }
253 return 0;
254 }
255
256
257 // Return the position of the given card. If it is not a member of this pile
258 // return the origin of the pile.
259 void Pile::GetCardPos(Card* card, int& x, int& y)
260 {
261 x = m_x;
262 y = m_y;
263
264 for (int i = 0; i <= m_topCard; i++)
265 {
266 if (card == m_cards[i])
267 {
268 return;
269 }
270 x += (int)Card::GetScale()*m_dx;
271 y += (int)Card::GetScale()*m_dy;
272 }
273
274 // card not found in pile, return origin of pile
275 x = m_x;
276 y = m_y;
277 }
278
279
280 bool Pile::Overlap(int x, int y)
281 {
282 int cardX;
283 int cardY;
284 GetTopCardPos(cardX, cardY);
285
286 if (x >= cardX - Card::GetWidth() && x <= cardX + Card::GetWidth() &&
287 y >= cardY - Card::GetHeight() && y <= cardY + Card::GetHeight())
288 {
289 return true;
290 }
291 return false;
292 }