• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

ksquares

gameboardscene.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2006 by Matthew Williams    <matt@milliams.com>         *
00003  *                                                                         *
00004  *   This program is free software; you can redistribute it and/or modify  *
00005  *   it under the terms of the GNU General Public License as published by  *
00006  *   the Free Software Foundation; either version 2 of the License, or     *
00007  *   (at your option) any later version.                                   *
00008  ***************************************************************************/
00009 
00010 #include "gameboardscene.h"
00011 
00012 #include "highlightanimation.h"
00013 
00014 #include <math.h>
00015 
00016 #include <QGraphicsSceneMouseEvent>
00017 #include <QGraphicsEllipseItem>
00018 
00019 #include <kdebug.h>
00020 #include <kggzmod/module.h>
00021 
00022 GameBoardScene::GameBoardScene(int newWidth, int newHeight, QObject *parent) : QGraphicsScene(parent), width(newWidth), height(newHeight), acceptEvents(true)
00023 {
00024     //kDebug() << "GameBoardScene::GameBoardScene()";
00025     
00026     for(int i = 0; i < (2*width*height + width + height); i++)
00027     {
00028         lineList.append(false); //simply fill array with 'false's
00029     }
00030     
00031     spacing = 40;   //this hard coding doesn't matter since auto-resizing exists :)
00032     for(int iWidth = 0; iWidth <= width; iWidth++)
00033     {
00034         for(int iHeight = 0; iHeight <= height; iHeight++)
00035         {
00036             int x = iWidth*spacing;
00037             int y = iHeight*spacing;
00038             QGraphicsEllipseItem *dot = new QGraphicsEllipseItem(QRectF(-2,-2,4,4));
00039             dot->moveBy(x,y);
00040             dot->setBrush(Qt::SolidPattern);
00041             dot->setZValue(20); // set the elevation, the dot's are on top
00042             addItem(dot);
00043         }
00044     }
00045     QPen feintPen(Qt::DotLine); //for the guidelines between dots
00046     feintPen.setWidth(1);
00047     feintPen.setColor(Qt::lightGray);
00048     for(int iWidth = 0; iWidth <= width; iWidth++)
00049     {
00050         addLine(QLineF(spacing*iWidth, 0, spacing*iWidth, spacing*height), feintPen);
00051     }
00052     for(int iHeight = 0; iHeight <= height; iHeight++)
00053     {
00054         addLine(QLineF(0, spacing*iHeight, spacing*width, spacing*iHeight), feintPen);
00055     }
00056     
00057     setBackgroundBrush(QBrush(Qt::white));
00058     
00059     indicatorLine = new QGraphicsLineItem(1,1,1,1);
00060     indicatorLine->setZValue(10);
00061     indicatorLine->setPen(QPen(Qt::yellow, 2.5));
00062     indicatorLine->hide();
00063     addItem(indicatorLine);
00064     
00065     QGraphicsEllipseItem tempItem;
00066     QGraphicsEllipseItemType = tempItem.type();
00067     
00068     qreal border = 10;
00069     QRectF rect = sceneRect();
00070     rect.setLeft(rect.left() - border);
00071     rect.setRight(rect.right() + border);
00072     rect.setTop(rect.top() - border);
00073     rect.setBottom(rect.bottom() + border);
00074     setSceneRect(rect);
00075 }
00076 
00077 GameBoardScene::~GameBoardScene()
00078 {
00079     kDebug() << "GameBoardScene::~GameBoardScene()";
00080     delete indicatorLine;
00081 }
00082 
00083 void GameBoardScene::drawLine(int index, const QColor &colour)
00084 {
00085     QGraphicsLineItem* line = new QGraphicsLineItem(lineFromIndex(index));
00086     line->setZValue(10);
00087     line->setPen(QPen(QBrush(colour), 2.5));
00088     addItem(line);  //draw new line
00089     lineList[index] = true; //keep this table in sync
00090     indicatorLine->hide();
00091     update(line->boundingRect());
00092 }
00093 
00094 void GameBoardScene::highlightLine(int index)
00095 {
00096     HighlightAnimation* anim = new HighlightAnimation(lineFromIndex(index));
00097     anim->setZValue(9);
00098     addItem(anim);
00099 }
00100 
00101 void GameBoardScene::drawSquare(int index, const QColor &colour)
00102 {
00103     QBrush brush(colour, Qt::SolidPattern);
00104     
00105     addRect(QRectF(qreal((index%width)*spacing), qreal((index/width)*spacing), qreal(spacing), qreal(spacing)), QPen(), brush)->setZValue(-1);
00106 }
00107 
00108 int GameBoardScene::indexFromPointPair(const QList<QGraphicsEllipseItem*> &pointPair) const
00109 {
00110 
00111     if (pointPair.size() != 2)
00112         return -1; // if it isn't a pair
00113     
00114     qreal pointOneX = pointPair.at(0)->scenePos().x()/spacing;
00115     qreal pointOneY = pointPair.at(0)->scenePos().y()/spacing;
00116     qreal pointTwoX = pointPair.at(1)->scenePos().x()/spacing;
00117     qreal pointTwoY = pointPair.at(1)->scenePos().y()/spacing;
00118     
00119     //this int conversion could go bad but SHOULD be safe
00120     qreal refX; // these two will be the grid-coord of the
00121     qreal refY; // to and left most point of the two
00122     
00123     int index = -1;
00124     if (pointOneX == pointTwoX)
00125     {
00126         //dir = VERTICAL;
00127         refX = pointOneX;
00128         if (pointTwoY < pointOneY)  //want the topmost point as reference
00129             refY = pointTwoY;
00130         else
00131             refY = pointOneY;
00132         index = static_cast<int>(refY * ((2*width)+1) + refX + width);
00133     }
00134 
00135     else if (pointOneY == pointTwoY)
00136     {
00137         //dir = HORIZONTAL;
00138         refY = pointOneY;
00139         if (pointOneX < pointTwoX)  //want the leftmost point as reference
00140             refX = pointOneX;
00141         else
00142             refX = pointTwoX;
00143         index = static_cast<int>(refY * ((2*width)+1) + refX);
00144     }
00145     return index;
00146 }
00147 
00148 QLineF GameBoardScene::lineFromIndex(int index) const
00149 {
00150     int index2 = index % ((2*width) + 1);
00151     enum{HORIZONTAL, VERTICAL} dir;
00152     if(index2 < width)
00153         dir = HORIZONTAL;
00154     else
00155         dir = VERTICAL;
00156     
00157     int yCoordStart = (index / ((2*width) + 1)) * spacing;
00158     int xCoordStart = 0;
00159     int yCoordEnd = 0;
00160     int xCoordEnd = 0;
00161     switch(dir)
00162     {
00163         case HORIZONTAL:
00164             xCoordStart = index2 * spacing;
00165             yCoordEnd = yCoordStart;
00166             xCoordEnd = xCoordStart + spacing;
00167             break;
00168         case VERTICAL:
00169             xCoordStart = (index2 - width) * spacing;
00170             yCoordEnd = yCoordStart + spacing;
00171             xCoordEnd = xCoordStart;
00172             break;
00173     }
00174     return QLineF(xCoordStart, yCoordStart, xCoordEnd, yCoordEnd);
00175 }
00176 
00177 bool GameBoardScene::isLineAlready(const QList<QGraphicsEllipseItem*> &pointPair) const //TODO does this work?
00178 {
00179     int index = indexFromPointPair(pointPair);
00180     if (index == -1)
00181         return true;
00182     
00183     return lineList.at(index);
00184 }
00185 
00186 void GameBoardScene::addLineToIndex(const QList<QGraphicsEllipseItem*> &pointPair)
00187 {
00188     int index = indexFromPointPair(pointPair);
00189     if (index == -1)    //not a valid line since no two unique ends
00190         return;
00191     
00192     emit lineDrawn(index);  //addLineToIndex(index);
00193 }
00194 
00195 QList<QGraphicsEllipseItem*> GameBoardScene::getTwoNearestPoints(const QPointF &pos) const
00196 {
00197     QList<QGraphicsItem*> itemList = items();
00198     QList<QGraphicsEllipseItem*> connectList;
00199     for (int i = 0; i < itemList.size(); ++i) 
00200     {
00201         if (itemList.at(i)->type() == QGraphicsEllipseItemType)
00202         {
00203             //cout << "itemList.at(i)->scenePos():" << qgraphicsitem_cast<QGraphicsEllipseItem*>(itemList.at(i))->scenePos().x() << "," << qgraphicsitem_cast<QGraphicsEllipseItem*>(itemList.at(i))->scenePos().y() << endl;
00204             QPointF dist(pos - itemList.at(i)->scenePos());
00205             qreal distMod = sqrt(dist.x()*dist.x() + dist.y()*dist.y());
00206             //if (distMod < (spacing*0.7071))   //there will only ever be either 1 or 2 items that fulfil this [0.7071 ~ 2^(-0.5)]
00207             if (distMod < spacing-5)
00208             {
00209                 connectList << qgraphicsitem_cast<QGraphicsEllipseItem*>(itemList.at(i));
00210             }
00211         }
00212     }
00213     return connectList;
00214 }
00215 
00216 const QSize GameBoardScene::minimumSizeHint() const
00217 {
00218     return QSize((width*spacing)+10, (height*spacing)+10);  // the +10 is to provide padding and to avoid scrollbars
00219 }
00220 
00221 /*void GameBoardScene::mousePressEvent (QGraphicsSceneMouseEvent* mouseEvent)
00222 {
00223     if (!acceptEvents) return;
00224     QGraphicsScene::mousePressEvent(mouseEvent);
00225 }*/
00226 
00227 void GameBoardScene::mouseReleaseEvent (QGraphicsSceneMouseEvent* mouseEvent)
00228 {
00229     if (!acceptEvents) 
00230     {
00231         QGraphicsScene::mouseReleaseEvent(mouseEvent);
00232         return;
00233     }
00234 
00235     //cout << "GameBoardScene::mouseReleaseEvent" << endl;
00236     if (mouseEvent->button() == Qt::LeftButton)
00237     {
00238         QList<QGraphicsEllipseItem*> connectList = getTwoNearestPoints(mouseEvent->scenePos());
00239         if (connectList.size() == 2)
00240         {
00241             if(KGGZMod::Module::instance())
00242             {
00243                 int x1 = (qint8)(connectList.at(0)->scenePos().x() / spacing);
00244                 int y1 = (qint8)(connectList.at(0)->scenePos().y() / spacing);
00245                 int x2 = (qint8)(connectList.at(1)->scenePos().x() / spacing);
00246                 int y2 = (qint8)(connectList.at(1)->scenePos().y() / spacing);
00247                 emit signalMoveRequest(x1, y1, x2, y2);
00248             }
00249             else
00250             {
00251                 addLineToIndex(connectList);
00252             }
00253         }
00254     }
00255     
00256     QGraphicsScene::mouseReleaseEvent(mouseEvent);
00257 }
00258 
00259 void GameBoardScene::acknowledgeMove(int x1, int y1, int x2, int y2)
00260 {
00261     QPoint calculatedpos(((x1 + x2) / 2.0) * spacing, ((y1 + y2) / 2.0) * spacing);
00262     QList<QGraphicsEllipseItem*> connectList = getTwoNearestPoints(calculatedpos);
00263     addLineToIndex(connectList);
00264 }
00265 
00266 void GameBoardScene::mouseMoveEvent (QGraphicsSceneMouseEvent* mouseEvent)
00267 {
00268     if (!acceptEvents) return;
00269     //indicatorLine = 0;
00270     
00271     //kDebug() << "GameBoardScene::mouseMoveEvent";
00272     //kDebug() << "mouseEvent->scenePos():" << mouseEvent->scenePos().x() << "," << mouseEvent->scenePos().y();
00273     
00274     QList<QGraphicsEllipseItem*> connectList = getTwoNearestPoints(mouseEvent->scenePos());
00275     
00276     if (connectList.size() == 2 && !isLineAlready(connectList))
00277     {   //if there are two nearest points and there isn't already a line
00278         indicatorLine->setLine(QLineF(connectList.at(0)->scenePos(), connectList.at(1)->scenePos()));   //where
00279         indicatorLine->show();
00280     }
00281     else
00282     {
00283         indicatorLine->hide();
00284     }
00285     
00286     QGraphicsScene::mouseMoveEvent(mouseEvent);
00287 }
00288 
00289 #include "gameboardscene.moc"

ksquares

Skip menu "ksquares"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • kblackbox
  • kgoldrunner
  • kmahjongg
  • ksquares
  • libkdegames
  •   highscore
  •   kgame
  •   kggzgames
  •   kggzmod
  •   kggznet
  • libkmahjongg
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal