Compare commits

..

No commits in common. "d633f9751dd1309758b81de8e762028d072faa04" and "7b436c15c4c5c21d3cf44273fb502131b0baa082" have entirely different histories.

10 changed files with 276 additions and 426 deletions

View File

@ -1,15 +1,38 @@
#include "Controller.h"
Controller::Controller(Drawer& drawer) : drawer(drawer){};
Controller::Controller(Drawer& drawer): drawer(drawer) {};
void Controller::resize(const wxSize& tableSize) {
wxSize& resolution = drawer.resolution;
Dimensions& gridSize = drawer.gridSize;
wxRect& tablePixelRect = drawer.tablePixelRect;
resolution = tableSize;
if (stopwatch >= 0) {
int gridPoint = mmin(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(table);
}
void Controller::loadLayout(const wxString& path) {
layout.openFile(path);
gridSize = layout.getDimensions();
drawer.gridSize = layout.getDimensions();
table = TLVec(
gridSize.z,
vector<vector<CardT>>(gridSize.x, vector<CardT>(gridSize.y, EMPTY)));
table = TLVec(drawer.gridSize.z, vector<vector<CardT>>(drawer.gridSize.x, vector<CardT>(drawer.gridSize.y, EMPTY)));
layout.readLayout(table);
@ -37,6 +60,8 @@ void Controller::fill(bool solveable) {
void Controller::fillSolveableTable() {
time_t start_time = time(NULL);
auto& gridSize = drawer.gridSize;
std::list<ThreePoint> positions;
int overall = gridSize.z * gridSize.x * gridSize.y;
@ -66,13 +91,10 @@ void Controller::fillSolveableTable() {
emplace_rand(id, positions, past_pos, past_ptr);
}
wxLogInfo(
wxString::Format("Filling took %i seconds", start_time - time(NULL)));
wxLogInfo(wxString::Format("Filling took %i seconds", start_time - time(NULL)));
}
int Controller::emplace_rand(int id, std::list<ThreePoint> positions,
int past_pos,
std::list<ThreePoint>::iterator past_ptr) {
int Controller::emplace_rand(int id, std::list<ThreePoint> positions, int past_pos, std::list<ThreePoint>::iterator past_ptr) {
int d = rand() % positions.size() - past_pos;
if (d > 0)
@ -97,9 +119,9 @@ int Controller::emplace_rand(int id, std::list<ThreePoint> positions,
}
void Controller::free_table() {
for (int z = 0; z < gridSize.z; z++)
for (int x = 0; x < gridSize.x; x++)
for (int y = 0; y < gridSize.y; y++) {
for (int z = 0; z < drawer.gridSize.z; z++)
for (int x = 0; x < drawer.gridSize.x; x++)
for (int y = 0; y < drawer.gridSize.y; y++) {
CardT id = table[z][x][y];
if (id >= 0) {
@ -119,9 +141,9 @@ void Controller::fillRandom() {
auto not_end = remaining;
for (int z = 0; z < gridSize.z && not_end; z++)
for (int x = 0; x < gridSize.x && not_end; x++)
for (int y = 0; y < gridSize.y && not_end; y++)
for (int z = 0; z < drawer.gridSize.z && not_end; z++)
for (int x = 0; x < drawer.gridSize.x && not_end; x++)
for (int y = 0; y < drawer.gridSize.y && not_end; y++)
if (table[z][x][y] == FREE) {
table[z][x][y] = genRandId();
not_end--;
@ -145,7 +167,7 @@ CardT Controller::genRandId() {
/**
* It also changes point to top right coordinate of card
*/
*/
CardT* Controller::getCardByPosition(ThreePoint& point) {
int8_t topIndex = -1;
CardT* res = nullptr;
@ -163,10 +185,10 @@ CardT* Controller::getCardByPosition(ThreePoint& point) {
if (point.x > 0)
for (int z = table.size() - 1; z >= 0; z--)
if (table[z][point.x - 1][point.y] >= 0) {
if (table[z][point.x-1][point.y] >= 0) {
if (z > topIndex) {
topIndex = z;
res = &table[z][point.x - 1][point.y];
res = &table[z][point.x-1][point.y];
realPos.x = point.x - 1;
realPos.y = point.y;
@ -176,10 +198,10 @@ CardT* Controller::getCardByPosition(ThreePoint& point) {
if (point.y > 0)
for (int z = table.size() - 1; z >= 0; z--)
if (table[z][point.x][point.y - 1] >= 0) {
if (table[z][point.x][point.y-1] >= 0) {
if (z > topIndex) {
topIndex = z;
res = &table[z][point.x][point.y - 1];
res = &table[z][point.x][point.y-1];
realPos.x = point.x;
realPos.y = point.y - 1;
@ -189,10 +211,10 @@ CardT* Controller::getCardByPosition(ThreePoint& point) {
if (point.x > 0 && point.y > 0)
for (int z = table.size() - 1; z >= 0; z--)
if (table[z][point.x - 1][point.y - 1] >= 0) {
if (table[z][point.x-1][point.y-1] >= 0) {
if (z > topIndex) {
topIndex = z;
res = &table[z][point.x - 1][point.y - 1];
res = &table[z][point.x-1][point.y-1];
realPos.x = point.x - 1;
realPos.y = point.y - 1;
@ -207,50 +229,45 @@ CardT* Controller::getCardByPosition(ThreePoint& point) {
return res;
}
bool Controller::available(const ThreePoint& point) const {
bool Controller::available(const ThreePoint& point) {
return upFree(point) && sideFree(point);
}
bool Controller::upFree(const ThreePoint& point) const {
bool Controller::upFree(const ThreePoint& point) {
if (point.z == table.size() - 1)
return true;
return !((table[point.z + 1][point.x][point.y] >= 0) ||
return !(
(table[point.z + 1][point.x][point.y] >= 0) ||
(point.x > 0 && table[point.z + 1][point.x - 1][point.y] >= 0) ||
(point.y > 0 && table[point.z + 1][point.x][point.y - 1] >= 0) ||
(point.x > 0 && point.y > 0 &&
table[point.z + 1][point.x - 1][point.y - 1] >= 0) ||
(point.x < table[point.z].size() - 1 &&
table[point.z + 1][point.x + 1][point.y] >= 0) ||
(point.y < table[point.z][point.x].size() - 1 &&
table[point.z + 1][point.x][point.y + 1] >= 0) ||
(point.x < table[point.z].size() - 1 &&
point.y < table[point.z][point.x].size() - 1 &&
table[point.z + 1][point.x + 1][point.y + 1] >= 0) ||
(point.x > 0 && point.y < table[point.z][point.x].size() - 1 &&
table[point.z + 1][point.x - 1][point.y + 1] >= 0) ||
(point.x < table[point.z].size() - 1 && point.y > 0 &&
table[point.z + 1][point.x + 1][point.y - 1] >= 0));
(point.x > 0 && point.y > 0 && table[point.z + 1][point.x - 1][point.y - 1] >= 0) ||
(point.x < table[point.z].size() - 1 && table[point.z + 1][point.x + 1][point.y] >= 0) ||
(point.y < table[point.z][point.x].size() - 1 && table[point.z + 1][point.x][point.y + 1] >= 0) ||
(point.x < table[point.z].size() - 1 && point.y < table[point.z][point.x].size() - 1 && table[point.z + 1][point.x + 1][point.y + 1] >= 0) ||
(point.x > 0 && point.y < table[point.z][point.x].size() - 1 && table[point.z + 1][point.x - 1][point.y + 1] >= 0) ||
(point.x < table[point.z].size() - 1 && point.y > 0 && table[point.z + 1][point.x + 1][point.y - 1] >= 0)
);
}
bool Controller::sideFree(const ThreePoint& point) const {
bool Controller::sideFree(const ThreePoint& point) {
bool lfree = true;
bool rfree = true;
if (point.x > 1)
lfree =
!((point.y > 0 && table[point.z][point.x - 2][point.y - 1] >= 0) ||
(table[point.z][point.x - 2][point.y] >= 0) ||
(point.y < table[point.z][point.x].size() - 1 &&
table[point.z][point.x - 2][point.y + 1] >= 0));
lfree = !(
(point.y > 0 && table[point.z][point.x-2][point.y-1] >= 0) ||
(table[point.z][point.x-2][point.y] >= 0) ||
(point.y < table[point.z][point.x].size() - 1 && table[point.z][point.x-2][point.y+1] >= 0)
);
if (point.x < table[point.z].size() - 2)
rfree =
!((point.y > 0 && table[point.z][point.x + 2][point.y - 1] >= 0) ||
(table[point.z][point.x + 2][point.y] >= 0) ||
(point.y < table[point.z][point.x].size() - 1 &&
table[point.z][point.x + 2][point.y + 1] >= 0));
rfree = !(
(point.y > 0 && table[point.z][point.x+2][point.y-1] >= 0) ||
(table[point.z][point.x+2][point.y] >= 0) ||
(point.y < table[point.z][point.x].size() - 1 && table[point.z][point.x+2][point.y+1] >= 0)
);
return lfree || rfree;
}
@ -264,10 +281,8 @@ void Controller::handleClick(const wxPoint& point) {
auto card = getCardByPosition(pos);
if (pos.z >= 0 && available(pos)) {
if (selected != nullptr && sameValues(*card, *selected) &&
selected != card) {
steps.push({CardEntry{drawer.marked, *selected},
CardEntry{pos, *card}});
if (selected != nullptr && sameValues(*card, *selected) && selected != card) {
steps.push({CardEntry{drawer.marked, *selected}, CardEntry{pos, *card}});
*selected = MATCHED;
*card = MATCHED;
@ -281,13 +296,14 @@ void Controller::handleClick(const wxPoint& point) {
selected = card;
drawer.marked = pos;
}
drawer.initScreen(table);
}
}
}
bool Controller::sameValues(CardT a, CardT b) const {
if (a == b)
return true;
bool Controller::sameValues(CardT a, CardT b) {
if (a == b) return true;
else if (a >= 38 && b >= 38)
return true;
else if (a >= 34 && a <= 37 && b >= 34 && b <= 37)
@ -307,7 +323,3 @@ void Controller::undo() {
steps.pop();
}
}
bool Controller::gameStarted() const {
return stopwatch > 0;
}

View File

@ -16,6 +16,8 @@ public:
int stopwatch = -1;
void resize(const wxSize& tableSize);
void loadLayout(const wxString& path);
void handleClick(const wxPoint& point);
@ -29,11 +31,6 @@ public:
uint8_t remaining;
void undo();
bool gameStarted() const;
Dimensions gridSize;
private:
Drawer& drawer;
XmlLayout layout;
@ -43,22 +40,21 @@ private:
CardT* selected = nullptr;
void fillSolveableTable();
int emplace_rand(int id, std::list<ThreePoint> positions, int past_pos,
std::list<ThreePoint>::iterator past_ptr);
void fillRandom();
int emplace_rand(int id, std::list<ThreePoint> positions, int past_pos, std::list<ThreePoint>::iterator past_ptr);
CardT genRandId();
CardT* getCardByPosition(ThreePoint& point);
bool available(const ThreePoint& point) const;
bool upFree(const ThreePoint& point) const;
bool sideFree(const ThreePoint& point) const;
bool available(const ThreePoint& point);
bool upFree(const ThreePoint& point);
bool sideFree(const ThreePoint& point);
bool sameValues(CardT a, CardT b) const;
bool sameValues(CardT a, CardT b);
std::array<uint8_t, TILE_IMAGES_N> cardsCounter;
std::array<uint8_t, TILE_IMAGES_N>cardsCounter;
std::stack<std::array<CardEntry, 2>> steps;
};

View File

@ -1,60 +1,66 @@
#include "Drawer.h"
static const char* tileImageNames[] = {
// clang-format off
"Pin1", "Pin2", "Pin3", "Pin4", "Pin5", "Pin6", "Pin7", "Pin8", "Pin9",
"Sou1", "Sou2", "Sou3", "Sou4", "Sou5", "Sou6", "Sou7", "Sou8", "Sou9",
"Man1", "Man2", "Man3", "Man4", "Man5", "Man6", "Man7", "Man8", "Man9",
"Chun", "Haku", "Hatsu",
"Nan", "Pei", "Shaa", "Ton",
"Flower1", "Flower2", "Flower3", "Flower4",
"Season1", "Season2", "Season3", "Season4"
// clang-format on
};
static const char* tileImageNames[] = { "Pin1", "Pin2", "Pin3", "Pin4", "Pin5", "Pin6", "Pin7", "Pin8", "Pin9", "Sou1", "Sou2", "Sou3", "Sou4", "Sou5", "Sou6", "Sou7", "Sou8", "Sou9", "Man1", "Man2", "Man3", "Man4", "Man5", "Man6", "Man7", "Man8", "Man9", "Chun", "Haku", "Hatsu", "Nan", "Pei", "Shaa", "Ton", "Flower1", "Flower2", "Flower3", "Flower4", "Season1", "Season2", "Season3", "Season4" };
static const wxColor lGreen{0x07, 0x55, 0x2b};
static const wxColor dGreen{0x01, 0x2d, 0x16};
Drawer::Drawer() : marked{-1, -1, -1} {
Drawer::Drawer(): marked{-1, -1, -1} {
for (int i = 0; i < TILE_IMAGES_N; i++) {
bool succeed = tileImages[i].LoadFile(
_("./resources/tiles/") + _(tileImageNames[i]) + _(".png"),
wxBITMAP_TYPE_PNG);
if (!succeed)
wxLogDebug(_("failed to load tile ./resources/tiles/") +
_(tileImageNames[i]) + _(".png with index") +
wxString::Format("%i", i));
if (!tileImages[i].LoadFile(_("./resources/tiles/") + _(tileImageNames[i]) + _(".png"), wxBITMAP_TYPE_PNG))
wxLogDebug(_("./resources/tiles/") + _(tileImageNames[i]) + _(".png ") + wxString::Format(wxT("%i"), i));
}
}
void Drawer::drawTable(wxDC& dc) {
dc.DrawBitmap(bgBitmap, 0, 0, false);
if (boardBitmap.IsOk()) {
wxLogDebug("Drawing board");
dc.DrawBitmap(boardBitmap, tablePixelRect.GetPosition(), true);
}
if (isScreenReady)
dc.DrawBitmap(screenBitmap, 0, 0, false);
}
void Drawer::composeBG() {
bgBitmap = wxBitmap(resolution);
wxBitmap copyBitmap(const wxBitmap& old) {
return old.GetSubBitmap(wxRect(0, 0, old.GetWidth(), old.GetHeight()));
}
wxLogDebug(
wxString::Format("Rebuild bg %i %i", resolution.x, resolution.y));
void Drawer::setBG(const wxSize& tableSize) {
bgBitmap = wxBitmap(tableSize);
wxMemoryDC dc;
dc.SelectObject(bgBitmap);
dc.GradientFillConcentric(wxRect(wxPoint(0, 0), resolution), lGreen,
dGreen);
dc.GradientFillConcentric(wxRect(wxPoint(0, 0), tableSize), wxColor(7, 85, 45), wxColor(1, 45, 22));
isBgReady = true;
}
void Drawer::composeBoard(const TLVec& layout, const Dimensions& gridSize) {
boardBitmap = wxBitmap(tablePixelRect.GetSize());
wxPoint Drawer::toGrid(const wxPoint& point) {
wxPoint out(-1, -1);
wxLogDebug(_("Rebuild board"));
if (point.x >= tablePixelRect.x &&
point.x <= tablePixelRect.x + tablePixelRect.width &&
point.y >= tablePixelRect.y &&
point.y <= tablePixelRect.y + tablePixelRect.height)
{
out.x = (point.x - tablePixelRect.x) / tilePixelSize.x;
out.y = (point.y - tablePixelRect.y) / tilePixelSize.y;
}
return out;
}
wxPoint Drawer::fromGrid(int x, int y) {
return { tablePixelRect.x + x * tilePixelSize.x,
tablePixelRect.y + y * tilePixelSize.y };
}
wxPoint Drawer::fromGrid(const wxPoint& point) {
return fromGrid(point.x, point.y);
}
void Drawer::initScreen(const TLVec& layout) {
if (isBgReady) {
screenBitmap = copyBitmap(bgBitmap);
wxLogDebug(_("Reinit"));
wxMemoryDC dc;
dc.SelectObject(boardBitmap);
dc.SelectObject(screenBitmap);
for (int z = 0; z < gridSize.z; z++)
for (int x = 0; x < gridSize.x; x++)
@ -64,125 +70,35 @@ void Drawer::composeBoard(const TLVec& layout, const Dimensions& gridSize) {
drawTile(dc, c, fromGrid(x, y), z);
}
wxMask* mask = new wxMask(boardBitmap, wxColor(0x00, 0x00, 0x00));
boardBitmap.SetMask(mask);
isScreenReady = true;
}
}
void Drawer::drawTile(wxDC& dc, int8_t index, const wxPoint& position,
uint8_t zIndex) const {
void Drawer::drawTile(wxDC& dc, int8_t index, const wxPoint& position, uint8_t zIndex) {
wxBrush _bgColor = dc.GetBrush();
wxBrush front = wxColor(0xff, 0xff, 0xff);
wxBrush back = wxColor(0xc8, 0xc8, 0xc8);
wxBrush front = wxColor(255, 255, 255);
wxBrush back = wxColor(200, 200, 200);
if (position == fromGrid({marked.x, marked.y}) && marked.z == zIndex) {
front = wxColor(0xc8, 0xff, 0xc8);
back = wxColor(0xbe, 0xdc, 0xbe);
front = wxColor(200, 255, 200);
back = wxColor(190, 220, 190);
}
dc.SetBrush(back);
dc.DrawRoundedRectangle(position.x + (tilePixelSize.GetWidth() / 10 + 3) -
(tilePixelSize.GetWidth() / 10 + 3) * zIndex,
position.y + (tilePixelSize.GetHeight() / 10 + 3) -
(tilePixelSize.GetHeight() / 10 + 3) * zIndex,
tilePixelSize.GetWidth() * 2,
tilePixelSize.GetHeight() * 2, 10);
dc.DrawRoundedRectangle(position.x + (tilePixelSize.GetWidth()/10 + 3) - (tilePixelSize.GetWidth()/10 + 3)*zIndex, position.y + (tilePixelSize.GetHeight()/10 + 3) - (tilePixelSize.GetHeight()/10 + 3)*zIndex, tilePixelSize.GetWidth() * 2, tilePixelSize.GetHeight() * 2, 10);
dc.SetBrush(front);
dc.DrawRoundedRectangle(
position.x - (tilePixelSize.GetWidth() / 10 + 3) * zIndex,
position.y - (tilePixelSize.GetHeight() / 10 + 3) * zIndex,
tilePixelSize.GetWidth() * 2, tilePixelSize.GetHeight() * 2, 10);
dc.DrawRoundedRectangle(position.x - (tilePixelSize.GetWidth()/10 + 3)*zIndex, position.y - (tilePixelSize.GetHeight()/10 + 3)*zIndex, tilePixelSize.GetWidth() * 2, tilePixelSize.GetHeight() * 2, 10);
dc.SetBrush(_bgColor);
if (tileImages[index].IsOk()) {
wxPoint pos;
pos.x = position.x + 10 - (tilePixelSize.GetWidth() / 10 + 3) * zIndex;
pos.y = position.y + 10 - (tilePixelSize.GetHeight() / 10 + 3) * zIndex;
if (tileImages[index].GetWidth() != tilePixelSize.x * 2)
dc.DrawBitmap(tileImages[index].Scale(tilePixelSize.x * 2 - 20,
tilePixelSize.y * 2 - 20),
pos);
dc.DrawBitmap(tileImages[index].Scale(tilePixelSize.x * 2 - 20, tilePixelSize.y * 2 - 20), {position.x + 10 - (tilePixelSize.GetWidth()/10 + 3)*zIndex, position.y + 10 - (tilePixelSize.GetHeight()/10 + 3)*zIndex});
else
dc.DrawBitmap(tileImages[index], pos);
dc.DrawBitmap(tileImages[index], {position.x + 10 - (tilePixelSize.GetWidth()/10 + 3)*zIndex, position.y + 10 - (tilePixelSize.GetHeight()/10 + 3)*zIndex});
}
}
void Drawer::resizeBg(const wxSize& resolution) {
if (this->resolution != resolution) {
this->resolution = resolution;
composeBG();
}
}
/**
* Resizes tile and whole board bitmap size to the resolution, set in this
* instance
*/
bool Drawer::resizeBoard(const TLVec& layout, const Dimensions& gridSize) {
bool res = false;
const int gridPoint = mmin(resolution.x / (gridSize.x * TILE_WIDTH),
resolution.y / (gridSize.y * TILE_HEIGHT));
wxLogDebug(wxString::Format("Resize board: %i", gridPoint));
if (gridPoint >= MIN_GRID_POINT) {
if (gridPoint != prevGridPoint) {
tablePixelRect.SetSize({gridPoint * TILE_WIDTH * gridSize.x,
gridPoint * TILE_HEIGHT * gridSize.y});
tilePixelSize.Set(gridPoint * TILE_WIDTH, gridPoint * TILE_HEIGHT);
}
tablePixelRect.SetPosition(
{(resolution.x - tablePixelRect.width) / 2,
(resolution.y - tablePixelRect.height) / 2});
if (gridPoint != prevGridPoint) {
composeBoard(layout, gridSize);
res = true;
}
prevGridPoint = gridPoint;
}
return res;
}
wxPoint Drawer::toGrid(const wxPoint& point) const {
wxPoint out(-1, -1);
if (point.x >= tablePixelRect.x &&
point.x <= tablePixelRect.x + tablePixelRect.width &&
point.y >= tablePixelRect.y &&
point.y <= tablePixelRect.y + tablePixelRect.height) {
out.x = (point.x - tablePixelRect.x) / tilePixelSize.x;
out.y = (point.y - tablePixelRect.y) / tilePixelSize.y;
}
return out;
}
wxPoint Drawer::fromGrid(int x, int y) const {
return {x * tilePixelSize.x, y * tilePixelSize.y};
}
wxPoint Drawer::fromGrid(const wxPoint& point) const {
return fromGrid(point.x, point.y);
}
wxSize Drawer::composeMinSize(const wxSize& gridSize) {
wxSize ms;
ms.SetWidth(MIN_GRID_POINT * TILE_WIDTH * gridSize.x);
ms.SetHeight(MIN_GRID_POINT * TILE_HEIGHT * gridSize.y);
wxLogDebug(wxString::Format("MinSize %i %i", ms.x, ms.y));
return ms;
}

View File

@ -10,44 +10,39 @@
#define TILE_IMAGES_N 42
#define MIN_GRID_POINT 3
class Drawer {
public:
Drawer();
void drawTable(wxDC& dc);
void composeBG();
void composeBoard(const TLVec& layout, const Dimensions& gridSize);
void resizeBg(const wxSize& tableSize);
bool resizeBoard(const TLVec& layout, const Dimensions& gridSize);
wxPoint toGrid(const wxPoint& point) const;
wxPoint fromGrid(int x, int y) const;
wxPoint fromGrid(const wxPoint& point) const;
wxSize composeMinSize(const wxSize& gridSize);
wxSize tableSize;
wxSize tilePixelSize; // кратно 3x4, по умолчанию 600x800
wxSize tilePixelSize; // кратно 600x800
wxSize resolution;
Dimensions gridSize;
wxRect tablePixelRect;
void setBG(const wxSize& tableSize);
void initScreen(const TLVec& layout);
wxPoint toGrid(const wxPoint& point);
wxPoint fromGrid(int x, int y);
wxPoint fromGrid(const wxPoint& point);
ThreePoint marked;
private:
void drawTile(wxDC& dc, int8_t index, const wxPoint& position,
uint8_t zIndex) const;
void drawScreen(wxDC& dc);
void drawTile(wxDC& dc, int8_t index, const wxPoint& position, uint8_t zIndex);
wxImage tileImages[TILE_IMAGES_N];
wxBitmap bgBitmap;
wxBitmap boardBitmap;
wxBitmap screenBitmap;
int prevGridPoint;
bool isBgReady = false;
bool isScreenReady = false;
};
#endif

View File

@ -4,96 +4,65 @@
#include "utils.h"
// clang-format off
wxBEGIN_EVENT_TABLE(GamePanel, wxPanel)
EVT_PAINT(GamePanel::OnPaint)
EVT_SIZE(GamePanel::OnResize)
EVT_TIMER(TIMER_ID, GamePanel::OnTimer)
EVT_LEFT_DOWN(GamePanel::OnClick)
wxEND_EVENT_TABLE();
// clang-format on
GamePanel::GamePanel(wxFrame* parent)
: wxPanel(parent), controller(drawer),
sb(((wxFrame*)this->GetParent())->GetStatusBar()), timer(this, TIMER_ID) {
GamePanel::GamePanel(wxFrame* parent) : wxPanel(parent), controller(drawer) {
SetBackgroundStyle(wxBG_STYLE_PAINT);
Bind(wxEVT_PAINT, &GamePanel::OnPaint, this);
Bind(wxEVT_SIZE, [this](wxSizeEvent& evt) -> void {
this->controller.resize(evt.GetSize());
});
timer = new wxTimer(this, 1);
Bind(wxEVT_TIMER, &GamePanel::OnTimer, this, timer->GetId());
Bind(wxEVT_LEFT_DOWN, &GamePanel::OnClick, this);
}
void GamePanel::Start(const wxString& path, bool solveable,
std::function<void(const wxSize& size)> setMinSize) {
wxLogDebug(_("Started game"));
void GamePanel::Start(const wxString& path, bool solveable) {
controller.stopwatch = 0;
controller.loadLayout(path);
controller.fill(solveable);
setMinSize(drawer.composeMinSize(controller.gridSize));
timer.Start(1000, wxTIMER_CONTINUOUS);
timer->Start(1000, wxTIMER_CONTINUOUS);
if (sb == nullptr)
sb = ((wxFrame*)this->GetParent())->GetStatusBar();
sb->SetStatusText(LTimeToStr(controller.stopwatch), 0);
sb->SetStatusText(PRemaining(controller.remaining), 1);
bool redrawn =
drawer.resizeBoard(controller.getTable(), controller.gridSize);
if (!redrawn)
drawer.composeBoard(controller.getTable(), controller.gridSize);
Refresh();
}
void GamePanel::undo() {
controller.undo();
drawer.composeBoard(controller.getTable(), controller.gridSize);
Refresh();
}
void GamePanel::reshuffle(bool solveable) {
controller.free_table();
controller.fill(solveable);
drawer.composeBoard(controller.getTable(), controller.gridSize);
Refresh();
drawer.initScreen(controller.getTable());
}
void GamePanel::OnPaint(wxPaintEvent& _) {
wxAutoBufferedPaintDC dc(this);
wxLogDebug(_("OnPaint"));
drawer.drawTable(dc);
}
void GamePanel::OnResize(wxSizeEvent& _) {
const wxSize& resolution = GetClientSize();
wxLogDebug(wxString::Format("OnResize %i %i", resolution.x, resolution.y));
if (isPositive(resolution)) {
drawer.resizeBg(resolution);
if (controller.gameStarted())
drawer.resizeBoard(controller.getTable(), controller.gridSize);
}
Refresh();
}
void GamePanel::OnTimer(wxTimerEvent& _) {
controller.stopwatch += 1;
sb->SetStatusText(LTimeToStr(controller.stopwatch), 0);
}
void GamePanel::OnClick(wxMouseEvent& _) {
if (controller.gameStarted()) {
controller.handleClick(ScreenToClient(wxGetMousePosition()));
sb->SetStatusText(PRemaining(controller.remaining), 1);
drawer.composeBoard(controller.getTable(), controller.gridSize);
Refresh();
}
void GamePanel::undo() {
controller.undo();
drawer.initScreen(controller.getTable());
Refresh();
}
void GamePanel::reshuffle(bool solveable) {
controller.free_table();
controller.fill(solveable);
drawer.initScreen(controller.getTable());
Refresh();
}
}

View File

@ -5,15 +5,14 @@
#include <wx/stopwatch.h>
#include "Controller.h"
#include "Drawer.h"
#include "Controller.h"
class GamePanel : public wxPanel {
public:
GamePanel(wxFrame* parent);
void Start(const wxString& path, bool solveable,
std::function<void(const wxSize& size)> setMinSize);
void Start(const wxString& path, bool solveable);
void undo();
void reshuffle(bool solveable);
@ -23,16 +22,11 @@ private:
Controller controller;
void OnPaint(wxPaintEvent& _);
void OnResize(wxSizeEvent& _);
void OnTimer(wxTimerEvent& _);
void OnClick(wxMouseEvent& _);
wxDECLARE_EVENT_TABLE();
wxStatusBar* sb = nullptr;
wxTimer timer;
wxTimer* timer = nullptr;
};
#define TIMER_ID 1
#endif

View File

@ -1,53 +1,46 @@
#include "MainFrame.h"
#include "AboutDlg.h"
#include "HelpDlg.h"
#include "RulesDlg.h"
#include "AboutDlg.h"
#include "resources/icon.xpm"
MainFrame::MainFrame()
: wxFrame(nullptr, wxID_ANY, _("Маджонг (пасьянс)"), wxDefaultPosition,
wxSize(800, 600)),
dataDirPath(wxStandardPaths::Get().GetUserDataDir()) {
: wxFrame(nullptr, wxID_ANY, _("Маджонг (пасьянс)"), wxDefaultPosition, wxSize(800, 600)),
dataDirPath(wxStandardPaths::Get().GetUserDataDir())
{
SetIcon(logo_icon);
initMenu();
bindMenu();
Bind(wxEVT_SHOW, [this](wxShowEvent& _) -> void {
if (openLayout())
panel->Start(layoutPath, solveable,
[this](const wxSize& size) -> void {
this->SetMinClientSize(size);
});
});
CreateStatusBar(2);
panel = new GamePanel(this);
panel->SetFocus();
openLayout();
}
void MainFrame::initMenu() {
wxMenu* menuGame = new wxMenu;
wxMenu *menuGame = new wxMenu;
menuGame->Append(IDM_New_Game, _("Начать сначала"));
menuGame->Append(IDM_Open, _("Открыть карту"));
menuGame->AppendCheckItem(IDM_Solveable, _("Генерировать решаемую карту"));
menuGame->Enable(IDM_Solveable,
false); // TODO: finish solveable table generation
menuGame->Enable(IDM_Solveable, false); // TODO: finish solveable table generation
menuGame->AppendSeparator();
menuGame->Append(IDM_Undo, _("Отменить ход"));
menuGame->Append(IDM_Reshuffle, _("Перемешать поле"));
menuGame->AppendSeparator();
menuGame->Append(IDM_Exit, _("Выход"));
wxMenu* menuHelp = new wxMenu;
wxMenu *menuHelp = new wxMenu;
menuHelp->Append(IDM_Help, _("Инструкция"));
menuHelp->Append(IDM_Rules, _("Правила игры"));
menuHelp->Append(IDM_About, _("О программе"));
wxMenuBar* menuBar = new wxMenuBar;
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append(menuGame, _("Игра"));
menuBar->Append(menuHelp, _("Помощь"));
@ -55,77 +48,55 @@ void MainFrame::initMenu() {
}
void MainFrame::bindMenu() {
Bind(
wxEVT_MENU, [this](wxCommandEvent& _) -> void { Close(); }, IDM_Exit);
Bind(wxEVT_MENU, [this](wxCommandEvent& _) -> void {
Close();
}, IDM_Exit);
Bind(
wxEVT_MENU,
[this](wxCommandEvent& _) -> void {
if (openLayout())
panel->Start(layoutPath, solveable,
[this](const wxSize& size) -> void {
this->SetMinClientSize(size);
});
},
IDM_Open);
Bind(wxEVT_MENU, [this](wxCommandEvent& _) -> void {
openLayout();
}, IDM_Open);
Bind(
wxEVT_MENU,
[this](wxCommandEvent& _) -> void { (new HelpDlg(this, -1))->Show(); },
IDM_Help);
Bind(wxEVT_MENU, [this](wxCommandEvent& _) -> void {
(new HelpDlg(this, -1))->Show();
}, IDM_Help);
Bind(
wxEVT_MENU,
[this](wxCommandEvent& _) -> void { (new AboutDlg(this, -1))->Show(); },
IDM_About);
Bind(wxEVT_MENU, [this](wxCommandEvent& _) -> void {
(new AboutDlg(this, -1))->Show();
}, IDM_About);
Bind(
wxEVT_MENU,
[this](wxCommandEvent& _) -> void { (new RulesDlg(this, -1))->Show(); },
IDM_Rules);
Bind(wxEVT_MENU, [this](wxCommandEvent& _) -> void {
(new RulesDlg(this, -1))->Show();
}, IDM_Rules);
Bind(
wxEVT_MENU,
[this](wxCommandEvent& _) -> void {
if (!layoutPath.IsEmpty() || openLayout()) {
panel->Start(layoutPath, solveable,
[this](const wxSize& size) -> void {
this->SetMinClientSize(size);
});
}
},
IDM_New_Game);
Bind(wxEVT_MENU, [this](wxCommandEvent& _) -> void {
if (layoutPath.IsEmpty())
openLayout();
else
panel->Start(layoutPath, solveable);
Bind(
wxEVT_MENU,
[this](wxCommandEvent& evt) -> void { solveable = evt.IsChecked(); },
IDM_Solveable);
Refresh();
}, IDM_New_Game);
Bind(
wxEVT_MENU, [this](wxCommandEvent& _) -> void { panel->undo(); },
IDM_Undo);
Bind(wxEVT_MENU, [this](wxCommandEvent& _) -> void {
solveable = _.IsChecked();
}, IDM_Solveable);
Bind(
wxEVT_MENU,
[this](wxCommandEvent& _) -> void { panel->reshuffle(solveable); },
IDM_Reshuffle);
Bind(wxEVT_MENU, [this](wxCommandEvent& _) -> void {
panel->undo();
}, IDM_Undo);
Bind(wxEVT_MENU, [this](wxCommandEvent& _) -> void {
panel->reshuffle(solveable);
}, IDM_Reshuffle);
}
/**
* Shows a file opening dialog asking for .smlf file if succed, sets its path to
* layoutPath
* @return true if user have chosen a file, false if cancelled
*/
bool MainFrame::openLayout() {
wxFileDialog openFileDlg(
this, _("Открыть карту"),
dataDirPath + wxFileName::GetPathSeparator() + _("layouts"),
_("Turtle.smlf"), _("Файлы Mahjong карт (*.smlf)|*.smlf"),
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
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 false;
return;
layoutPath = openFileDlg.GetPath();
return true;
panel->Start(layoutPath, solveable);
}

View File

@ -18,14 +18,14 @@ private:
void initMenu();
void bindMenu();
GamePanel *panel;
void openLayout();
bool openLayout();
GamePanel *panel;
const wxString dataDirPath;
wxString layoutPath;
bool solveable = false; // determites wether to generate solveable or completely random map
bool solveable = false;
};
enum

View File

@ -1,8 +1,7 @@
#include "utils.h"
wxString LTimeToStr(int time) {
return wxString::Format(_("%d:%02d:%02d"), time / 3600, (time / 60) % 60,
time % 60);
return wxString::Format(_("%d:%02d:%02d"), time / 3600, (time / 60) % 60, time % 60);
}
int upDiv(int a, int b) {
@ -14,9 +13,5 @@ wxString itowxS(int a) {
}
wxString PRemaining(uint8_t remaining) {
return wxString::Format("%i%%", remaining * 100 / 144);
}
bool isPositive(const wxSize& size) {
return size.x > 0 && size.y > 0;
return wxString::Format("%i%%", remaining*100 / 144);
}

16
utils.h
View File

@ -19,15 +19,15 @@ using CardT = int16_t;
class Dimensions : public wxSize {
public:
Dimensions(int _z, int _x, int _y) : wxSize(_x, _y), z(_z){};
Dimensions() : wxSize(), z(0){};
Dimensions(int _z, int _x, int _y): wxSize(_x, _y), z(_z) {};
Dimensions(): wxSize(), z(0) {};
int z;
};
class ThreePoint {
public:
ThreePoint(int _z, int _x, int _y) : x(_x), y(_y), z(_z){};
ThreePoint() : x(0), y(0), z(0){};
ThreePoint(int _z, int _x, int _y): x(_x), y(_y), z(_z) {};
ThreePoint(): x(0), y(0), z(0) {};
int x;
int y;
int z;
@ -41,8 +41,10 @@ public:
using TLVec = vector<vector<vector<CardT>>>;
enum Values { MATCHED = -3, EMPTY, FREE };
bool isPositive(const wxSize& size);
enum Values {
MATCHED = -3,
EMPTY,
FREE
};
#endif