]> git.saurik.com Git - wxWidgets.git/blame - demos/bombs/bombs1.cpp
I keep running into situations where the old small default window size
[wxWidgets.git] / demos / bombs / bombs1.cpp
CommitLineData
025e88c5
JS
1///////////////////////////////////////////////////////////////////////////////
2// Name: bombs1.cpp
3// Purpose: Bombs game
4// Author: P. Foggia 1996
0c65afdb 5// Modified by: Wlodzimierz Skiba (ABX) 2003
025e88c5
JS
6// Created: 1996
7// RCS-ID: $Id$
8// Copyright: (c) 1996 P. Foggia
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12/*
13 * implementation of the methods DrawField and OnEvent of the
14 * class BombsCanvas
15 */
16
17#ifdef __GNUG__
0c65afdb 18# pragma implementation
025e88c5
JS
19#endif
20
21#include "wx/wxprec.h"
22
0c65afdb
DS
23#ifdef __BORLANDC__
24# pragma hdrstop
25#endif
26
025e88c5 27#ifndef WX_PRECOMP
0c65afdb 28# include "wx/wx.h"
025e88c5
JS
29#endif //precompiled headers
30
31#include "bombs.h"
32
0c65afdb
DS
33// Draws the field on the device context dc
34// xc1,yc1 etc. are the (inclusive) limits of the area to be drawn,
35// expressed in cells.
36void BombsCanvas::DrawField(wxDC *dc, int xc1, int yc1, int xc2, int yc2)
37{
38 wxString buf;
39 long chw, chh;
40
41 wxColour wxBlack = wxTheColourDatabase->Find(wxT("BLACK"));
42 wxColour wxWhite = wxTheColourDatabase->Find(wxT("WHITE"));
43 wxColour wxRed = wxTheColourDatabase->Find(wxT("RED"));
44 wxColour wxBlue = wxTheColourDatabase->Find(wxT("BLUE"));
45 wxColour wxGrey = wxTheColourDatabase->Find(wxT("LIGHT GREY"));
46 wxColour wxFocused = wxTheColourDatabase->Find(wxT("GREY"));
47 wxColour wxGreen = wxTheColourDatabase->Find(wxT("GREEN"));
48
49 wxPen *blackPen = wxThePenList->FindOrCreatePen(wxBlack, 1, wxSOLID);
50 wxPen *redPen = wxThePenList->FindOrCreatePen(wxRed, 1, wxSOLID);
51 wxPen *bluePen = wxThePenList->FindOrCreatePen(wxBlue, 1, wxSOLID);
52 wxBrush *whiteBrush = wxTheBrushList->FindOrCreateBrush(wxWhite, wxSOLID);
53 wxBrush *greyBrush = wxTheBrushList->FindOrCreateBrush(wxGrey, wxSOLID);
54 wxBrush *focusedBrush = wxTheBrushList->FindOrCreateBrush(wxFocused, wxSOLID);
55 wxBrush *redBrush = wxTheBrushList->FindOrCreateBrush(wxRed, wxSOLID);
56
57 dc->SetPen(* blackPen);
58
59 int x, y;
60 int xMax = this->GetGridSizeInPixels().GetWidth();
61 int yMax = this->GetGridSizeInPixels().GetHeight();
62 for(x=xc1; x<=xc2; x++)
63 dc->DrawLine(x*m_cellWidth*X_UNIT, 0, x*m_cellWidth*X_UNIT, yMax);
64 for(y=xc1; y<=yc2; y++)
65 dc->DrawLine(0, y*m_cellHeight*Y_UNIT, xMax, y*m_cellHeight*Y_UNIT);
66
67
68 wxFont font= BOMBS_FONT;
69 dc->SetFont(font);
70
71 for(x=xc1; x<=xc2; x++)
72 for(y=yc1; y<=yc2; y++)
73 {
74 if (m_game->IsMarked(x,y))
75 {
76 dc->SetPen(* blackPen);
77
78 if (m_game->IsFocussed(x, y))
79 dc->SetBrush(* focusedBrush);
80 else
81 dc->SetBrush(* greyBrush);
82
83 dc->DrawRectangle( x*m_cellWidth*X_UNIT, y*m_cellHeight*Y_UNIT,
84 m_cellWidth*X_UNIT+1, m_cellHeight*Y_UNIT+1);
85 buf = wxT("M");
86 if (!m_game->IsHidden(x,y) && m_game->IsBomb(x,y))
87 dc->SetTextForeground(wxBlue);
88 else
89 dc->SetTextForeground(wxRed);
90
91 dc->SetTextBackground(wxGrey);
92 dc->GetTextExtent(buf, &chw, &chh);
93 dc->DrawText( buf,
94 x*m_cellWidth*X_UNIT + (m_cellWidth*X_UNIT-chw)/2,
95 y*m_cellHeight*Y_UNIT + (m_cellHeight*Y_UNIT-chh)/2 );
96
97 if (!m_game->IsHidden(x,y) && m_game->IsBomb(x,y))
98 {
99 dc->SetPen(*redPen);
100 dc->DrawLine(x*m_cellWidth*X_UNIT, y*m_cellHeight*Y_UNIT,
101 (x+1)*m_cellWidth*X_UNIT, (y+1)*m_cellHeight*Y_UNIT);
102 dc->DrawLine(x*m_cellWidth*X_UNIT, (y+1)*m_cellHeight*Y_UNIT,
103 (x+1)*m_cellWidth*X_UNIT, y*m_cellHeight*Y_UNIT);
104 }
105 }
106 else if (m_game->IsHidden(x,y))
107 {
108 dc->SetPen(*blackPen);
109 if (m_game->IsFocussed(x, y))
110 dc->SetBrush(* focusedBrush);
111 else
112 dc->SetBrush(*greyBrush);
113
114 dc->DrawRectangle( x*m_cellWidth*X_UNIT, y*m_cellHeight*Y_UNIT,
115 m_cellWidth*X_UNIT+1, m_cellHeight*Y_UNIT+1);
116 }
117 else if (m_game->IsBomb(x,y))
118 {
119 dc->SetPen(* blackPen);
120 dc->SetBrush(* redBrush);
121 dc->DrawRectangle( x*m_cellWidth*X_UNIT, y*m_cellHeight*Y_UNIT,
122 m_cellWidth*X_UNIT+1, m_cellHeight*Y_UNIT+1);
123 buf = wxT("B");
124 dc->SetTextForeground(wxBlack);
125 dc->SetTextBackground(wxRed);
126 dc->GetTextExtent(buf, &chw, &chh);
127 dc->DrawText( buf,
128 x*m_cellWidth*X_UNIT + (m_cellWidth*X_UNIT-chw)/2,
129 y*m_cellHeight*Y_UNIT + (m_cellHeight*Y_UNIT-chh)/2);
130 if (m_game->IsExploded(x,y))
131 {
132 dc->SetPen(* bluePen);
133 dc->DrawLine(x*m_cellWidth*X_UNIT, y*m_cellHeight*Y_UNIT,
134 (x+1)*m_cellWidth*X_UNIT, (y+1)*m_cellHeight*Y_UNIT);
135 dc->DrawLine(x*m_cellWidth*X_UNIT, (y+1)*m_cellHeight*Y_UNIT,
136 (x+1)*m_cellWidth*X_UNIT, y*m_cellHeight*Y_UNIT);
137 }
138 }
139 else // Display a digit
140 {
141 dc->SetPen(* blackPen);
142 if (m_game->IsFocussed(x, y))
143 dc->SetBrush(* focusedBrush);
144 else
145 dc->SetBrush(* whiteBrush);
146 dc->DrawRectangle( x*m_cellWidth*X_UNIT, y*m_cellHeight*Y_UNIT,
147 m_cellWidth*X_UNIT+1, m_cellHeight*Y_UNIT+1);
148
149 int digit_value = m_game->Get(x,y) & BG_MASK;
150 switch(digit_value)
151 {
152 case 0:
153 buf = wxT("0");
154 dc->SetTextForeground(wxGreen);
155 break;
156 case 1:
157 buf = wxT("1");
158 dc->SetTextForeground(wxBlue);
159 break;
160 default:
161 buf.Printf(wxT("%d"),digit_value);
162 dc->SetTextForeground(wxBlack);
163 break;
164 }
025e88c5 165 dc->GetTextExtent(buf, &chw, &chh);
0c65afdb 166 dc->SetTextBackground(wxWhite);
025e88c5 167 dc->DrawText( buf,
0c65afdb
DS
168 x*m_cellWidth*X_UNIT + (m_cellWidth*X_UNIT-chw)/2,
169 y*m_cellHeight*Y_UNIT + (m_cellHeight*Y_UNIT-chh)/2);
170 }
025e88c5 171 }
0c65afdb
DS
172 dc->SetFont(wxNullFont);
173
174#if wxUSE_LOG
175 wxLogStatus(wxT("%d bombs %d remaining cells"),
176 m_game->GetNumBombs(), m_game->GetNumRemainingCells() );
177#endif
025e88c5
JS
178}
179
0c65afdb
DS
180// Refreshes the field image
181// xc1,yc1 etc. are the (inclusive) limits of the area to be drawn,
182// expressed in cells.
183void BombsCanvas::RefreshField(int xc1, int yc1, int xc2, int yc2)
184{
025e88c5
JS
185 wxClientDC dc(this);
186 DrawField(& dc, xc1, yc1, xc2, yc2);
0c65afdb
DS
187 if (m_bmp)
188 {
189 wxMemoryDC memDC;
190 memDC.SelectObject(*m_bmp);
025e88c5
JS
191 DrawField(&memDC, xc1, yc1, xc2, yc2);
192 memDC.SelectObject(wxNullBitmap);
0c65afdb
DS
193 }
194}
025e88c5 195
7874bf54 196// Called when uncovering a cell.
0c65afdb 197void BombsCanvas::Uncover(int x, int y)
7874bf54 198{
0c65afdb
DS
199 m_game->Unhide(x,y);
200 RefreshField(x, y, x, y);
201
202 const int gridWidth = m_game->GetWidth();
203 const int gridHeight = m_game->GetHeight();
204
205 const bool hasWon = m_game->GetNumRemainingCells() == 0;
206 if (m_game->IsBomb(x,y) || hasWon)
207 {
208 wxBell();
209 if (hasWon)
210 {
211 wxMessageBox(wxT("Nice! You found all the bombs!"),
212 wxT("wxWin Bombs"), wxOK|wxCENTRE);
213 }
214 else // x,y is a bomb
215 {
216 m_game->Explode(x, y);
217 }
218
219 for(x=0; x<gridWidth; x++)
220 for(y=0; y<gridHeight; y++)
221 m_game->Unhide(x,y);
222 RefreshField(0, 0, gridWidth-1, gridHeight-1);
7874bf54 223 }
0c65afdb
DS
224 else if (!m_game->Get(x, y))
225 {
226 int left = ( x > 0 ) ? x-1 : 0;
227 int right = ( x < gridWidth - 1 )
228 ? x+1
229 : gridWidth - 1;
230 int top = ( y > 0 ) ? y-1 : 0;
231 int bottom = ( y < gridHeight - 1 )
232 ? y+1
233 : gridHeight - 1;
234
235 int i, j;
236 for (j=top; j<=bottom; j++)
237 for (i=left; i<=right; i++)
238 if ( (i != x || j != y) && m_game->IsHidden(i, j)
239 && !m_game->IsMarked(i, j) )
240 {
241 Uncover(i, j);
242 }
7874bf54
VZ
243 }
244}
245
025e88c5 246// Called when the canvas receives a mouse event.
0c65afdb 247void BombsCanvas::OnMouseEvent(wxMouseEvent& event)
f5d01a1c 248{
0c65afdb
DS
249 const int gridWidth = m_game->GetWidth();
250 const int gridHeight = m_game->GetHeight();
251
252 wxCoord fx, fy;
253 event.GetPosition(&fx, &fy);
254 int x = fx/(m_cellWidth*X_UNIT);
255 int y = fy/(m_cellHeight*Y_UNIT);
256 if (x<gridWidth && y<gridHeight)
257 {
258 if ( (event.RightDown() || (event.LeftDown() && event.ShiftDown()))
259 && (m_game->IsHidden(x,y)
260 || !m_game->GetNumRemainingCells() ) )
261 {
262 // store previous and current field
263 int prevFocusX = m_game->m_gridFocusX;
264 int prevFocusY = m_game->m_gridFocusY;
265 m_game->m_gridFocusX = x;
266 m_game->m_gridFocusY = y;
267 RefreshField(prevFocusX, prevFocusY, prevFocusX, prevFocusY);
268 m_game->Mark(x, y);
269 RefreshField(x, y, x, y);
270 return;
025e88c5 271 }
0c65afdb
DS
272 else if (event.LeftDown() && m_game->IsHidden(x,y)
273 && !m_game->IsMarked(x,y))
274 {
275 // store previous and current field
276 int prevGridFocusX = m_game->m_gridFocusX;
277 int prevGridFocusY = m_game->m_gridFocusY;
278 m_game->m_gridFocusX = x;
279 m_game->m_gridFocusY = y;
280 RefreshField(prevGridFocusX, prevGridFocusY,
281 prevGridFocusX, prevGridFocusY);
282 Uncover(x, y);
283 return;
025e88c5
JS
284 }
285 }
286}
287
0c65afdb
DS
288void BombsCanvas::OnChar(wxKeyEvent& event)
289{
290 int keyCode = event.GetKeyCode();
291 int prevGridFocusX = m_game->m_gridFocusX;
292 int prevGridFocusY = m_game->m_gridFocusY;
293
294 const int gridWidth = m_game->GetWidth();
295 const int gridHeight = m_game->GetHeight();
296
297 switch(keyCode)
298 {
299
300 case WXK_RIGHT:
301 m_game->m_gridFocusX++;
302 if (m_game->m_gridFocusX >= gridWidth) m_game->m_gridFocusX = 0;
303 break;
304
305 case WXK_LEFT:
306 m_game->m_gridFocusX--;
307 if (m_game->m_gridFocusX<0) m_game->m_gridFocusX = gridWidth-1;
308 break;
309
310 case WXK_DOWN:
311 m_game->m_gridFocusY++;
312 if (m_game->m_gridFocusY >= gridHeight) m_game->m_gridFocusY = 0;
313 break;
314
315 case WXK_UP:
316 m_game->m_gridFocusY--;
317 if (m_game->m_gridFocusY<0) m_game->m_gridFocusY = gridHeight-1;
318 break;
319
320 case WXK_RETURN:
321 if ( (prevGridFocusX == m_game->m_gridFocusX)
322 && (prevGridFocusY == m_game->m_gridFocusY)
323 && (m_game->IsHidden(m_game->m_gridFocusX, m_game->m_gridFocusY)) )
324 {
325 m_game->Mark(m_game->m_gridFocusX, m_game->m_gridFocusY);
326 if (!m_game->IsMarked(m_game->m_gridFocusX, m_game->m_gridFocusY))
327 {
328 Uncover(m_game->m_gridFocusX, m_game->m_gridFocusY);
329 }
330 RefreshField(m_game->m_gridFocusX, m_game->m_gridFocusY,
331 m_game->m_gridFocusX, m_game->m_gridFocusY);
332 }
333 break;
334
335 default:
336 event.Skip();
337
338 }
339
340 if ((prevGridFocusX != m_game->m_gridFocusX)
341 || (prevGridFocusY != m_game->m_gridFocusY))
342 {
23290a8c
JS
343 // cause focused field to be visible after first key hit after launching new game
344 if( m_game->m_gridFocusX < 0 ) m_game->m_gridFocusX = 0;
345 if( m_game->m_gridFocusY < 0 ) m_game->m_gridFocusY = 0;
346
0c65afdb
DS
347 // refresh previous field and focused field
348 RefreshField(prevGridFocusX, prevGridFocusY,
349 prevGridFocusX, prevGridFocusY);
350 RefreshField(m_game->m_gridFocusX, m_game->m_gridFocusY,
351 m_game->m_gridFocusX, m_game->m_gridFocusY);
352 }
353}