toruschess/src/field2d.cpp

157 lines
5.5 KiB
C++

/***************************************************************************
* Copyright (C) 2009 by Stefan Bühler *
* stbuehler@web.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "field2d.h"
#include <math.h>
#include <QResizeEvent>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QPainter>
namespace toruschess {
Field2D::Field2D(Game *game, QWidget *parent)
: QWidget(parent), m_lib(new PieceLibrary(this)), m_game(game), m_fieldWidth(360), m_fieldHeight(360), m_originX(23), m_originY(23), m_fieldBuffer(0) {
for (int x = 0; x < 8; x++) for (int y = 0; y < 8; y++) m_marked[x][y] = false;
m_lib->setSize(m_fieldWidth / 8, m_fieldHeight / 8);
checkSizes();
connect(game, SIGNAL(updated()), this, SLOT(fieldUpdated()));
}
Field2D::~Field2D() {
if (m_fieldBuffer) delete m_fieldBuffer;
}
void Field2D::markMoves(const QList<Move> &moves) {
foreach(Move m, m_markedMoves) m_marked[m.to().x()][m.to().y()] = false;
m_markedMoves = moves;
foreach(Move m, m_markedMoves) m_marked[m.to().x()][m.to().y()] = true;
updateFieldBuffer();
update();
}
QSize Field2D::sizeHint() const {
return QSize(17*m_fieldWidth/8, 17*m_fieldHeight/8);
}
void Field2D::paintEvent(QPaintEvent *) {
QPainter pt(this);
int winWidth = width(), winHeight = height();
for (int px = m_originX - m_fieldWidth; px < winWidth; px += m_fieldWidth)
for (int py = m_originY - m_fieldHeight; py < winHeight; py += m_fieldHeight) {
pt.drawImage(QRect(px, py, m_fieldWidth, m_fieldHeight), *m_fieldBuffer);
}
}
void Field2D::mousePressEvent(QMouseEvent *event) {
if (event->button() == Qt::LeftButton) {
QList<Move> moves;
Pos p = findPos(event->x(), event->y());
moves = m_game->field()->validMoves(p);
markMoves(moves);
}
m_mouseLastX = event->x();
m_mouseLastY = event->y();
}
void Field2D::mouseMoveEvent(QMouseEvent *event) {
if (event->buttons() & Qt::RightButton) {
m_originX += event->x() - m_mouseLastX;
m_originY += event->y() - m_mouseLastY;
checkSizes();
update();
}
m_mouseLastX = event->x();
m_mouseLastY = event->y();
}
void Field2D::mouseReleaseEvent(QMouseEvent *event) {
m_mouseLastX = event->x();
m_mouseLastY = event->y();
if (event->button() == Qt::LeftButton) {
if (m_markedMoves.size() == 0) return;
Pos from = m_markedMoves[0].from();
QList<Move> moves;
markMoves(QList<Move>());
Pos p = findPos(event->x(), event->y());
Move m(m_game->field(), from, p);
m_game->move(m);
}
}
void Field2D::wheelEvent(QWheelEvent *event) {
double zoom = pow(1.2, event->delta() / 120);
int max = qMin(width(), height());
m_fieldWidth = qMax(120, qMin(max, (int) (m_fieldWidth * zoom))) & ~(0x7);
m_fieldHeight = qMax(120, qMin(max, (int) (m_fieldHeight * zoom))) & ~(0x7);
m_lib->setSize(m_fieldWidth / 8, m_fieldHeight / 8);
checkSizes();
update();
}
void Field2D::checkSizes() {
m_originX = m_originX % m_fieldWidth;
m_originY = m_originY % m_fieldHeight;
if (m_originX < 0) m_originX += m_fieldWidth;
if (m_originY < 0) m_originY += m_fieldHeight;
if (!m_fieldBuffer || m_fieldBuffer->width() != m_fieldWidth || m_fieldBuffer->height() != m_fieldHeight) {
if (m_fieldBuffer) delete m_fieldBuffer;
m_fieldBuffer = new QImage(QSize(m_fieldWidth, m_fieldHeight), QImage::Format_ARGB32_Premultiplied);
m_fieldBuffer->fill(Qt::black);
updateFieldBuffer();
}
}
void Field2D::updateFieldBuffer() {
QPainter pt(m_fieldBuffer);
int pieceWidth = m_fieldWidth / 8;
int pieceHeight = m_fieldHeight / 8;
for (int x = 0; x < 8; x++)
for (int y = 0; y < 8; y++) {
bool marked = m_marked[x][y];
int place = m_game->field()->place(Pos(x, y));
QRect prect(x * pieceWidth, y * pieceHeight, pieceWidth - 1, pieceHeight - 1);
m_lib->paint_board(pt, (x+y) % 2 == 1, prect);
m_lib->paint(pt, place, prect);
if (marked) {
int r = qMax(1, (pieceWidth + pieceHeight) / 36);
pt.setBrush(place != 0 ? Qt::green : Qt::white);
pt.setPen(Qt::red);
pt.drawEllipse(QPoint(prect.x() + pieceWidth / 2, prect.y() + pieceHeight / 2), r, r);
}
}
update();
}
Pos Field2D::findPos(int x, int y) {
return Pos(8 * ((x - m_originX) % m_fieldWidth) / m_fieldWidth, 8 * ((y - m_originY) % m_fieldHeight) / m_fieldHeight);
}
void Field2D::fieldUpdated() {
markMoves(QList<Move>());
}
}