X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7874bf5430d47317bebf5c68cd7d4a2d964dee95..6bd1764f2716e8d0814edd6374b20960bba23579:/demos/bombs/bombs1.cpp diff --git a/demos/bombs/bombs1.cpp b/demos/bombs/bombs1.cpp index 173bce2383..19549cb882 100644 --- a/demos/bombs/bombs1.cpp +++ b/demos/bombs/bombs1.cpp @@ -2,7 +2,7 @@ // Name: bombs1.cpp // Purpose: Bombs game // Author: P. Foggia 1996 -// Modified by: +// Modified by: Wlodzimierz Skiba (ABX) since 2003 // Created: 1996 // RCS-ID: $Id$ // Copyright: (c) 1996 P. Foggia @@ -14,211 +14,337 @@ * class BombsCanvas */ -#ifdef __GNUG__ -#pragma implementation -#endif - #include "wx/wxprec.h" +#ifdef __BORLANDC__ +# pragma hdrstop +#endif + #ifndef WX_PRECOMP - #include "wx/wx.h" +# include "wx/wx.h" #endif //precompiled headers #include "bombs.h" -/*-------- BombCanvasClass::DrawField(dc, xc1, yc1, xc2, yc2) -------*/ -/* Draws the field on the device context dc */ -/* xc1,yc1 etc. are the (inclusive) limits of the area to be drawn, */ -/* expressed in cells. */ -/*---------------------------------------------------------------------*/ -void BombsCanvasClass::DrawField(wxDC *dc, int xc1, int yc1, int xc2, int yc2) -{ int x,y,xmax,ymax; - char buf[2]; - long chw, chh; - - wxColour *wxBlack = wxTheColourDatabase->FindColour("BLACK"); - wxColour *wxWhite = wxTheColourDatabase->FindColour("WHITE"); - wxColour *wxRed = wxTheColourDatabase->FindColour("RED"); - wxColour *wxBlue = wxTheColourDatabase->FindColour("BLUE"); - wxColour *wxGrey = wxTheColourDatabase->FindColour("LIGHT GREY"); - wxColour *wxGreen = wxTheColourDatabase->FindColour("GREEN"); - - wxPen *blackPen = wxThePenList->FindOrCreatePen(*wxBlack, 1, wxSOLID); - wxPen *redPen = wxThePenList->FindOrCreatePen(*wxRed, 1, wxSOLID); - wxPen *bluePen = wxThePenList->FindOrCreatePen(*wxBlue, 1, wxSOLID); - wxBrush *whiteBrush = wxTheBrushList->FindOrCreateBrush(*wxWhite, wxSOLID); - wxBrush *greyBrush = wxTheBrushList->FindOrCreateBrush(*wxGrey, wxSOLID); - wxBrush *redBrush = wxTheBrushList->FindOrCreateBrush(*wxRed, wxSOLID); - - xmax=field_width*x_cell*X_UNIT; - ymax=field_height*y_cell*Y_UNIT; - - - dc->SetPen(* blackPen); - for(x=xc1; x<=xc2; x++) - dc->DrawLine(x*x_cell*X_UNIT, 0, x*x_cell*X_UNIT, ymax); - for(y=xc1; y<=yc2; y++) - dc->DrawLine(0, y*y_cell*Y_UNIT, xmax, y*y_cell*Y_UNIT); - - - wxFont font= BOMBS_FONT; - dc->SetFont(font); - - buf[1]='\0'; - for(x=xc1; x<=xc2; x++) - for(y=yc1; y<=yc2; y++) - { if (wxGetApp().Game.IsMarked(x,y)) - { dc->SetPen(* blackPen); - dc->SetBrush(* greyBrush); - dc->DrawRectangle( x*x_cell*X_UNIT, y*y_cell*Y_UNIT, - x_cell*X_UNIT+1, y_cell*Y_UNIT+1); - *buf='M'; - if (!wxGetApp().Game.IsHidden(x,y) && wxGetApp().Game.IsBomb(x,y)) - dc->SetTextForeground(*wxBlue); - else - dc->SetTextForeground(*wxRed); - dc->SetTextBackground(*wxGrey); - dc->GetTextExtent(buf, &chw, &chh); - dc->DrawText( buf, - x*x_cell*X_UNIT + (x_cell*X_UNIT-chw)/2, - y*y_cell*Y_UNIT + (y_cell*Y_UNIT-chh)/2 - ); - if (!wxGetApp().Game.IsHidden(x,y) && wxGetApp().Game.IsBomb(x,y)) - { dc->SetPen(*redPen); - dc->DrawLine(x*x_cell*X_UNIT, y*y_cell*Y_UNIT, - (x+1)*x_cell*X_UNIT, (y+1)*y_cell*Y_UNIT); - dc->DrawLine(x*x_cell*X_UNIT, (y+1)*y_cell*Y_UNIT, - (x+1)*x_cell*X_UNIT, y*y_cell*Y_UNIT); - } - } - else if (wxGetApp().Game.IsHidden(x,y)) - { dc->SetPen(*blackPen); - dc->SetBrush(*greyBrush); - dc->DrawRectangle( x*x_cell*X_UNIT, y*y_cell*Y_UNIT, - x_cell*X_UNIT+1, y_cell*Y_UNIT+1); - } - else if (wxGetApp().Game.IsBomb(x,y)) - { dc->SetPen(* blackPen); - dc->SetBrush(* redBrush); - dc->DrawRectangle( x*x_cell*X_UNIT, y*y_cell*Y_UNIT, - x_cell*X_UNIT+1, y_cell*Y_UNIT+1); - *buf='B'; - dc->SetTextForeground(* wxBlack); - dc->SetTextBackground(* wxRed); - dc->GetTextExtent(buf, &chw, &chh); - dc->DrawText( buf, - x*x_cell*X_UNIT + (x_cell*X_UNIT-chw)/2, - y*y_cell*Y_UNIT + (y_cell*Y_UNIT-chh)/2 - ); - if (wxGetApp().Game.IsExploded(x,y)) - { dc->SetPen(* bluePen); - dc->DrawLine(x*x_cell*X_UNIT, y*y_cell*Y_UNIT, - (x+1)*x_cell*X_UNIT, (y+1)*y_cell*Y_UNIT); - dc->DrawLine(x*x_cell*X_UNIT, (y+1)*y_cell*Y_UNIT, - (x+1)*x_cell*X_UNIT, y*y_cell*Y_UNIT); - } - } - else // Display a digit - { dc->SetPen(* blackPen); - dc->SetBrush(* whiteBrush); - dc->DrawRectangle( x*x_cell*X_UNIT, y*y_cell*Y_UNIT, - x_cell*X_UNIT+1, y_cell*Y_UNIT+1); - *buf = (wxGetApp().Game.Get(x,y) & BG_MASK) + '0'; +// Draws the field on the device context dc +// xc1,yc1 etc. are the (inclusive) limits of the area to be drawn, +// expressed in cells. +void BombsCanvas::DrawField(wxDC *dc, int xc1, int yc1, int xc2, int yc2) +{ + wxString buf; + wxCoord chw, chh; + + wxColour wxYellow = wxTheColourDatabase->Find(wxT("YELLOW")); + wxColour wxFocused = wxTheColourDatabase->Find(wxT("GREY")); + + wxPen *bluePen = wxThePenList->FindOrCreatePen(*wxBLUE, 1, wxSOLID); + + wxBrush *focusedBrush = wxTheBrushList->FindOrCreateBrush(wxFocused, wxSOLID); + wxBrush *yellowBrush = wxTheBrushList->FindOrCreateBrush(wxYellow, wxSOLID); + + dc->SetPen(*wxBLACK_PEN); + + int x, y; + int xMax = this->GetGridSizeInPixels().GetWidth(); + int yMax = this->GetGridSizeInPixels().GetHeight(); + for(x=xc1; x<=xc2; x++) + dc->DrawLine(x*m_cellWidth*X_UNIT, 0, x*m_cellWidth*X_UNIT, yMax); + for(y=xc1; y<=yc2; y++) + dc->DrawLine(0, y*m_cellHeight*Y_UNIT, xMax, y*m_cellHeight*Y_UNIT); + + + wxFont font= BOMBS_FONT; + dc->SetFont(font); + + for(x=xc1; x<=xc2; x++) + for(y=yc1; y<=yc2; y++) + { + if (m_game->IsMarked(x,y)) + { + dc->SetPen(*wxBLACK_PEN); + + if (m_game->IsFocussed(x, y)) + dc->SetBrush(*focusedBrush); + else + dc->SetBrush(*wxLIGHT_GREY_BRUSH); + + dc->DrawRectangle( x*m_cellWidth*X_UNIT, y*m_cellHeight*Y_UNIT, + m_cellWidth*X_UNIT+1, m_cellHeight*Y_UNIT+1); + buf = wxT("M"); + if (!m_game->IsHidden(x,y) && m_game->IsBomb(x,y)) + dc->SetTextForeground(*wxBLUE); + else + dc->SetTextForeground(*wxRED); + + dc->SetTextBackground(*wxLIGHT_GREY); + dc->GetTextExtent(buf, &chw, &chh); + dc->DrawText( buf, + x*m_cellWidth*X_UNIT + (m_cellWidth*X_UNIT-chw)/2, + y*m_cellHeight*Y_UNIT + (m_cellHeight*Y_UNIT-chh)/2 ); + + if (!m_game->IsHidden(x,y) && m_game->IsBomb(x,y)) + { + dc->SetPen(*wxRED_PEN); + dc->DrawLine(x*m_cellWidth*X_UNIT, y*m_cellHeight*Y_UNIT, + (x+1)*m_cellWidth*X_UNIT, (y+1)*m_cellHeight*Y_UNIT); + dc->DrawLine(x*m_cellWidth*X_UNIT, (y+1)*m_cellHeight*Y_UNIT, + (x+1)*m_cellWidth*X_UNIT, y*m_cellHeight*Y_UNIT); + } + } + else if (m_game->IsHidden(x,y)) + { + dc->SetPen(*wxBLACK_PEN); + if (m_game->IsFocussed(x, y)) + dc->SetBrush(*focusedBrush); + else + dc->SetBrush(*wxLIGHT_GREY_BRUSH); + + dc->DrawRectangle( x*m_cellWidth*X_UNIT, y*m_cellHeight*Y_UNIT, + m_cellWidth*X_UNIT+1, m_cellHeight*Y_UNIT+1); + } + else if (m_game->IsBomb(x,y)) + { + dc->SetPen(*wxBLACK_PEN); + dc->SetBrush(*wxRED_BRUSH); + dc->DrawRectangle( x*m_cellWidth*X_UNIT, y*m_cellHeight*Y_UNIT, + m_cellWidth*X_UNIT+1, m_cellHeight*Y_UNIT+1); + buf = wxT("B"); + dc->SetTextForeground(*wxBLACK); + dc->SetTextBackground(*wxRED); + dc->GetTextExtent(buf, &chw, &chh); + dc->DrawText( buf, + x*m_cellWidth*X_UNIT + (m_cellWidth*X_UNIT-chw)/2, + y*m_cellHeight*Y_UNIT + (m_cellHeight*Y_UNIT-chh)/2); + if (m_game->IsExploded(x,y)) + { + dc->SetPen(*bluePen); + dc->DrawLine(x*m_cellWidth*X_UNIT, y*m_cellHeight*Y_UNIT, + (x+1)*m_cellWidth*X_UNIT, (y+1)*m_cellHeight*Y_UNIT); + dc->DrawLine(x*m_cellWidth*X_UNIT, (y+1)*m_cellHeight*Y_UNIT, + (x+1)*m_cellWidth*X_UNIT, y*m_cellHeight*Y_UNIT); + } + } + else // Display a digit + { + dc->SetPen(*wxBLACK_PEN); + if (m_game->IsFocussed(x, y)) + dc->SetBrush(*focusedBrush); + else if (m_game->IsSelected(x,y)) + dc->SetBrush(*wxWHITE_BRUSH); + else + dc->SetBrush(*yellowBrush); + dc->DrawRectangle( x*m_cellWidth*X_UNIT, y*m_cellHeight*Y_UNIT, + m_cellWidth*X_UNIT+1, m_cellHeight*Y_UNIT+1); + + int digit_value = m_game->Get(x,y) & BG_MASK; + switch(digit_value) + { + case 0: + buf = wxT("0"); + dc->SetTextForeground(*wxGREEN); + break; + case 1: + buf = wxT("1"); + dc->SetTextForeground(*wxBLUE); + break; + default: + buf.Printf(wxT("%d"),digit_value); + dc->SetTextForeground(*wxBLACK); + break; + } dc->GetTextExtent(buf, &chw, &chh); - switch(*buf) - { case '0': dc->SetTextForeground(* wxGreen); break; - case '1': dc->SetTextForeground(* wxBlue); break; - default: dc->SetTextForeground(* wxBlack); break; - } - dc->SetTextBackground(* wxWhite); + dc->SetTextBackground(*wxWHITE); dc->DrawText( buf, - x*x_cell*X_UNIT + (x_cell*X_UNIT-chw)/2, - y*y_cell*Y_UNIT + (y_cell*Y_UNIT-chh)/2 - ); - } - } - dc->SetFont(wxNullFont); - - if (wxGetApp().BombsFrame) - { char buf[80]; - sprintf(buf, "%d bombs %d remaining cells", - wxGetApp().Game.GetBombs(), wxGetApp().Game.GetRemainingCells()); - wxGetApp().BombsFrame->SetStatusText(buf, 0); + x*m_cellWidth*X_UNIT + (m_cellWidth*X_UNIT-chw)/2, + y*m_cellHeight*Y_UNIT + (m_cellHeight*Y_UNIT-chh)/2); + } } + dc->SetFont(wxNullFont); + + wxString msg; + msg.Printf(wxT("%d bombs, %u marked, %d remaining cells"), + m_game->GetNumBombs(), m_game->GetNumMarkedCells(), + m_game->GetNumRemainingCells() ); + +#if wxUSE_LOG && wxUSE_STATUSBAR + wxLogStatus(msg); +#else + this->GetParent()->SetTitle(msg); +#endif } -/*-------- BombCanvasClass::Refresh(xc1, yc1, xc2, yc2) -------------*/ -/* Refreshes the field image */ -/* xc1,yc1 etc. are the (inclusive) limits of the area to be drawn, */ -/* expressed in cells. */ -/*---------------------------------------------------------------------*/ -void BombsCanvasClass::Refresh(int xc1, int yc1, int xc2, int yc2) - { +// Refreshes the field image +// xc1,yc1 etc. are the (inclusive) limits of the area to be drawn, +// expressed in cells. +void BombsCanvas::RefreshField(int xc1, int yc1, int xc2, int yc2) +{ wxClientDC dc(this); DrawField(& dc, xc1, yc1, xc2, yc2); - if (bmp) - { wxMemoryDC memDC; - memDC.SelectObject(* bmp); + if (m_bmp) + { + wxMemoryDC memDC; + memDC.SelectObject(*m_bmp); DrawField(&memDC, xc1, yc1, xc2, yc2); memDC.SelectObject(wxNullBitmap); - } - } + } +} // Called when uncovering a cell. -void BombsCanvasClass::Uncover(int x, int y) +void BombsCanvas::Uncover(int x, int y) { - wxGetApp().Game.Unhide(x,y); - Refresh(x, y, x, y); - if (wxGetApp().Game.IsBomb(x,y) || wxGetApp().Game.GetRemainingCells()==0) - { wxBell(); - if (!wxGetApp().Game.IsBomb(x,y)) - { wxMessageBox("Nice! You found all the bombs!", "wxWin Bombs", - wxOK|wxCENTRE, wxGetApp().BombsFrame); - } - else // x,y is a bomb - { wxGetApp().Game.Explode(x, y); - } - for(x=0; xUnhide(x,y,true); + RefreshField(x, y, x, y); + + const int gridWidth = m_game->GetWidth(); + const int gridHeight = m_game->GetHeight(); + + const bool hasWon = m_game->GetNumRemainingCells() == 0; + if (m_game->IsBomb(x,y) || hasWon) + { + wxBell(); + if (hasWon) + { + wxMessageBox(wxT("Nice! You found all the bombs!"), + wxT("wxWin Bombs"), wxOK|wxCENTRE); + } + else // x,y is a bomb + { + m_game->Explode(x, y); + } + + for(x=0; xUnhide(x,y,false); + + RefreshField(0, 0, gridWidth-1, gridHeight-1); } - else if (!wxGetApp().Game.Get(x, y)) - { int left = ( x > 0 ) ? x-1 : 0; - int right = ( x < wxGetApp().Game.GetWidth() - 1 )? - x+1 : wxGetApp().Game.GetWidth() - 1; - int top = ( y > 0 ) ? y-1 : 0; - int bottom = ( y < wxGetApp().Game.GetHeight() - 1 )? - y+1 : wxGetApp().Game.GetHeight() - 1; - int i,j; - for (j = top; j <= bottom; j++) - for (i=left; i <= right; i++) - if ((i != x || j != y) && wxGetApp().Game.IsHidden(i,j) - && !wxGetApp().Game.IsMarked(i,j)) - Uncover(i,j); + else if (0 == (m_game->Get(x, y) & BG_MASK)) + { + int left = ( x > 0 ) ? x-1 : 0; + int right = ( x < gridWidth - 1 ) + ? x+1 + : gridWidth - 1; + int top = ( y > 0 ) ? y-1 : 0; + int bottom = ( y < gridHeight - 1 ) + ? y+1 + : gridHeight - 1; + + int i, j; + for (j=top; j<=bottom; j++) + for (i=left; i<=right; i++) + if ( (i != x || j != y) && m_game->IsHidden(i, j) + && !m_game->IsMarked(i, j) ) + { + Uncover(i, j); + } } } // Called when the canvas receives a mouse event. -void BombsCanvasClass::OnEvent(wxMouseEvent& event) +void BombsCanvas::OnMouseEvent(wxMouseEvent& event) { - wxCoord fx, fy; - event.GetPosition(&fx, &fy); - int x = fx/(x_cell*X_UNIT); - int y = fy/(y_cell*Y_UNIT); - if (xGetWidth(); + const int gridHeight = m_game->GetHeight(); + + wxCoord fx, fy; + event.GetPosition(&fx, &fy); + int x = fx/(m_cellWidth*X_UNIT); + int y = fy/(m_cellHeight*Y_UNIT); + if (xIsHidden(x,y) + || !m_game->GetNumRemainingCells() ) ) + { + // store previous and current field + int prevFocusX = m_game->m_gridFocusX; + int prevFocusY = m_game->m_gridFocusY; + m_game->m_gridFocusX = x; + m_game->m_gridFocusY = y; + RefreshField(prevFocusX, prevFocusY, prevFocusX, prevFocusY); + m_game->Mark(x, y); + RefreshField(x, y, x, y); + return; } - else if (event.LeftDown() && wxGetApp().Game.IsHidden(x,y) - && !wxGetApp().Game.IsMarked(x,y)) - { Uncover(x,y); - return; + else if (event.LeftDown() && m_game->IsHidden(x,y) + && !m_game->IsMarked(x,y)) + { + // store previous and current field + int prevGridFocusX = m_game->m_gridFocusX; + int prevGridFocusY = m_game->m_gridFocusY; + m_game->m_gridFocusX = x; + m_game->m_gridFocusY = y; + RefreshField(prevGridFocusX, prevGridFocusY, + prevGridFocusX, prevGridFocusY); + Uncover(x, y); + return; } } } +void BombsCanvas::OnChar(wxKeyEvent& event) +{ + int keyCode = event.GetKeyCode(); + int prevGridFocusX = m_game->m_gridFocusX; + int prevGridFocusY = m_game->m_gridFocusY; + + const int gridWidth = m_game->GetWidth(); + const int gridHeight = m_game->GetHeight(); + + switch(keyCode) + { + + case WXK_RIGHT: + m_game->m_gridFocusX++; + if (m_game->m_gridFocusX >= gridWidth) m_game->m_gridFocusX = 0; + break; + + case WXK_LEFT: + m_game->m_gridFocusX--; + if (m_game->m_gridFocusX<0) m_game->m_gridFocusX = gridWidth-1; + break; + + case WXK_DOWN: + m_game->m_gridFocusY++; + if (m_game->m_gridFocusY >= gridHeight) m_game->m_gridFocusY = 0; + break; + + case WXK_UP: + m_game->m_gridFocusY--; + if (m_game->m_gridFocusY<0) m_game->m_gridFocusY = gridHeight-1; + break; + + case WXK_RETURN: + if ( (prevGridFocusX == m_game->m_gridFocusX) + && (prevGridFocusY == m_game->m_gridFocusY) + && (m_game->IsHidden(m_game->m_gridFocusX, m_game->m_gridFocusY)) ) + { + m_game->Mark(m_game->m_gridFocusX, m_game->m_gridFocusY); + if (!m_game->IsMarked(m_game->m_gridFocusX, m_game->m_gridFocusY)) + { + Uncover(m_game->m_gridFocusX, m_game->m_gridFocusY); + } + RefreshField(m_game->m_gridFocusX, m_game->m_gridFocusY, + m_game->m_gridFocusX, m_game->m_gridFocusY); + } + break; + + default: + event.Skip(); + + } + + if ((prevGridFocusX != m_game->m_gridFocusX) + || (prevGridFocusY != m_game->m_gridFocusY)) + { + // cause focused field to be visible after first key hit after launching new game + if( m_game->m_gridFocusX < 0 ) m_game->m_gridFocusX = 0; + if( m_game->m_gridFocusY < 0 ) m_game->m_gridFocusY = 0; + + // refresh previous field and focused field + RefreshField(prevGridFocusX, prevGridFocusY, + prevGridFocusX, prevGridFocusY); + RefreshField(m_game->m_gridFocusX, m_game->m_gridFocusY, + m_game->m_gridFocusX, m_game->m_gridFocusY); + } +}