Improved rendering system: fixed bugs, added min size limits, moved all drawing-related methods to Drawer class
This commit is contained in:
parent
43c90fc63b
commit
d633f9751d
156
Controller.cpp
156
Controller.cpp
@ -1,38 +1,15 @@
|
||||
#include "Controller.h"
|
||||
|
||||
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);
|
||||
}
|
||||
Controller::Controller(Drawer& drawer) : drawer(drawer){};
|
||||
|
||||
void Controller::loadLayout(const wxString& path) {
|
||||
layout.openFile(path);
|
||||
|
||||
drawer.gridSize = layout.getDimensions();
|
||||
gridSize = layout.getDimensions();
|
||||
|
||||
table = TLVec(drawer.gridSize.z, vector<vector<CardT>>(drawer.gridSize.x, vector<CardT>(drawer.gridSize.y, EMPTY)));
|
||||
table = TLVec(
|
||||
gridSize.z,
|
||||
vector<vector<CardT>>(gridSize.x, vector<CardT>(gridSize.y, EMPTY)));
|
||||
|
||||
layout.readLayout(table);
|
||||
|
||||
@ -60,8 +37,6 @@ 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;
|
||||
@ -87,16 +62,19 @@ void Controller::fillSolveableTable() {
|
||||
past_pos = emplace_rand(id, positions, past_pos, past_ptr);
|
||||
|
||||
cardsCounter[id]--;
|
||||
} else
|
||||
} else
|
||||
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)
|
||||
for (int i = 0; i < d; i++)
|
||||
past_ptr++;
|
||||
@ -119,9 +97,9 @@ int Controller::emplace_rand(int id, std::list<ThreePoint> positions, int past_p
|
||||
}
|
||||
|
||||
void Controller::free_table() {
|
||||
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++) {
|
||||
for (int z = 0; z < gridSize.z; z++)
|
||||
for (int x = 0; x < gridSize.x; x++)
|
||||
for (int y = 0; y < gridSize.y; y++) {
|
||||
CardT id = table[z][x][y];
|
||||
|
||||
if (id >= 0) {
|
||||
@ -136,14 +114,14 @@ void Controller::free_table() {
|
||||
|
||||
void Controller::fillRandom() {
|
||||
srand(time(NULL));
|
||||
|
||||
|
||||
wxLogDebug(wxString::Format("%i", remaining));
|
||||
|
||||
auto not_end = remaining;
|
||||
|
||||
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++)
|
||||
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++)
|
||||
if (table[z][x][y] == FREE) {
|
||||
table[z][x][y] = genRandId();
|
||||
not_end--;
|
||||
@ -166,8 +144,8 @@ CardT Controller::genRandId() {
|
||||
}
|
||||
|
||||
/**
|
||||
* It also changes point to top right coordinate of card
|
||||
*/
|
||||
* It also changes point to top right coordinate of card
|
||||
*/
|
||||
CardT* Controller::getCardByPosition(ThreePoint& point) {
|
||||
int8_t topIndex = -1;
|
||||
CardT* res = nullptr;
|
||||
@ -185,10 +163,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;
|
||||
@ -198,10 +176,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;
|
||||
@ -211,10 +189,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;
|
||||
@ -229,45 +207,50 @@ CardT* Controller::getCardByPosition(ThreePoint& point) {
|
||||
return res;
|
||||
}
|
||||
|
||||
bool Controller::available(const ThreePoint& point) {
|
||||
bool Controller::available(const ThreePoint& point) const {
|
||||
return upFree(point) && sideFree(point);
|
||||
}
|
||||
|
||||
bool Controller::upFree(const ThreePoint& point) {
|
||||
bool Controller::upFree(const ThreePoint& point) const {
|
||||
|
||||
if (point.z == table.size() - 1)
|
||||
return true;
|
||||
|
||||
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)
|
||||
);
|
||||
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));
|
||||
}
|
||||
|
||||
bool Controller::sideFree(const ThreePoint& point) {
|
||||
bool Controller::sideFree(const ThreePoint& point) const {
|
||||
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)
|
||||
);
|
||||
|
||||
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));
|
||||
|
||||
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;
|
||||
}
|
||||
@ -281,9 +264,11 @@ 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;
|
||||
|
||||
@ -296,19 +281,18 @@ void Controller::handleClick(const wxPoint& point) {
|
||||
selected = card;
|
||||
drawer.marked = pos;
|
||||
}
|
||||
|
||||
drawer.initScreen(table);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Controller::sameValues(CardT a, CardT b) {
|
||||
if (a == b) return true;
|
||||
else if (a >= 38 && b >= 38)
|
||||
bool Controller::sameValues(CardT a, CardT b) const {
|
||||
if (a == b)
|
||||
return true;
|
||||
else if (a >= 38 && b >= 38)
|
||||
return true;
|
||||
else if (a >= 34 && a <= 37 && b >= 34 && b <= 37)
|
||||
return true;
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -323,3 +307,7 @@ void Controller::undo() {
|
||||
steps.pop();
|
||||
}
|
||||
}
|
||||
|
||||
bool Controller::gameStarted() const {
|
||||
return stopwatch > 0;
|
||||
}
|
22
Controller.h
22
Controller.h
@ -16,8 +16,6 @@ public:
|
||||
|
||||
int stopwatch = -1;
|
||||
|
||||
void resize(const wxSize& tableSize);
|
||||
|
||||
void loadLayout(const wxString& path);
|
||||
|
||||
void handleClick(const wxPoint& point);
|
||||
@ -31,6 +29,11 @@ public:
|
||||
uint8_t remaining;
|
||||
|
||||
void undo();
|
||||
|
||||
bool gameStarted() const;
|
||||
|
||||
Dimensions gridSize;
|
||||
|
||||
private:
|
||||
Drawer& drawer;
|
||||
XmlLayout layout;
|
||||
@ -40,21 +43,22 @@ private:
|
||||
CardT* selected = nullptr;
|
||||
|
||||
void fillSolveableTable();
|
||||
void fillRandom();
|
||||
int emplace_rand(int id, std::list<ThreePoint> positions, int past_pos,
|
||||
std::list<ThreePoint>::iterator past_ptr);
|
||||
|
||||
int emplace_rand(int id, std::list<ThreePoint> positions, int past_pos, std::list<ThreePoint>::iterator past_ptr);
|
||||
void fillRandom();
|
||||
|
||||
CardT genRandId();
|
||||
|
||||
CardT* getCardByPosition(ThreePoint& point);
|
||||
|
||||
bool available(const ThreePoint& point);
|
||||
bool upFree(const ThreePoint& point);
|
||||
bool sideFree(const ThreePoint& point);
|
||||
bool available(const ThreePoint& point) const;
|
||||
bool upFree(const ThreePoint& point) const;
|
||||
bool sideFree(const ThreePoint& point) const;
|
||||
|
||||
bool sameValues(CardT a, CardT b);
|
||||
bool sameValues(CardT a, CardT b) const;
|
||||
|
||||
std::array<uint8_t, TILE_IMAGES_N>cardsCounter;
|
||||
std::array<uint8_t, TILE_IMAGES_N> cardsCounter;
|
||||
|
||||
std::stack<std::array<CardEntry, 2>> steps;
|
||||
};
|
||||
|
218
Drawer.cpp
218
Drawer.cpp
@ -1,42 +1,166 @@
|
||||
#include "Drawer.h"
|
||||
|
||||
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 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
|
||||
};
|
||||
|
||||
Drawer::Drawer(): marked{-1, -1, -1} {
|
||||
static const wxColor lGreen{0x07, 0x55, 0x2b};
|
||||
static const wxColor dGreen{0x01, 0x2d, 0x16};
|
||||
|
||||
Drawer::Drawer() : marked{-1, -1, -1} {
|
||||
for (int i = 0; i < TILE_IMAGES_N; i++) {
|
||||
if (!tileImages[i].LoadFile(_("./resources/tiles/") + _(tileImageNames[i]) + _(".png"), wxBITMAP_TYPE_PNG))
|
||||
wxLogDebug(_("./resources/tiles/") + _(tileImageNames[i]) + _(".png ") + wxString::Format(wxT("%i"), 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));
|
||||
}
|
||||
}
|
||||
|
||||
void Drawer::drawTable(wxDC& dc) {
|
||||
if (isScreenReady)
|
||||
dc.DrawBitmap(screenBitmap, 0, 0, false);
|
||||
dc.DrawBitmap(bgBitmap, 0, 0, false);
|
||||
if (boardBitmap.IsOk()) {
|
||||
wxLogDebug("Drawing board");
|
||||
dc.DrawBitmap(boardBitmap, tablePixelRect.GetPosition(), true);
|
||||
}
|
||||
}
|
||||
|
||||
wxBitmap copyBitmap(const wxBitmap& old) {
|
||||
return old.GetSubBitmap(wxRect(0, 0, old.GetWidth(), old.GetHeight()));
|
||||
}
|
||||
void Drawer::composeBG() {
|
||||
bgBitmap = wxBitmap(resolution);
|
||||
|
||||
void Drawer::setBG(const wxSize& tableSize) {
|
||||
bgBitmap = wxBitmap(tableSize);
|
||||
wxLogDebug(
|
||||
wxString::Format("Rebuild bg %i %i", resolution.x, resolution.y));
|
||||
|
||||
wxMemoryDC dc;
|
||||
dc.SelectObject(bgBitmap);
|
||||
|
||||
dc.GradientFillConcentric(wxRect(wxPoint(0, 0), tableSize), wxColor(7, 85, 45), wxColor(1, 45, 22));
|
||||
|
||||
isBgReady = true;
|
||||
dc.GradientFillConcentric(wxRect(wxPoint(0, 0), resolution), lGreen,
|
||||
dGreen);
|
||||
}
|
||||
|
||||
wxPoint Drawer::toGrid(const wxPoint& point) {
|
||||
void Drawer::composeBoard(const TLVec& layout, const Dimensions& gridSize) {
|
||||
boardBitmap = wxBitmap(tablePixelRect.GetSize());
|
||||
|
||||
wxLogDebug(_("Rebuild board"));
|
||||
|
||||
wxMemoryDC dc;
|
||||
dc.SelectObject(boardBitmap);
|
||||
|
||||
for (int z = 0; z < gridSize.z; z++)
|
||||
for (int x = 0; x < gridSize.x; x++)
|
||||
for (int y = 0; y < gridSize.y; y++) {
|
||||
CardT c = layout[z][x][y];
|
||||
if (c >= 0)
|
||||
drawTile(dc, c, fromGrid(x, y), z);
|
||||
}
|
||||
|
||||
wxMask* mask = new wxMask(boardBitmap, wxColor(0x00, 0x00, 0x00));
|
||||
boardBitmap.SetMask(mask);
|
||||
}
|
||||
|
||||
void Drawer::drawTile(wxDC& dc, int8_t index, const wxPoint& position,
|
||||
uint8_t zIndex) const {
|
||||
wxBrush _bgColor = dc.GetBrush();
|
||||
|
||||
wxBrush front = wxColor(0xff, 0xff, 0xff);
|
||||
wxBrush back = wxColor(0xc8, 0xc8, 0xc8);
|
||||
|
||||
if (position == fromGrid({marked.x, marked.y}) && marked.z == zIndex) {
|
||||
front = wxColor(0xc8, 0xff, 0xc8);
|
||||
back = wxColor(0xbe, 0xdc, 0xbe);
|
||||
}
|
||||
|
||||
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.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.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);
|
||||
else
|
||||
dc.DrawBitmap(tileImages[index], pos);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
point.y <= tablePixelRect.y + tablePixelRect.height) {
|
||||
out.x = (point.x - tablePixelRect.x) / tilePixelSize.x;
|
||||
out.y = (point.y - tablePixelRect.y) / tilePixelSize.y;
|
||||
}
|
||||
@ -44,61 +168,21 @@ wxPoint Drawer::toGrid(const wxPoint& point) {
|
||||
return out;
|
||||
}
|
||||
|
||||
wxPoint Drawer::fromGrid(int x, int y) {
|
||||
return { tablePixelRect.x + x * tilePixelSize.x,
|
||||
tablePixelRect.y + y * tilePixelSize.y };
|
||||
wxPoint Drawer::fromGrid(int x, int y) const {
|
||||
return {x * tilePixelSize.x, y * tilePixelSize.y};
|
||||
}
|
||||
|
||||
wxPoint Drawer::fromGrid(const wxPoint& point) {
|
||||
wxPoint Drawer::fromGrid(const wxPoint& point) const {
|
||||
return fromGrid(point.x, point.y);
|
||||
}
|
||||
|
||||
void Drawer::initScreen(const TLVec& layout) {
|
||||
if (isBgReady) {
|
||||
screenBitmap = copyBitmap(bgBitmap);
|
||||
wxSize Drawer::composeMinSize(const wxSize& gridSize) {
|
||||
wxSize ms;
|
||||
|
||||
wxLogDebug(_("Reinit"));
|
||||
ms.SetWidth(MIN_GRID_POINT * TILE_WIDTH * gridSize.x);
|
||||
ms.SetHeight(MIN_GRID_POINT * TILE_HEIGHT * gridSize.y);
|
||||
|
||||
wxMemoryDC dc;
|
||||
dc.SelectObject(screenBitmap);
|
||||
wxLogDebug(wxString::Format("MinSize %i %i", ms.x, ms.y));
|
||||
|
||||
for (int z = 0; z < gridSize.z; z++)
|
||||
for (int x = 0; x < gridSize.x; x++)
|
||||
for (int y = 0; y < gridSize.y; y++) {
|
||||
CardT c = layout[z][x][y];
|
||||
if (c >= 0)
|
||||
drawTile(dc, c, fromGrid(x, y), z);
|
||||
}
|
||||
|
||||
isScreenReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Drawer::drawTile(wxDC& dc, int8_t index, const wxPoint& position, uint8_t zIndex) {
|
||||
wxBrush _bgColor = dc.GetBrush();
|
||||
|
||||
wxBrush front = wxColor(255, 255, 255);
|
||||
wxBrush back = wxColor(200, 200, 200);
|
||||
|
||||
if (position == fromGrid({marked.x, marked.y}) && marked.z == zIndex) {
|
||||
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.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.SetBrush(_bgColor);
|
||||
|
||||
if (tileImages[index].IsOk()) {
|
||||
if (tileImages[index].GetWidth() != tilePixelSize.x * 2)
|
||||
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], {position.x + 10 - (tilePixelSize.GetWidth()/10 + 3)*zIndex, position.y + 10 - (tilePixelSize.GetHeight()/10 + 3)*zIndex});
|
||||
}
|
||||
}
|
||||
return ms;
|
||||
}
|
35
Drawer.h
35
Drawer.h
@ -10,39 +10,44 @@
|
||||
|
||||
#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; // кратно 600x800
|
||||
wxSize tilePixelSize; // кратно 3x4, по умолчанию 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 drawScreen(wxDC& dc);
|
||||
void drawTile(wxDC& dc, int8_t index, const wxPoint& position, uint8_t zIndex);
|
||||
|
||||
void drawTile(wxDC& dc, int8_t index, const wxPoint& position,
|
||||
uint8_t zIndex) const;
|
||||
|
||||
wxImage tileImages[TILE_IMAGES_N];
|
||||
|
||||
wxBitmap bgBitmap;
|
||||
wxBitmap screenBitmap;
|
||||
wxBitmap boardBitmap;
|
||||
|
||||
bool isBgReady = false;
|
||||
bool isScreenReady = false;
|
||||
int prevGridPoint;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
103
GamePanel.cpp
103
GamePanel.cpp
@ -4,65 +4,96 @@
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
GamePanel::GamePanel(wxFrame* parent) : wxPanel(parent), controller(drawer) {
|
||||
// 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) {
|
||||
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) {
|
||||
void GamePanel::Start(const wxString& path, bool solveable,
|
||||
std::function<void(const wxSize& size)> setMinSize) {
|
||||
wxLogDebug(_("Started game"));
|
||||
|
||||
controller.stopwatch = 0;
|
||||
controller.loadLayout(path);
|
||||
controller.fill(solveable);
|
||||
|
||||
timer->Start(1000, wxTIMER_CONTINUOUS);
|
||||
|
||||
if (sb == nullptr)
|
||||
sb = ((wxFrame*)this->GetParent())->GetStatusBar();
|
||||
setMinSize(drawer.composeMinSize(controller.gridSize));
|
||||
|
||||
timer.Start(1000, wxTIMER_CONTINUOUS);
|
||||
|
||||
sb->SetStatusText(LTimeToStr(controller.stopwatch), 0);
|
||||
sb->SetStatusText(PRemaining(controller.remaining), 1);
|
||||
|
||||
drawer.initScreen(controller.getTable());
|
||||
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();
|
||||
}
|
||||
|
||||
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& _) {
|
||||
controller.handleClick(ScreenToClient(wxGetMousePosition()));
|
||||
sb->SetStatusText(PRemaining(controller.remaining), 1);
|
||||
if (controller.gameStarted()) {
|
||||
controller.handleClick(ScreenToClient(wxGetMousePosition()));
|
||||
sb->SetStatusText(PRemaining(controller.remaining), 1);
|
||||
|
||||
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();
|
||||
drawer.composeBoard(controller.getTable(), controller.gridSize);
|
||||
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
14
GamePanel.h
14
GamePanel.h
@ -5,14 +5,15 @@
|
||||
|
||||
#include <wx/stopwatch.h>
|
||||
|
||||
#include "Drawer.h"
|
||||
#include "Controller.h"
|
||||
#include "Drawer.h"
|
||||
|
||||
class GamePanel : public wxPanel {
|
||||
public:
|
||||
GamePanel(wxFrame* parent);
|
||||
|
||||
void Start(const wxString& path, bool solveable);
|
||||
void Start(const wxString& path, bool solveable,
|
||||
std::function<void(const wxSize& size)> setMinSize);
|
||||
|
||||
void undo();
|
||||
void reshuffle(bool solveable);
|
||||
@ -22,11 +23,16 @@ private:
|
||||
Controller controller;
|
||||
|
||||
void OnPaint(wxPaintEvent& _);
|
||||
void OnResize(wxSizeEvent& _);
|
||||
void OnTimer(wxTimerEvent& _);
|
||||
void OnClick(wxMouseEvent& _);
|
||||
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
|
||||
wxStatusBar* sb = nullptr;
|
||||
wxTimer* timer = nullptr;
|
||||
wxTimer timer;
|
||||
};
|
||||
|
||||
#define TIMER_ID 1
|
||||
|
||||
#endif
|
||||
|
116
MainFrame.cpp
116
MainFrame.cpp
@ -1,47 +1,53 @@
|
||||
#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();
|
||||
|
||||
if (openLayout())
|
||||
panel->Start(layoutPath, solveable);
|
||||
}
|
||||
|
||||
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, _("Помощь"));
|
||||
|
||||
@ -49,57 +55,77 @@ 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);
|
||||
}, IDM_Open);
|
||||
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 {
|
||||
(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);
|
||||
Refresh();
|
||||
}
|
||||
}, IDM_New_Game);
|
||||
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& evt) -> void {
|
||||
solveable = evt.IsChecked();
|
||||
}, IDM_Solveable);
|
||||
Bind(
|
||||
wxEVT_MENU,
|
||||
[this](wxCommandEvent& evt) -> void { solveable = evt.IsChecked(); },
|
||||
IDM_Solveable);
|
||||
|
||||
Bind(wxEVT_MENU, [this](wxCommandEvent& _) -> void {
|
||||
panel->undo();
|
||||
}, IDM_Undo);
|
||||
Bind(
|
||||
wxEVT_MENU, [this](wxCommandEvent& _) -> void { panel->undo(); },
|
||||
IDM_Undo);
|
||||
|
||||
Bind(wxEVT_MENU, [this](wxCommandEvent& _) -> void {
|
||||
panel->reshuffle(solveable);
|
||||
}, IDM_Reshuffle);
|
||||
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
|
||||
* 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);
|
||||
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;
|
||||
|
||||
layoutPath = openFileDlg.GetPath();
|
||||
layoutPath = openFileDlg.GetPath();
|
||||
return true;
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
#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) {
|
||||
@ -13,5 +14,9 @@ wxString itowxS(int a) {
|
||||
}
|
||||
|
||||
wxString PRemaining(uint8_t remaining) {
|
||||
return wxString::Format("%i%%", remaining*100 / 144);
|
||||
return wxString::Format("%i%%", remaining * 100 / 144);
|
||||
}
|
||||
|
||||
bool isPositive(const wxSize& size) {
|
||||
return size.x > 0 && size.y > 0;
|
||||
}
|
16
utils.h
16
utils.h
@ -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,10 +41,8 @@ public:
|
||||
|
||||
using TLVec = vector<vector<vector<CardT>>>;
|
||||
|
||||
enum Values {
|
||||
MATCHED = -3,
|
||||
EMPTY,
|
||||
FREE
|
||||
};
|
||||
enum Values { MATCHED = -3, EMPTY, FREE };
|
||||
|
||||
bool isPositive(const wxSize& size);
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user