displaygame.cpp

Go to the documentation of this file.
00001 /*
00002    This file is part of the KDE games kwin4 program
00003    Copyright (c) 2006 Martin Heni <kde@heni-online.de>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018    Boston, MA 02110-1301, USA.
00019 */
00020 
00021 // Standard includes
00022 #include <math.h>
00023 #include <assert.h>
00024 
00025 // Qt includes
00026 #include <QFont>
00027 #include <QColor>
00028 #include <QPixmap>
00029 #include <QPoint>
00030 
00031 // KDE includes
00032 #include <klocale.h>
00033 #include <kdebug.h>
00034 
00035 // Local includes
00036 #include "displaygame.h"
00037 #include "thememanager.h"
00038 #include "piecesprite.h"
00039 #include "pixmapsprite.h"
00040 #include "scoresprite.h"
00041 #include "spritenotify.h"
00042 #include "kwin4doc.h"
00043 
00044 
00045 
00046 // Constructor for the display
00047 DisplayGame::DisplayGame(int advancePeriod, QGraphicsScene* scene, ThemeManager* theme, QGraphicsView* parent)
00048            : Themable("gamedisplay",theme), QObject(parent)
00049 {
00050   // Store arguments as attributes
00051   mScene         = scene;
00052   mView          = parent;
00053   mAdvancePeriod = advancePeriod;
00054   mTheme         = theme;
00055   
00056     // Choose a background color
00057   scene->setBackgroundBrush(QColor(0,0,128));
00058 
00059   // Clear storage of all sprites
00060   mSprites.clear();
00061 
00062   // Create piece sprites 
00063   for (int i=0; i<42; i++)
00064   {
00065     PieceSprite* sprite = new PieceSprite("piece", mTheme, mAdvancePeriod, i, mScene);
00066     if (!sprite) kFatal() << "Cannot load sprite " << "piece" << endl;
00067     mSprites.append(sprite);
00068     mPieces.append(sprite);
00069     sprite->hide();
00070   }
00071 
00072   // Create stars
00073   for (int i=0;i<4;i++)
00074   {
00075     PixmapSprite* sprite = new PixmapSprite("star", mTheme, mAdvancePeriod, i, mScene);
00076     if (!sprite) kFatal() << "Cannot load sprite " << "star" << endl;
00077     mSprites.append(sprite);
00078     mStars.append(sprite);
00079     sprite->hide();
00080   }
00081 
00082   // Create board
00083   mBoard = new PixmapSprite("board", mTheme, mAdvancePeriod, 0, mScene);
00084   if (!mBoard) kFatal() << "Cannot load sprite " << "board" << endl;
00085   mSprites.append(mBoard);
00086   mBoard->hide();
00087 
00088   // Create hint
00089   mHint = new PixmapSprite("hint", mTheme, mAdvancePeriod, 0, mScene);
00090   if (!mHint) kFatal() << "Cannot load sprite " << "hint" << endl;
00091   mSprites.append(mHint);
00092   mHint->hide();
00093 
00094   // Create Game Over
00095   mGameOver = new PixmapSprite("gameover", mTheme, mAdvancePeriod, 0, mScene);
00096   if (!mGameOver) kFatal() << "Cannot load sprite " << "gameover" << endl;
00097   mSprites.append(mGameOver);
00098   mGameOver->hide();
00099 
00100   // Create board holes
00101   for (int i=0; i<42; i++)
00102   {
00103     PixmapSprite* boardHole = new PixmapSprite("boardholes", mTheme, mAdvancePeriod, i, mScene);
00104     if (!boardHole) kFatal() << "Cannot load sprite " << "boardHoles" << endl;
00105     mSprites.append(boardHole);
00106     mBoardHoles.append(boardHole);
00107     boardHole->hide();
00108   }
00109 
00110   // Create score board
00111   mScoreBoard = new ScoreSprite("scoreboard", mTheme, mAdvancePeriod, 0, mScene);
00112   if (!mScoreBoard) kFatal() << "Cannot load sprite " << "scoreboard" << endl;
00113   mSprites.append(mScoreBoard);
00114   mScoreBoard->hide();
00115 
00116 
00117   // Create movement indication arrows
00118   for (int i=0; i<7; i++)
00119   {
00120     PixmapSprite* arrow = new PixmapSprite("arrow", mTheme, mAdvancePeriod, i, mScene);
00121     if (!arrow) kFatal() << "Cannot load sprite " << "arrow" << endl;
00122     mSprites.append(arrow);
00123     mArrows.append(arrow);
00124     arrow->hide();
00125   }
00126 
00127   // Animation timer
00128   mTimer = new QTimer(this);
00129   connect(mTimer, SIGNAL(timeout()), this, SLOT(advance()));
00130 
00131   // Redraw
00132   if (theme) theme->updateTheme(this);
00133 
00134 }
00135 
00136 
00137 // Destructor: clean up
00138 DisplayGame::~DisplayGame()
00139 {
00140   delete mTimer;
00141   while (!mSprites.isEmpty())
00142   {
00143     delete mSprites.takeFirst();
00144   }
00145 }
00146 
00147 
00148 // Called by thememanager when theme or theme geometry changes. Redraw and resize
00149 // this display.
00150 void DisplayGame::changeTheme()
00151 {
00152   // Retrieve theme data
00153   KConfigGroup config = thememanager()->config(id());
00154 
00155   // Retrieve background pixmap
00156   QString bgsvgid = config.readEntry("background-svgid");
00157   QPixmap pixmap  = thememanager()->getPixmap(bgsvgid, mScene->sceneRect().size().toSize());
00158   mScene->setBackgroundBrush(pixmap);
00159   mView->update();
00160 
00161 }
00162 
00163 
00164 // Start a new game. Initialize graphics.
00165 void DisplayGame::start()
00166 {
00167         // Run timer (unused)
00168   // mTimer->setSingleShot(true);
00169   // mTimer->start(0);
00170 
00171   // Retrieve theme data
00172   KConfigGroup config = thememanager()->config(id());
00173   QPointF board_pos    = config.readEntry("board-pos", QPointF(1.0,1.0));
00174   QPointF arrow_pos    = config.readEntry("arrow-pos", QPointF(1.0,1.0));
00175   QPointF board_spread = config.readEntry("board-spread", QPointF(1.0,1.0));
00176 
00177   // Show decoration
00178   mBoard->show();
00179   mScoreBoard->show();
00180 
00181   // Show board holes
00182   for (int i=0; i<42; i++)
00183   {
00184     int x = i/6;
00185     int y = i%6;
00186     QPointF to   = QPointF(board_spread.x()*x + board_pos.x(),
00187                            board_spread.y()*y + board_pos.y());
00188     mBoardHoles.value(i)->setPosition(to);
00189     mBoardHoles.value(i)->show();
00190   }
00191 
00192   // Show movement arrows
00193   for (int i=0; i<7; i++)
00194   {
00195     QPointF to   = QPointF(board_spread.x()*i + arrow_pos.x(),
00196                            board_spread.y()*0 + arrow_pos.y());
00197     mArrows.value(i)->setPosition(to);
00198     mArrows.value(i)->setFrame(0);
00199     mArrows.value(i)->show();
00200   }
00201 
00202   // Hide piece sprites 
00203   for (int i=0; i<42; i++)
00204   {
00205     mPieces.value(i)->hide();
00206   }
00207   
00208   // Hide stars
00209   for (int i=0;i<4;i++)
00210   {
00211     mStars.value(i)->setAnimation(false);
00212     mStars.value(i)->hide();
00213   }
00214 
00215   // Hide game over
00216   mGameOver->hide();
00217 }
00218 
00219 
00220 // Run game animation
00221 void DisplayGame::advance()
00222 {
00223          // Currently unused
00224 }
00225 
00226 
00227 // Display end game sprite
00228 void DisplayGame::displayEnd()
00229 {
00230         assert(mGameOver != 0);
00231   mGameOver->show();
00232 }
00233 
00234 
00235 // Set the movement indicator arrows above the game board
00236 void DisplayGame::displayArrow(int x,int color)
00237 {
00238   // Set all arrows back to frame 0
00239   for (int i=0; i<7; i++)
00240   {
00241     mArrows.value(i)->setFrame(0);
00242   }
00243 
00244   // Check for no color 
00245   if (color==Nobody)
00246   {
00247     return ;
00248   }
00249 
00250   // Make sure the frames are chosen properly
00251   if (color==Yellow) mArrows.value(x)->setFrame(1);
00252   else mArrows.value(x)->setFrame(2);
00253 }
00254 
00255 
00256 // Set a game HINT sprite
00257 void DisplayGame::displayHint(int x, int y, bool show)
00258 {
00259   // Invert height
00260   y=5-y;
00261 
00262   // Check for removal of the sprite
00263   if (!show)
00264   {
00265     mHint->hide();
00266     return;
00267   }
00268 
00269   // Retrieve theme data
00270   KConfigGroup config   = thememanager()->config(id());
00271   QPointF board_pos     = config.readEntry("board-pos", QPointF(1.0,1.0));
00272   QPointF board_spread  = config.readEntry("board-spread", QPointF(1.0,1.0));
00273 
00274   QPointF to   = QPointF(board_spread.x()*x + board_pos.x(),
00275                          board_spread.y()*y + board_pos.y());
00276   mHint->setPosition(to);
00277   mHint->show();
00278 }
00279 
00280 
00281 // Set a game piece, red or yellow or hidden depending on 'color'
00282 SpriteNotify* DisplayGame::displayPiece(int x, int y, int color, int no, bool animation)
00283 {
00284   // Invert height
00285   y=5-y;
00286 
00287   // Get piece
00288   PieceSprite *sprite = mPieces.value(no);
00289   assert(sprite != 0);
00290 
00291   // Check for removal of sprite
00292   if (color==Nobody)
00293   {
00294     sprite->hide();
00295     return 0;
00296   }
00297 
00298   // Retrieve theme data
00299   KConfigGroup config   = thememanager()->config(id());
00300   QPointF board_pos     = config.readEntry("board-pos", QPointF(1.0,1.0));
00301   QPointF board_spread  = config.readEntry("board-spread", QPointF(1.0,1.0));
00302   double velocity       = config.readEntry("move-velocity", 0.1);
00303 
00304   // Make sure the frames are ok
00305   int frame;
00306   if (color==Yellow) frame = 0;
00307   else frame = 1;
00308 
00309 
00310   // Just draw the sprites or show an movement animation?
00311   if (animation)
00312   {
00313     QPointF from = QPointF(board_spread.x()*x    + board_pos.x(),
00314                            board_spread.y()*(-1) + board_pos.y());
00315     QPointF to   = QPointF(board_spread.x()*x    + board_pos.x(),
00316                            board_spread.y()*y    + board_pos.y());
00317     sprite->setFrame(frame);
00318     sprite->startLinear(from, to, velocity);
00319   }
00320   else
00321   {
00322     QPointF to   = QPointF(board_spread.x()*x + board_pos.x(),
00323                            board_spread.y()*y + board_pos.y());
00324     sprite->setFrame(frame);
00325     sprite->setPosition(to);
00326   }
00327 
00328   sprite->show();
00329   return sprite->notify();
00330 }
00331 
00332 
00333 // Return the mouse mapped to the board or bar item so that a
00334 // move 0..6 is generated. -1 means an illegal position.
00335 int DisplayGame::mapMouseToMove(QPoint pos)
00336 {
00337   // Error?
00338   if (!mBoard) return -1;
00339 
00340   // Find which arrow the mouse is closest to. This way
00341   // all board scaling become irrelevant. An alteratnive
00342   // would be to calculate the position using board_pos and
00343   // board_spread.
00344   for (int i=0; i<7; i++)
00345   {
00346     PixmapSprite* arrow = mArrows.value(i);
00347     int width           = int(arrow->boundingRect().width());
00348     int relPos          = int(arrow->mapFromParent(QPointF(pos)).x());
00349     // Found matching arrow
00350     if (relPos > 0 && relPos<= width)
00351     {
00352       return i;
00353     }
00354   }
00355 
00356   // Nothing found
00357   return -1;
00358 }
00359 
00360 
00361 // Draw Star Sprites as winning indicator
00362 void DisplayGame::displayStar(int x,int y,int no)
00363 {
00364         // Invert height
00365   y=5-y;
00366   PixmapSprite* star = mStars.value(no-1);
00367   assert(star != 0);
00368 
00369   // Retrieve theme data
00370   KConfigGroup config  = thememanager()->config(id());
00371   QPointF board_pos    = config.readEntry("board-pos", QPointF(1.0,1.0));
00372   QPointF board_spread = config.readEntry("board-spread", QPointF(1.0,1.0));
00373   //double velocity      = config.readEntry("move-velocity", 0.1);
00374 
00375   QPointF pos  = QPointF(board_spread.x()*x    + board_pos.x(),
00376                          board_spread.y()*y    + board_pos.y());
00377   star->setAnimation(true);
00378   star->setPosition(pos);
00379   star->show();
00380 }
00381 
00382 
00383 // Retrieve the score sprite.
00384 ScoreSprite* DisplayGame::score()
00385 {
00386   return mScoreBoard;
00387 }
00388 
00389 
00390 #include "displaygame.moc"

Generated on Sun Mar 4 10:56:43 2007 for KWin4 by  doxygen 1.4.6