]>
git.saurik.com Git - wxWidgets.git/blob - demos/bombs/bombs1.cpp
1 ///////////////////////////////////////////////////////////////////////////////
4 // Author: P. Foggia 1996
5 // Modified by: Wlodzimierz Skiba (ABX) since 2003
7 // Copyright: (c) 1996 P. Foggia
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
12 * implementation of the methods DrawField and OnEvent of the
16 #include "wx/wxprec.h"
24 #endif //precompiled headers
28 // Draws the field on the device context dc
29 // xc1,yc1 etc. are the (inclusive) limits of the area to be drawn,
30 // expressed in cells.
31 void BombsCanvas::DrawField(wxDC
*dc
, int xc1
, int yc1
, int xc2
, int yc2
)
36 wxColour wxYellow
= wxTheColourDatabase
->Find(wxT("YELLOW"));
37 wxColour wxFocused
= wxTheColourDatabase
->Find(wxT("GREY"));
39 wxPen
*bluePen
= wxThePenList
->FindOrCreatePen(*wxBLUE
, 1, wxSOLID
);
41 wxBrush
*focusedBrush
= wxTheBrushList
->FindOrCreateBrush(wxFocused
, wxSOLID
);
42 wxBrush
*yellowBrush
= wxTheBrushList
->FindOrCreateBrush(wxYellow
, wxSOLID
);
44 dc
->SetPen(*wxBLACK_PEN
);
47 int xMax
= this->GetGridSizeInPixels().GetWidth();
48 int yMax
= this->GetGridSizeInPixels().GetHeight();
49 for(x
=xc1
; x
<=xc2
; x
++)
50 dc
->DrawLine(x
*m_cellWidth
*X_UNIT
, 0, x
*m_cellWidth
*X_UNIT
, yMax
);
51 for(y
=xc1
; y
<=yc2
; y
++)
52 dc
->DrawLine(0, y
*m_cellHeight
*Y_UNIT
, xMax
, y
*m_cellHeight
*Y_UNIT
);
55 wxFont font
= BOMBS_FONT
;
58 for(x
=xc1
; x
<=xc2
; x
++)
59 for(y
=yc1
; y
<=yc2
; y
++)
61 if (m_game
->IsMarked(x
,y
))
63 dc
->SetPen(*wxBLACK_PEN
);
65 if (m_game
->IsFocussed(x
, y
))
66 dc
->SetBrush(*focusedBrush
);
68 dc
->SetBrush(*wxLIGHT_GREY_BRUSH
);
70 dc
->DrawRectangle( x
*m_cellWidth
*X_UNIT
, y
*m_cellHeight
*Y_UNIT
,
71 m_cellWidth
*X_UNIT
+1, m_cellHeight
*Y_UNIT
+1);
73 if (!m_game
->IsHidden(x
,y
) && m_game
->IsBomb(x
,y
))
74 dc
->SetTextForeground(*wxBLUE
);
76 dc
->SetTextForeground(*wxRED
);
78 dc
->SetTextBackground(*wxLIGHT_GREY
);
79 dc
->GetTextExtent(buf
, &chw
, &chh
);
81 x
*m_cellWidth
*X_UNIT
+ (m_cellWidth
*X_UNIT
-chw
)/2,
82 y
*m_cellHeight
*Y_UNIT
+ (m_cellHeight
*Y_UNIT
-chh
)/2 );
84 if (!m_game
->IsHidden(x
,y
) && m_game
->IsBomb(x
,y
))
86 dc
->SetPen(*wxRED_PEN
);
87 dc
->DrawLine(x
*m_cellWidth
*X_UNIT
, y
*m_cellHeight
*Y_UNIT
,
88 (x
+1)*m_cellWidth
*X_UNIT
, (y
+1)*m_cellHeight
*Y_UNIT
);
89 dc
->DrawLine(x
*m_cellWidth
*X_UNIT
, (y
+1)*m_cellHeight
*Y_UNIT
,
90 (x
+1)*m_cellWidth
*X_UNIT
, y
*m_cellHeight
*Y_UNIT
);
93 else if (m_game
->IsHidden(x
,y
))
95 dc
->SetPen(*wxBLACK_PEN
);
96 if (m_game
->IsFocussed(x
, y
))
97 dc
->SetBrush(*focusedBrush
);
99 dc
->SetBrush(*wxLIGHT_GREY_BRUSH
);
101 dc
->DrawRectangle( x
*m_cellWidth
*X_UNIT
, y
*m_cellHeight
*Y_UNIT
,
102 m_cellWidth
*X_UNIT
+1, m_cellHeight
*Y_UNIT
+1);
104 else if (m_game
->IsBomb(x
,y
))
106 dc
->SetPen(*wxBLACK_PEN
);
107 dc
->SetBrush(*wxRED_BRUSH
);
108 dc
->DrawRectangle( x
*m_cellWidth
*X_UNIT
, y
*m_cellHeight
*Y_UNIT
,
109 m_cellWidth
*X_UNIT
+1, m_cellHeight
*Y_UNIT
+1);
111 dc
->SetTextForeground(*wxBLACK
);
112 dc
->SetTextBackground(*wxRED
);
113 dc
->GetTextExtent(buf
, &chw
, &chh
);
115 x
*m_cellWidth
*X_UNIT
+ (m_cellWidth
*X_UNIT
-chw
)/2,
116 y
*m_cellHeight
*Y_UNIT
+ (m_cellHeight
*Y_UNIT
-chh
)/2);
117 if (m_game
->IsExploded(x
,y
))
119 dc
->SetPen(*bluePen
);
120 dc
->DrawLine(x
*m_cellWidth
*X_UNIT
, y
*m_cellHeight
*Y_UNIT
,
121 (x
+1)*m_cellWidth
*X_UNIT
, (y
+1)*m_cellHeight
*Y_UNIT
);
122 dc
->DrawLine(x
*m_cellWidth
*X_UNIT
, (y
+1)*m_cellHeight
*Y_UNIT
,
123 (x
+1)*m_cellWidth
*X_UNIT
, y
*m_cellHeight
*Y_UNIT
);
126 else // Display a digit
128 dc
->SetPen(*wxBLACK_PEN
);
129 if (m_game
->IsFocussed(x
, y
))
130 dc
->SetBrush(*focusedBrush
);
131 else if (m_game
->IsSelected(x
,y
))
132 dc
->SetBrush(*wxWHITE_BRUSH
);
134 dc
->SetBrush(*yellowBrush
);
135 dc
->DrawRectangle( x
*m_cellWidth
*X_UNIT
, y
*m_cellHeight
*Y_UNIT
,
136 m_cellWidth
*X_UNIT
+1, m_cellHeight
*Y_UNIT
+1);
138 int digit_value
= m_game
->Get(x
,y
) & BG_MASK
;
143 dc
->SetTextForeground(*wxGREEN
);
147 dc
->SetTextForeground(*wxBLUE
);
150 buf
.Printf(wxT("%d"),digit_value
);
151 dc
->SetTextForeground(*wxBLACK
);
154 dc
->GetTextExtent(buf
, &chw
, &chh
);
155 dc
->SetTextBackground(*wxWHITE
);
157 x
*m_cellWidth
*X_UNIT
+ (m_cellWidth
*X_UNIT
-chw
)/2,
158 y
*m_cellHeight
*Y_UNIT
+ (m_cellHeight
*Y_UNIT
-chh
)/2);
161 dc
->SetFont(wxNullFont
);
164 msg
.Printf(wxT("%d bombs, %u marked, %d remaining cells"),
165 m_game
->GetNumBombs(), m_game
->GetNumMarkedCells(),
166 m_game
->GetNumRemainingCells() );
168 #if wxUSE_LOG && wxUSE_STATUSBAR
171 this->GetParent()->SetTitle(msg
);
175 // Refreshes the field image
176 // xc1,yc1 etc. are the (inclusive) limits of the area to be drawn,
177 // expressed in cells.
178 void BombsCanvas::RefreshField(int xc1
, int yc1
, int xc2
, int yc2
)
181 DrawField(& dc
, xc1
, yc1
, xc2
, yc2
);
185 memDC
.SelectObject(*m_bmp
);
186 DrawField(&memDC
, xc1
, yc1
, xc2
, yc2
);
187 memDC
.SelectObject(wxNullBitmap
);
191 // Called when uncovering a cell.
192 void BombsCanvas::Uncover(int x
, int y
)
194 m_game
->Unhide(x
,y
,true);
195 RefreshField(x
, y
, x
, y
);
197 const int gridWidth
= m_game
->GetWidth();
198 const int gridHeight
= m_game
->GetHeight();
200 const bool hasWon
= m_game
->GetNumRemainingCells() == 0;
201 if (m_game
->IsBomb(x
,y
) || hasWon
)
206 wxMessageBox(wxT("Nice! You found all the bombs!"),
207 wxT("wxWin Bombs"), wxOK
|wxCENTRE
);
209 else // x,y is a bomb
211 m_game
->Explode(x
, y
);
214 for(x
=0; x
<gridWidth
; x
++)
215 for(y
=0; y
<gridHeight
; y
++)
216 m_game
->Unhide(x
,y
,false);
218 RefreshField(0, 0, gridWidth
-1, gridHeight
-1);
220 else if (0 == (m_game
->Get(x
, y
) & BG_MASK
))
222 int left
= ( x
> 0 ) ? x
-1 : 0;
223 int right
= ( x
< gridWidth
- 1 )
226 int top
= ( y
> 0 ) ? y
-1 : 0;
227 int bottom
= ( y
< gridHeight
- 1 )
232 for (j
=top
; j
<=bottom
; j
++)
233 for (i
=left
; i
<=right
; i
++)
234 if ( (i
!= x
|| j
!= y
) && m_game
->IsHidden(i
, j
)
235 && !m_game
->IsMarked(i
, j
) )
242 // Called when the canvas receives a mouse event.
243 void BombsCanvas::OnMouseEvent(wxMouseEvent
& event
)
245 const int gridWidth
= m_game
->GetWidth();
246 const int gridHeight
= m_game
->GetHeight();
249 event
.GetPosition(&fx
, &fy
);
250 int x
= fx
/(m_cellWidth
*X_UNIT
);
251 int y
= fy
/(m_cellHeight
*Y_UNIT
);
252 if (x
<gridWidth
&& y
<gridHeight
)
254 if ( (event
.RightDown() || (event
.LeftDown() && event
.ShiftDown()))
255 && (m_game
->IsHidden(x
,y
)
256 || !m_game
->GetNumRemainingCells() ) )
258 // store previous and current field
259 int prevFocusX
= m_game
->m_gridFocusX
;
260 int prevFocusY
= m_game
->m_gridFocusY
;
261 m_game
->m_gridFocusX
= x
;
262 m_game
->m_gridFocusY
= y
;
263 RefreshField(prevFocusX
, prevFocusY
, prevFocusX
, prevFocusY
);
265 RefreshField(x
, y
, x
, y
);
268 else if (event
.LeftDown() && m_game
->IsHidden(x
,y
)
269 && !m_game
->IsMarked(x
,y
))
271 // store previous and current field
272 int prevGridFocusX
= m_game
->m_gridFocusX
;
273 int prevGridFocusY
= m_game
->m_gridFocusY
;
274 m_game
->m_gridFocusX
= x
;
275 m_game
->m_gridFocusY
= y
;
276 RefreshField(prevGridFocusX
, prevGridFocusY
,
277 prevGridFocusX
, prevGridFocusY
);
284 void BombsCanvas::OnChar(wxKeyEvent
& event
)
286 int keyCode
= event
.GetKeyCode();
287 int prevGridFocusX
= m_game
->m_gridFocusX
;
288 int prevGridFocusY
= m_game
->m_gridFocusY
;
290 const int gridWidth
= m_game
->GetWidth();
291 const int gridHeight
= m_game
->GetHeight();
297 m_game
->m_gridFocusX
++;
298 if (m_game
->m_gridFocusX
>= gridWidth
) m_game
->m_gridFocusX
= 0;
302 m_game
->m_gridFocusX
--;
303 if (m_game
->m_gridFocusX
<0) m_game
->m_gridFocusX
= gridWidth
-1;
307 m_game
->m_gridFocusY
++;
308 if (m_game
->m_gridFocusY
>= gridHeight
) m_game
->m_gridFocusY
= 0;
312 m_game
->m_gridFocusY
--;
313 if (m_game
->m_gridFocusY
<0) m_game
->m_gridFocusY
= gridHeight
-1;
317 if ( (prevGridFocusX
== m_game
->m_gridFocusX
)
318 && (prevGridFocusY
== m_game
->m_gridFocusY
)
319 && (m_game
->IsHidden(m_game
->m_gridFocusX
, m_game
->m_gridFocusY
)) )
321 m_game
->Mark(m_game
->m_gridFocusX
, m_game
->m_gridFocusY
);
322 if (!m_game
->IsMarked(m_game
->m_gridFocusX
, m_game
->m_gridFocusY
))
324 Uncover(m_game
->m_gridFocusX
, m_game
->m_gridFocusY
);
326 RefreshField(m_game
->m_gridFocusX
, m_game
->m_gridFocusY
,
327 m_game
->m_gridFocusX
, m_game
->m_gridFocusY
);
336 if ((prevGridFocusX
!= m_game
->m_gridFocusX
)
337 || (prevGridFocusY
!= m_game
->m_gridFocusY
))
339 // cause focused field to be visible after first key hit after launching new game
340 if( m_game
->m_gridFocusX
< 0 ) m_game
->m_gridFocusX
= 0;
341 if( m_game
->m_gridFocusY
< 0 ) m_game
->m_gridFocusY
= 0;
343 // refresh previous field and focused field
344 RefreshField(prevGridFocusX
, prevGridFocusY
,
345 prevGridFocusX
, prevGridFocusY
);
346 RefreshField(m_game
->m_gridFocusX
, m_game
->m_gridFocusY
,
347 m_game
->m_gridFocusX
, m_game
->m_gridFocusY
);