diff --git a/App.h b/App.h index 6ebdb77..fdd2a56 100644 --- a/App.h +++ b/App.h @@ -5,7 +5,7 @@ class MyApp : public wxApp { - public: +public: virtual bool OnInit() override; }; diff --git a/Controller.cpp b/Controller.cpp index e650197..2d80858 100644 --- a/Controller.cpp +++ b/Controller.cpp @@ -5,25 +5,121 @@ Controller::Controller(Drawer& drawer): drawer(drawer) {}; void Controller::resize(const wxSize& tableSize) { - drawer.setBG(tableSize); - drawer.initScreen(tableSize); + wxSize& resolution = drawer.resolution; + wxSize& gridSize = drawer.gridSize; + wxRect& tablePixelRect = drawer.tablePixelRect; resolution = tableSize; - wxLogDebug("Resize"); + int gridPoint = min(resolution.x / (gridSize.x * TILE_WIDTH), + resolution.y / (gridSize.y * TILE_HEIGHT)); + + if (gridPoint > 2) { + tablePixelRect.SetSize({gridPoint * TILE_WIDTH * gridSize.x, gridPoint * TILE_HEIGHT * gridSize.y}); + + drawer.tilePixelSize.Set(gridPoint * TILE_WIDTH, gridPoint * TILE_HEIGHT); + } + + tablePixelRect.SetPosition({(resolution.x - tablePixelRect.width) / 2, + (resolution.y - tablePixelRect.height) / 2}); + + drawer.setBG(tableSize); + drawer.initScreen(tableSize, table); } wxPoint Controller::toGrid(const wxPoint& point) { wxPoint out(-1, -1); - if (point.x >= pixelTableRect.x && - point.x <= pixelTableRect.x + pixelTableRect.width && - point.y >= pixelTableRect.y && - point.y <= pixelTableRect.y + pixelTableRect.height) + wxRect& tablePixelRect = drawer.tablePixelRect; + + if (point.x >= tablePixelRect.x && + point.x <= tablePixelRect.x + tablePixelRect.width && + point.y >= tablePixelRect.y && + point.y <= tablePixelRect.y + tablePixelRect.height) { - out.x = upDiv(point.x - pixelTableRect.x, tileSize.x); - out.y = upDiv(point.y - pixelTableRect.y, tileSize.y); + out.x = (point.x - tablePixelRect.x) / drawer.tilePixelSize.x; + out.y = (point.y - tablePixelRect.y) / drawer.tilePixelSize.y; } return out; -} \ No newline at end of file +} + +wxPoint Controller::fromGrid(const wxPoint& point) { + return { drawer.tablePixelRect.x + point.x * drawer.tilePixelSize.x, + drawer.tablePixelRect.y + point.y * drawer.tilePixelSize.y }; +} + +void Controller::loadLayout(const wxString& path) { + layout.openFile(path); + + drawer.gridSize = layout.getDimensions(); + + table = TLVec(drawer.gridSize.x, wxVector>(drawer.gridSize.y, wxVector())); + + layout.readLayout(table); +} + +TLVec* Controller::getTable() { + return &table; +} + +TLSquare* Controller::getCardByPosition(const wxPoint& point) { + int8_t topIndex = -1; + auto res = table[0][0].rend(); + + for (auto el = table[point.x][point.y].rbegin(); el != table[point.x][point.y].rend(); ++el) + if (el->second != (uint8_t)-1) { + auto d = el->first; + if (d > topIndex) { + topIndex = d; + res = el; + } + break; + } + + if (point.x > 0) + for (auto el = table[point.x-1][point.y].rbegin(); el != table[point.x-1][point.y].rend(); ++el) + if (el->second != (uint8_t)-1) { + auto d = el->first; + if (d > topIndex) { + topIndex = d; + res = el; + } + break; + } + + if (point.y > 0) + for (auto el = table[point.x][point.y-1].rbegin(); el != table[point.x][point.y-1].rend(); ++el) + if (el->second != (uint8_t)-1) { + auto d = el->first; + if (d > topIndex) { + topIndex = d; + res = el; + } + break; + } + + if (point.x > 0 && point.y > 0) + for (auto el = table[point.x-1][point.y-1].rbegin(); el != table[point.x-1][point.y-1].rend(); ++el) + if (el->second != (uint8_t)-1) { + auto d = el->first; + if (d > topIndex) { + topIndex = d; + res = el; + } + break; + } + + return &(*res); +} + +void Controller::select(TLSquare* card) { + if (selected != nullptr && selected->second == card->second && selected != card) { + selected->second = -1; + card->second = -1; + selected = nullptr; + + drawer.initScreen(drawer.tableSize, table); + } else + selected = card; +} diff --git a/Controller.h b/Controller.h index fc0d3d0..58a994a 100644 --- a/Controller.h +++ b/Controller.h @@ -4,6 +4,7 @@ #include "wxw.h" #include "Drawer.h" +#include "XmlLayout.h" class Controller { public: @@ -13,14 +14,23 @@ public: void resize(const wxSize& tableSize); + void loadLayout(const wxString& path); + wxPoint toGrid(const wxPoint& point); + wxPoint fromGrid(const wxPoint& point); + + void select(TLSquare* card); + + TLVec* getTable(); + + TLSquare* getCardByPosition(const wxPoint& point); private: Drawer& drawer; + XmlLayout layout; - wxSize tileSize; - wxSize resolution; - wxSize gridSize; - wxRect pixelTableRect; + TLVec table; + + TLSquare* selected = nullptr; }; #endif diff --git a/Drawer.cpp b/Drawer.cpp index df60765..0d14a10 100644 --- a/Drawer.cpp +++ b/Drawer.cpp @@ -4,16 +4,12 @@ static const char* tileImageNames[] = { "Back", "Blank", "Chun", "Front", "Haku", "Hatsu", "Man1", "Man2", "Man3", "Man4", "Man5", "Man6", "Man7", "Man8", "Man9", "Nan", "Pei", "Pin1", "Pin2", "Pin3", "Pin4", "Pin5", "Pin6", "Pin7", "Pin8", "Pin9", "Shaa", "Sou1", "Sou2", "Sou3", "Sou4", "Sou5", "Sou6", "Sou7", "Sou8", "Sou9", "Ton" }; Drawer::Drawer() { - for (int i = 0; i < 37; i++) { + for (int i = 0; i < 37; i++) tileImages[i].LoadFile(_("./resources/tiles/") + _(tileImageNames[i]) + _(".png"), wxBITMAP_TYPE_PNG); - tileImages[i].Rescale(60, 80); - } } void Drawer::drawTable(wxDC& dc) { - wxLogDebug("Redraw"); - - if (isScreenReady) + if (isScreenReady) dc.DrawBitmap(screenBitmap, 0, 0, false); } @@ -22,8 +18,6 @@ wxBitmap copyBitmap(const wxBitmap& old) { } void Drawer::setBG(const wxSize& tableSize) { - wxLogDebug("Recreate background"); - bgBitmap = wxBitmap(tableSize); wxMemoryDC dc; @@ -34,15 +28,43 @@ void Drawer::setBG(const wxSize& tableSize) { isBgReady = true; } -void Drawer::initScreen(const wxSize& tableSize) { - wxLogDebug("Recreate screen"); +void Drawer::initScreen(const wxSize& tableSize, const TLVec& layout) { if (isBgReady) { screenBitmap = copyBitmap(bgBitmap); + + wxMemoryDC dc; + dc.SelectObject(screenBitmap); + + int cards_set = -1; + uint8_t layer = -1; + + while (cards_set) { + layer++; + cards_set = 0; + + for (int i = 0; i < layout.size(); i++) + for (int j = 0; j < layout[i].size(); j++) { + int k = layout[i][j].size() - 1; + while (k > -1 && layout[i][j][k].second == (uint8_t)-1) + k--; + + if (k > -1) + if (layout[i][j][k].first == layer) { + drawTile(dc, layout[i][j][k].second, {tablePixelRect.x + tilePixelSize.x*i, tablePixelRect.y + tilePixelSize.y*j}); + cards_set++; + } + } + } + isScreenReady = true; } } -void Drawer::drawTile(wxDC& dc, const char index) { - dc.DrawBitmap(tileImages[3], wxPoint(10, 10)); - dc.DrawBitmap(tileImages[index], wxPoint(10, 10)); +void Drawer::drawTile (wxDC& dc, int8_t index, const wxPoint& position) { + dc.DrawRoundedRectangle(position, tilePixelSize * 2, 10); + + if (tileImages[index].GetWidth() != tilePixelSize.x * 2) + dc.DrawBitmap(tileImages[index].Scale(tilePixelSize.x * 2 - 20, tilePixelSize.y * 2 - 20), {position.x + 10, position.y + 10}); + else + dc.DrawBitmap(tileImages[index], position); } diff --git a/Drawer.h b/Drawer.h index a7cc207..49afaac 100644 --- a/Drawer.h +++ b/Drawer.h @@ -3,6 +3,11 @@ #include "wxw.h" +#include "utils.h" + +#define TILE_HEIGHT 8 +#define TILE_WIDTH 6 + class Drawer { public: Drawer(); @@ -11,12 +16,17 @@ public: wxSize tableSize; + wxSize tilePixelSize; // 600x800 + wxSize resolution; + wxSize gridSize; + wxRect tablePixelRect; + void setBG(const wxSize& tableSize); - void initScreen(const wxSize& tableSize); + void initScreen(const wxSize& tableSize, const TLVec& layout); private: void drawScreen(wxDC& dc); - void drawTile(wxDC& dc, const char index); + void drawTile(wxDC& dc, int8_t index, const wxPoint& position); wxImage tileImages[40]; diff --git a/GamePanel.cpp b/GamePanel.cpp index 5ec827f..3dcee5b 100644 --- a/GamePanel.cpp +++ b/GamePanel.cpp @@ -18,8 +18,9 @@ GamePanel::GamePanel(wxFrame* parent) : wxPanel(parent), controller(drawer), sb( Bind(wxEVT_LEFT_DOWN, &GamePanel::OnClick, this); } -void GamePanel::Start() { +void GamePanel::Start(const wxString& path) { controller.stopwatch = 0; + controller.loadLayout(path); timer->Start(1000, wxTIMER_CONTINUOUS); sb->SetStatusText(LTimeToStr(controller.stopwatch)); @@ -37,6 +38,14 @@ void GamePanel::OnTimer(wxTimerEvent& _) { } void GamePanel::OnClick(wxMouseEvent& _) { - wxPoint res = controller.toGrid(wxGetMousePosition()); - sb->PushStatusText(itowxS(res.x) + _("x") + itowxS(res.y)); -} \ No newline at end of file + wxPoint res = controller.toGrid(ScreenToClient(wxGetMousePosition())); + + if (res.x > -1) { + auto card = controller.getCardByPosition(res); + if (card != nullptr) { + controller.select(card); + } + } + + Refresh(); +} diff --git a/GamePanel.h b/GamePanel.h index 787582e..af2f63c 100644 --- a/GamePanel.h +++ b/GamePanel.h @@ -12,7 +12,7 @@ class GamePanel : public wxPanel { public: GamePanel(wxFrame* parent); - void Start(); + void Start(const wxString& path); private: Drawer drawer; @@ -22,8 +22,8 @@ private: void OnTimer(wxTimerEvent& _); void OnClick(wxMouseEvent& _); - wxStatusBar* sb; - wxTimer* timer; + wxStatusBar* sb = nullptr; + wxTimer* timer = nullptr; }; #endif diff --git a/MainFrame.cpp b/MainFrame.cpp index 4e5318c..795fe99 100644 --- a/MainFrame.cpp +++ b/MainFrame.cpp @@ -5,24 +5,21 @@ #include "AboutDlg.h" MainFrame::MainFrame() - : wxFrame(nullptr, wxID_ANY, _("Маджонг (пасьянс)")), + : wxFrame(nullptr, wxID_ANY, _("Маджонг (пасьянс)"), wxDefaultPosition, wxSize(800, 600)), dataDirPath(wxStandardPaths::Get().GetUserDataDir()) { - InitMenu(); - BindMenu(); + initMenu(); + bindMenu(); CreateStatusBar(); panel = new GamePanel(this); panel->SetFocus(); - panel->Start(); + + openLayout(); } -MainFrame::~MainFrame() { - delete panel; -} - -void MainFrame::InitMenu() { +void MainFrame::initMenu() { wxMenu *menuGame = new wxMenu; menuGame->Append(IDM_New_Game, _("Начать сначала")); menuGame->Append(IDM_Open, _("Открыть карту")); @@ -41,12 +38,14 @@ void MainFrame::InitMenu() { SetMenuBar(menuBar); } -void MainFrame::BindMenu() { +void MainFrame::bindMenu() { Bind(wxEVT_MENU, [this](wxCommandEvent& _) -> void { Close(); }, IDM_Exit); - Bind(wxEVT_MENU, &MainFrame::OnOpen, this, IDM_Open); + Bind(wxEVT_MENU, [this](wxCommandEvent& _) -> void { + openLayout(); + }, IDM_Open); Bind(wxEVT_MENU, [this](wxCommandEvent& _) -> void { (new HelpDlg(this, -1))->Show(); @@ -61,15 +60,20 @@ void MainFrame::BindMenu() { }, IDM_Rules); Bind(wxEVT_MENU, [this](wxCommandEvent& _) -> void { - panel->Start(); + if (layoutPath.IsEmpty()) + openLayout(); + else + panel->Start(layoutPath); }, IDM_New_Game); } -void MainFrame::OnOpen(wxCommandEvent& _) { +void MainFrame::openLayout() { wxFileDialog openFileDlg(this, "Открыть карту", dataDirPath + wxFileName::GetPathSeparator() + _("layouts"), "Turtle.smlf", "Файлы Mahjong карт (*.smlf)|*.smlf", wxFD_OPEN | wxFD_FILE_MUST_EXIST); if (openFileDlg.ShowModal() == wxID_CANCEL) return; - GetStatusBar()->PushStatusText(openFileDlg.GetPath()); -} \ No newline at end of file + layoutPath = openFileDlg.GetPath(); + + panel->Start(layoutPath); +} diff --git a/MainFrame.h b/MainFrame.h index df9ea5c..e8dc20b 100644 --- a/MainFrame.h +++ b/MainFrame.h @@ -13,17 +13,17 @@ class MainFrame : public wxFrame { public: MainFrame(); - ~MainFrame(); private: - void InitMenu(); - void BindMenu(); + void initMenu(); + void bindMenu(); - void OnOpen(wxCommandEvent& _); + void openLayout(); GamePanel *panel; const wxString dataDirPath; + wxString layoutPath; }; enum