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