197 lines
4.8 KiB
C++
197 lines
4.8 KiB
C++
|
#include "puzzle.h"
|
||
|
#include "main.h"
|
||
|
#include "utils.h"
|
||
|
#include "sound.h"
|
||
|
|
||
|
|
||
|
#define FIELD_OFFSET_X 12
|
||
|
#define FIELD_OFFSET_Y 68
|
||
|
#define FIELD_GAP_X 4
|
||
|
#define FIELD_GAP_Y 4
|
||
|
#define FIELD_TILE_WIDTH 48
|
||
|
#define FIELD_TILE_HEIGHT 48
|
||
|
|
||
|
|
||
|
Puzzle::Puzzle(IconSet &is, SolvedPuzzle &s, Possibilities *p):
|
||
|
iconSet(is), solved(s)
|
||
|
{
|
||
|
possib = p;
|
||
|
|
||
|
reset();
|
||
|
}
|
||
|
|
||
|
|
||
|
Puzzle::~Puzzle()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void Puzzle::reset()
|
||
|
{
|
||
|
valid = true;
|
||
|
win = false;
|
||
|
|
||
|
int x, y;
|
||
|
SDL_GetMouseState(&x, &y);
|
||
|
getCellNo(x, y, hCol, hRow, subHNo);
|
||
|
}
|
||
|
|
||
|
void Puzzle::draw()
|
||
|
{
|
||
|
for (int i = 0; i < PUZZLE_SIZE; i++)
|
||
|
for (int j = 0; j < PUZZLE_SIZE; j++)
|
||
|
drawCell(i, j, true);
|
||
|
}
|
||
|
|
||
|
void Puzzle::drawCell(int col, int row, bool addToUpdate)
|
||
|
{
|
||
|
int posX = FIELD_OFFSET_X + col * (FIELD_TILE_WIDTH + FIELD_GAP_X);
|
||
|
int posY = FIELD_OFFSET_Y + row * (FIELD_TILE_HEIGHT + FIELD_GAP_Y);
|
||
|
|
||
|
if (possib->isDefined(col, row)) {
|
||
|
int element = possib->getDefined(col, row);
|
||
|
if (element > 0)
|
||
|
screen.draw(posX, posY, iconSet.getLargeIcon(row, element,
|
||
|
(hCol == col) && (hRow == row)));
|
||
|
} else {
|
||
|
screen.draw(posX, posY, iconSet.getEmptyFieldIcon());
|
||
|
int x = posX;
|
||
|
int y = posY + (FIELD_TILE_HEIGHT / 6);
|
||
|
for (int i = 0; i < 6; i++) {
|
||
|
if (possib->isPossible(col, row, i + 1))
|
||
|
screen.draw(x, y, iconSet.getSmallIcon(row, i + 1,
|
||
|
(hCol == col) && (hRow == row) && (i + 1 == subHNo)));
|
||
|
if (i == 2) {
|
||
|
x = posX;
|
||
|
y += (FIELD_TILE_HEIGHT / 3);
|
||
|
} else
|
||
|
x += (FIELD_TILE_WIDTH / 3);
|
||
|
}
|
||
|
}
|
||
|
if (addToUpdate)
|
||
|
screen.addRegionToUpdate(posX, posY, FIELD_TILE_WIDTH,
|
||
|
FIELD_TILE_HEIGHT);
|
||
|
}
|
||
|
|
||
|
|
||
|
void Puzzle::drawRow(int row, bool addToUpdate)
|
||
|
{
|
||
|
for (int i = 0; i < PUZZLE_SIZE; i++)
|
||
|
drawCell(i, row, addToUpdate);
|
||
|
}
|
||
|
|
||
|
|
||
|
bool Puzzle::onMouseButtonDown(int button, int x, int y)
|
||
|
{
|
||
|
int col, row, element;
|
||
|
|
||
|
if (! getCellNo(x, y, col, row, element))
|
||
|
return false;
|
||
|
|
||
|
if (! possib->isDefined(col, row)) {
|
||
|
/*if (button == 3) {
|
||
|
for (int i = 1; i <= PUZZLE_SIZE; i++)
|
||
|
possib->makePossible(col, row, i);
|
||
|
drawCell(col, row);
|
||
|
}
|
||
|
} else {*/
|
||
|
if (element == -1)
|
||
|
return false;
|
||
|
if (button == 1) {
|
||
|
if (possib->isPossible(col, row, element)) {
|
||
|
possib->set(col, row, element);
|
||
|
sound->play(L"laser.wav");
|
||
|
}
|
||
|
} else if (button == 3) {
|
||
|
if (possib->isPossible(col, row, element)) {
|
||
|
possib->exclude(col, row, element);
|
||
|
sound->play(L"whizz.wav");
|
||
|
}
|
||
|
/*else
|
||
|
possib->makePossible(col, row, element);*/
|
||
|
}
|
||
|
drawRow(row);
|
||
|
}
|
||
|
|
||
|
bool valid = possib->isValid(solved);
|
||
|
if (! valid)
|
||
|
onFail();
|
||
|
else
|
||
|
if (possib->isSolved() && valid)
|
||
|
onVictory();
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
void Puzzle::onFail()
|
||
|
{
|
||
|
if (failCommand)
|
||
|
failCommand->doAction();
|
||
|
}
|
||
|
|
||
|
|
||
|
void Puzzle::onVictory()
|
||
|
{
|
||
|
if (winCommand)
|
||
|
winCommand->doAction();
|
||
|
}
|
||
|
|
||
|
bool Puzzle::getCellNo(int x, int y, int &col, int &row, int &subNo)
|
||
|
{
|
||
|
col = row = subNo = -1;
|
||
|
|
||
|
if (! isInRect(x, y, FIELD_OFFSET_X, FIELD_OFFSET_Y,
|
||
|
(FIELD_TILE_WIDTH + FIELD_GAP_X) * PUZZLE_SIZE,
|
||
|
(FIELD_TILE_HEIGHT + FIELD_GAP_Y) * PUZZLE_SIZE))
|
||
|
return false;
|
||
|
|
||
|
x = x - FIELD_OFFSET_X;
|
||
|
y = y - FIELD_OFFSET_Y;
|
||
|
|
||
|
col = x / (FIELD_TILE_WIDTH + FIELD_GAP_X);
|
||
|
if (col * (FIELD_TILE_WIDTH + FIELD_GAP_X) + FIELD_TILE_WIDTH < x)
|
||
|
return false;
|
||
|
row = y / (FIELD_TILE_HEIGHT + FIELD_GAP_Y);
|
||
|
if (row * (FIELD_TILE_HEIGHT + FIELD_GAP_Y) + FIELD_TILE_HEIGHT < y)
|
||
|
return false;
|
||
|
|
||
|
x = x - col * (FIELD_TILE_WIDTH + FIELD_GAP_X);
|
||
|
y = y - row * (FIELD_TILE_HEIGHT + FIELD_GAP_Y)
|
||
|
- FIELD_TILE_HEIGHT / 6;
|
||
|
if ((y < 0) || (y >= (FIELD_TILE_HEIGHT / 3) * 2))
|
||
|
return true;
|
||
|
int cCol = x / (FIELD_TILE_WIDTH / 3);
|
||
|
if (cCol >= 3) {
|
||
|
col = row = -1;
|
||
|
return false;
|
||
|
}
|
||
|
int cRow = y / (FIELD_TILE_HEIGHT / 3);
|
||
|
subNo = cRow * 3 + cCol + 1;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool Puzzle::onMouseMove(int x, int y)
|
||
|
{
|
||
|
int oldCol = hCol;
|
||
|
int oldRow = hRow;
|
||
|
int oldElement = subHNo;
|
||
|
|
||
|
getCellNo(x, y, hCol, hRow, subHNo);
|
||
|
if ((hCol != oldCol) || (hRow != oldRow) || (subHNo != oldElement)) {
|
||
|
if ((oldCol != -1) && (oldRow != -1))
|
||
|
drawCell(oldCol, oldRow);
|
||
|
if ((hCol != -1) && (hRow != -1))
|
||
|
drawCell(hCol, hRow);
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void Puzzle::setCommands(Command *win, Command *fail)
|
||
|
{
|
||
|
winCommand = win;
|
||
|
failCommand = fail;
|
||
|
}
|
||
|
|