| 1 | /////////////////////////////////////////////////////////////////////////////// |
| 2 | // Name: bombs1.cpp |
| 3 | // Purpose: Bombs game |
| 4 | // Author: P. Foggia 1996 |
| 5 | // Modified by: |
| 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__ |
| 18 | #pragma implementation |
| 19 | #endif |
| 20 | |
| 21 | #include "wx/wxprec.h" |
| 22 | |
| 23 | #ifndef WX_PRECOMP |
| 24 | #include "wx/wx.h" |
| 25 | #endif //precompiled headers |
| 26 | |
| 27 | #include "bombs.h" |
| 28 | |
| 29 | /*-------- BombCanvasClass::DrawField(dc, xc1, yc1, xc2, yc2) -------*/ |
| 30 | /* Draws the field on the device context dc */ |
| 31 | /* xc1,yc1 etc. are the (inclusive) limits of the area to be drawn, */ |
| 32 | /* expressed in cells. */ |
| 33 | /*---------------------------------------------------------------------*/ |
| 34 | void BombsCanvasClass::DrawField(wxDC *dc, int xc1, int yc1, int xc2, int yc2) |
| 35 | { int x,y,xmax,ymax; |
| 36 | char buf[2]; |
| 37 | long chw, chh; |
| 38 | |
| 39 | wxColour *wxBlack = wxTheColourDatabase->FindColour("BLACK"); |
| 40 | wxColour *wxWhite = wxTheColourDatabase->FindColour("WHITE"); |
| 41 | wxColour *wxRed = wxTheColourDatabase->FindColour("RED"); |
| 42 | wxColour *wxBlue = wxTheColourDatabase->FindColour("BLUE"); |
| 43 | wxColour *wxGrey = wxTheColourDatabase->FindColour("LIGHT GREY"); |
| 44 | wxColour *wxGreen = wxTheColourDatabase->FindColour("GREEN"); |
| 45 | |
| 46 | wxPen *blackPen = wxThePenList->FindOrCreatePen(*wxBlack, 1, wxSOLID); |
| 47 | wxPen *redPen = wxThePenList->FindOrCreatePen(*wxRed, 1, wxSOLID); |
| 48 | wxPen *bluePen = wxThePenList->FindOrCreatePen(*wxBlue, 1, wxSOLID); |
| 49 | wxBrush *whiteBrush = wxTheBrushList->FindOrCreateBrush(*wxWhite, wxSOLID); |
| 50 | wxBrush *greyBrush = wxTheBrushList->FindOrCreateBrush(*wxGrey, wxSOLID); |
| 51 | wxBrush *redBrush = wxTheBrushList->FindOrCreateBrush(*wxRed, wxSOLID); |
| 52 | |
| 53 | xmax=field_width*x_cell*X_UNIT; |
| 54 | ymax=field_height*y_cell*Y_UNIT; |
| 55 | |
| 56 | |
| 57 | dc->SetPen(* blackPen); |
| 58 | for(x=xc1; x<=xc2; x++) |
| 59 | dc->DrawLine(x*x_cell*X_UNIT, 0, x*x_cell*X_UNIT, ymax); |
| 60 | for(y=xc1; y<=yc2; y++) |
| 61 | dc->DrawLine(0, y*y_cell*Y_UNIT, xmax, y*y_cell*Y_UNIT); |
| 62 | |
| 63 | |
| 64 | wxFont font= BOMBS_FONT; |
| 65 | dc->SetFont(font); |
| 66 | |
| 67 | buf[1]='\0'; |
| 68 | for(x=xc1; x<=xc2; x++) |
| 69 | for(y=yc1; y<=yc2; y++) |
| 70 | { if (wxGetApp().Game.IsMarked(x,y)) |
| 71 | { dc->SetPen(* blackPen); |
| 72 | dc->SetBrush(* greyBrush); |
| 73 | dc->DrawRectangle( x*x_cell*X_UNIT, y*y_cell*Y_UNIT, |
| 74 | x_cell*X_UNIT+1, y_cell*Y_UNIT+1); |
| 75 | *buf='M'; |
| 76 | if (!wxGetApp().Game.IsHidden(x,y) && wxGetApp().Game.IsBomb(x,y)) |
| 77 | dc->SetTextForeground(*wxBlue); |
| 78 | else |
| 79 | dc->SetTextForeground(*wxRed); |
| 80 | dc->SetTextBackground(*wxGrey); |
| 81 | dc->GetTextExtent(buf, &chw, &chh); |
| 82 | dc->DrawText( buf, |
| 83 | x*x_cell*X_UNIT + (x_cell*X_UNIT-chw)/2, |
| 84 | y*y_cell*Y_UNIT + (y_cell*Y_UNIT-chh)/2 |
| 85 | ); |
| 86 | if (!wxGetApp().Game.IsHidden(x,y) && wxGetApp().Game.IsBomb(x,y)) |
| 87 | { dc->SetPen(*redPen); |
| 88 | dc->DrawLine(x*x_cell*X_UNIT, y*y_cell*Y_UNIT, |
| 89 | (x+1)*x_cell*X_UNIT, (y+1)*y_cell*Y_UNIT); |
| 90 | dc->DrawLine(x*x_cell*X_UNIT, (y+1)*y_cell*Y_UNIT, |
| 91 | (x+1)*x_cell*X_UNIT, y*y_cell*Y_UNIT); |
| 92 | } |
| 93 | } |
| 94 | else if (wxGetApp().Game.IsHidden(x,y)) |
| 95 | { dc->SetPen(*blackPen); |
| 96 | dc->SetBrush(*greyBrush); |
| 97 | dc->DrawRectangle( x*x_cell*X_UNIT, y*y_cell*Y_UNIT, |
| 98 | x_cell*X_UNIT+1, y_cell*Y_UNIT+1); |
| 99 | } |
| 100 | else if (wxGetApp().Game.IsBomb(x,y)) |
| 101 | { dc->SetPen(* blackPen); |
| 102 | dc->SetBrush(* redBrush); |
| 103 | dc->DrawRectangle( x*x_cell*X_UNIT, y*y_cell*Y_UNIT, |
| 104 | x_cell*X_UNIT+1, y_cell*Y_UNIT+1); |
| 105 | *buf='B'; |
| 106 | dc->SetTextForeground(* wxBlack); |
| 107 | dc->SetTextBackground(* wxRed); |
| 108 | dc->GetTextExtent(buf, &chw, &chh); |
| 109 | dc->DrawText( buf, |
| 110 | x*x_cell*X_UNIT + (x_cell*X_UNIT-chw)/2, |
| 111 | y*y_cell*Y_UNIT + (y_cell*Y_UNIT-chh)/2 |
| 112 | ); |
| 113 | if (wxGetApp().Game.IsExploded(x,y)) |
| 114 | { dc->SetPen(* bluePen); |
| 115 | dc->DrawLine(x*x_cell*X_UNIT, y*y_cell*Y_UNIT, |
| 116 | (x+1)*x_cell*X_UNIT, (y+1)*y_cell*Y_UNIT); |
| 117 | dc->DrawLine(x*x_cell*X_UNIT, (y+1)*y_cell*Y_UNIT, |
| 118 | (x+1)*x_cell*X_UNIT, y*y_cell*Y_UNIT); |
| 119 | } |
| 120 | } |
| 121 | else // Display a digit |
| 122 | { dc->SetPen(* blackPen); |
| 123 | dc->SetBrush(* whiteBrush); |
| 124 | dc->DrawRectangle( x*x_cell*X_UNIT, y*y_cell*Y_UNIT, |
| 125 | x_cell*X_UNIT+1, y_cell*Y_UNIT+1); |
| 126 | *buf = (wxGetApp().Game.Get(x,y) & BG_MASK) + '0'; |
| 127 | dc->GetTextExtent(buf, &chw, &chh); |
| 128 | switch(*buf) |
| 129 | { case '0': dc->SetTextForeground(* wxGreen); break; |
| 130 | case '1': dc->SetTextForeground(* wxBlue); break; |
| 131 | default: dc->SetTextForeground(* wxBlack); break; |
| 132 | } |
| 133 | dc->SetTextBackground(* wxWhite); |
| 134 | dc->DrawText( buf, |
| 135 | x*x_cell*X_UNIT + (x_cell*X_UNIT-chw)/2, |
| 136 | y*y_cell*Y_UNIT + (y_cell*Y_UNIT-chh)/2 |
| 137 | ); |
| 138 | } |
| 139 | } |
| 140 | dc->SetFont(wxNullFont); |
| 141 | |
| 142 | if (wxGetApp().BombsFrame) |
| 143 | { char buf[80]; |
| 144 | sprintf(buf, "%d bombs %d remaining cells", |
| 145 | wxGetApp().Game.GetBombs(), wxGetApp().Game.GetRemainingCells()); |
| 146 | wxGetApp().BombsFrame->SetStatusText(buf, 0); |
| 147 | } |
| 148 | } |
| 149 | |
| 150 | /*-------- BombCanvasClass::Refresh(xc1, yc1, xc2, yc2) -------------*/ |
| 151 | /* Refreshes the field image */ |
| 152 | /* xc1,yc1 etc. are the (inclusive) limits of the area to be drawn, */ |
| 153 | /* expressed in cells. */ |
| 154 | /*---------------------------------------------------------------------*/ |
| 155 | void BombsCanvasClass::Refresh(int xc1, int yc1, int xc2, int yc2) |
| 156 | { |
| 157 | wxClientDC dc(this); |
| 158 | DrawField(& dc, xc1, yc1, xc2, yc2); |
| 159 | if (bmp) |
| 160 | { wxMemoryDC memDC; |
| 161 | memDC.SelectObject(* bmp); |
| 162 | DrawField(&memDC, xc1, yc1, xc2, yc2); |
| 163 | memDC.SelectObject(wxNullBitmap); |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | // Called when uncovering a cell. |
| 168 | void BombsCanvasClass::Uncover(int x, int y) |
| 169 | { |
| 170 | wxGetApp().Game.Unhide(x,y); |
| 171 | Refresh(x, y, x, y); |
| 172 | if (wxGetApp().Game.IsBomb(x,y) || wxGetApp().Game.GetRemainingCells()==0) |
| 173 | { wxBell(); |
| 174 | if (!wxGetApp().Game.IsBomb(x,y)) |
| 175 | { wxMessageBox("Nice! You found all the bombs!", "wxWin Bombs", |
| 176 | wxOK|wxCENTRE, wxGetApp().BombsFrame); |
| 177 | } |
| 178 | else // x,y is a bomb |
| 179 | { wxGetApp().Game.Explode(x, y); |
| 180 | } |
| 181 | for(x=0; x<field_width; x++) |
| 182 | for(y=0; y<field_height; y++) |
| 183 | wxGetApp().Game.Unhide(x,y); |
| 184 | Refresh(0, 0, field_width-1, field_height-1); |
| 185 | } |
| 186 | else if (!wxGetApp().Game.Get(x, y)) |
| 187 | { int left = ( x > 0 ) ? x-1 : 0; |
| 188 | int right = ( x < wxGetApp().Game.GetWidth() - 1 )? |
| 189 | x+1 : wxGetApp().Game.GetWidth() - 1; |
| 190 | int top = ( y > 0 ) ? y-1 : 0; |
| 191 | int bottom = ( y < wxGetApp().Game.GetHeight() - 1 )? |
| 192 | y+1 : wxGetApp().Game.GetHeight() - 1; |
| 193 | int i,j; |
| 194 | for (j = top; j <= bottom; j++) |
| 195 | for (i=left; i <= right; i++) |
| 196 | if ((i != x || j != y) && wxGetApp().Game.IsHidden(i,j) |
| 197 | && !wxGetApp().Game.IsMarked(i,j)) |
| 198 | Uncover(i,j); |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | // Called when the canvas receives a mouse event. |
| 203 | void BombsCanvasClass::OnEvent(wxMouseEvent& event) |
| 204 | { |
| 205 | wxCoord fx, fy; |
| 206 | event.GetPosition(&fx, &fy); |
| 207 | int x = fx/(x_cell*X_UNIT); |
| 208 | int y = fy/(y_cell*Y_UNIT); |
| 209 | if (x<field_width && y<field_height) |
| 210 | { if ( (event.RightDown() || (event.LeftDown() && event.ShiftDown())) |
| 211 | && (wxGetApp().Game.IsHidden(x,y) |
| 212 | || wxGetApp().Game.GetRemainingCells()==0)) |
| 213 | { wxGetApp().Game.Mark(x,y); |
| 214 | Refresh(x, y, x, y); |
| 215 | return; |
| 216 | } |
| 217 | else if (event.LeftDown() && wxGetApp().Game.IsHidden(x,y) |
| 218 | && !wxGetApp().Game.IsMarked(x,y)) |
| 219 | { Uncover(x,y); |
| 220 | return; |
| 221 | } |
| 222 | } |
| 223 | } |
| 224 | |