summaryrefslogtreecommitdiff
path: root/noncore/games/solitaire/canvascardgame.cpp
Side-by-side diff
Diffstat (limited to 'noncore/games/solitaire/canvascardgame.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/games/solitaire/canvascardgame.cpp380
1 files changed, 380 insertions, 0 deletions
diff --git a/noncore/games/solitaire/canvascardgame.cpp b/noncore/games/solitaire/canvascardgame.cpp
new file mode 100644
index 0000000..32635a0
--- a/dev/null
+++ b/noncore/games/solitaire/canvascardgame.cpp
@@ -0,0 +1,380 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "cardgame.h"
+#include "canvasshapes.h"
+#include "canvascard.h"
+#include "canvascardgame.h"
+
+#include <qpe/resource.h>
+#include <qpe/config.h>
+
+#include <qmainwindow.h>
+#include <qpe/qpemenubar.h>
+#include <qpainter.h>
+
+#include <stdlib.h>
+#include <limits.h>
+#include <time.h>
+#include <math.h>
+
+
+extern int highestZ;
+
+
+class CanvasCardPile : public QCanvasRectangle
+{
+public:
+ CanvasCardPile( CanvasCardGame *ccg, QCanvas *canvas ) : QCanvasRectangle( canvas ), parent( ccg ) {
+ pile = new QPixmap( 0, 0 );
+ pileHeight = 0;
+ firstCard = NULL;
+ }
+
+ void addCard( CanvasCard *card );
+ void advance(int stage);
+ void animatedMove() { animatedMove(savedX, savedY); }
+ void savePos(void) { savedX = (int)x(); savedY = (int)y(); }
+ void animatedMove(int x2, int y2, int steps = 7 );
+
+protected:
+ virtual void draw( QPainter& p );
+
+private:
+ CanvasCardGame *parent;
+ QPixmap *pile;
+ QImage tempImage32;
+ CanvasCard *firstCard;
+ int pileHeight;
+ int destX, destY;
+ int savedX, savedY;
+ int animSteps;
+};
+
+
+void CanvasCardPile::addCard( CanvasCard *card )
+{
+ if ( !firstCard )
+ firstCard = card;
+
+ int height = 36 + pileHeight * 13;
+ setSize( 23, height );
+ pile->resize( 23, height );
+ QPainter p( pile );
+ p.translate( -card->x(), -card->y() + pileHeight * 13 );
+ card->draw( p );
+ pileHeight++;
+
+ QImage tempImage;
+ tempImage = *pile;
+ tempImage32 = tempImage.convertDepth( 32 );
+ tempImage32.setAlphaBuffer( TRUE );
+ for ( int i = 0; i < tempImage32.width(); i++ )
+ for ( int j = 0; j < tempImage32.height(); j++ ) {
+ QRgb col = tempImage32.pixel( i, j );
+ int a = 255-j*220/tempImage32.height();
+ QRgb alpha = qRgba( qRed( col ), qGreen( col ), qBlue( col ), a );
+ tempImage32.setPixel( i, j, alpha );
+ }
+
+ QRgb alpha = qRgba( 0, 0, 0, 0 );
+ tempImage32.setPixel( 1, 0, alpha );
+ tempImage32.setPixel( 0, 0, alpha );
+ tempImage32.setPixel( 0, 1, alpha );
+
+ tempImage32.setPixel( 21, 0, alpha );
+ tempImage32.setPixel( 22, 0, alpha );
+ tempImage32.setPixel( 22, 1, alpha );
+ height--;
+ tempImage32.setPixel( 1, height, alpha );
+ tempImage32.setPixel( 0, height - 1, alpha );
+ tempImage32.setPixel( 0, height, alpha );
+
+ tempImage32.setPixel( 21, height, alpha );
+ tempImage32.setPixel( 22, height, alpha );
+ tempImage32.setPixel( 22, height - 1, alpha );
+}
+
+
+void CanvasCardPile::advance(int stage)
+{
+ if ( stage==1 ) {
+ if ( animSteps-- <= 0 ) {
+ CanvasCard *item = firstCard;
+ while (item) {
+ item->show();
+ item = (CanvasCard *)item->getCardPile()->cardInfront(item);
+ }
+ setVelocity(0,0);
+ setAnimated(FALSE);
+ parent->cancelMoving();
+ hide();
+ move(destX,destY); // exact
+ }
+ }
+ QCanvasRectangle::advance(stage);
+}
+
+
+void CanvasCardPile::animatedMove(int x2, int y2, int steps = 7 )
+{
+ destX = x2;
+ destY = y2;
+
+ double x1 = x(), y1 = y(), dx = x2 - x1, dy = y2 - y1;
+
+ // Ensure a good speed
+ while ( fabs(dx/steps)+fabs(dy/steps) < 5.0 && steps > 4 )
+ steps--;
+
+ setAnimated(TRUE);
+ setVelocity(dx/steps, dy/steps);
+
+ animSteps = steps;
+}
+
+
+void CanvasCardPile::draw( QPainter& p )
+{
+ int ix = (int)x(), iy = (int)y();
+ p.drawImage( ix, iy, tempImage32 );
+}
+
+
+CanvasCardGame::~CanvasCardGame() {
+ // the deletion stuff should be fixed now and only deletes
+ // items created by this CardGame. I haven't verified there are zero
+ // memory leaks yet
+ if ( alphaCardPile )
+ delete alphaCardPile;
+}
+
+
+void CanvasCardGame::gameWon() {
+
+ srand(time(NULL));
+
+ QCanvasItemList list = canvas()->allItems();
+ QCanvasItemList::Iterator it = list.begin();
+
+ for (; it != list.end(); ++it) {
+ if ( (*it)->rtti() == canvasCardId ) {
+ // disperse the cards everywhere
+ int x = 300 - rand() % 1000;
+ int y = 300 + rand() % 200;
+ ((CanvasCard *)*it)->animatedMove( x, y, 50 );
+ }
+ }
+}
+
+
+void CanvasCardGame::contentsMousePressEvent(QMouseEvent *e) {
+
+ if ( moving )
+ return;
+
+ QCanvasItemList l = canvas()->collisions( e->pos() );
+
+ for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
+
+ if ( (*it)->rtti() == canvasCardId ) {
+
+ moving = (CanvasCard *)*it;
+
+ if ( moving->animated() )
+ return;
+
+ cardXOff = (int)(e->pos().x() - moving->x());
+ cardYOff = (int)(e->pos().y() - moving->y());
+
+ if ( !mousePressCard( moving, e->pos() ) ) {
+ CanvasCard *card = moving;
+
+ if ( alphaCardPile )
+ delete alphaCardPile;
+
+ alphaCardPile = new CanvasCardPile( this, canvas() );
+ alphaCardPile->move( card->x(), card->y() );
+ alphaCardPile->savePos();
+ alphaCardPile->show();
+
+ while (card) {
+ alphaCardPile->addCard( card );
+ card->hide();
+ card = (CanvasCard *)card->getCardPile()->cardInfront(card);
+ }
+
+ alphaCardPile->setZ( INT_MAX );
+
+ moved = TRUE;
+ } else {
+ if ( alphaCardPile )
+ alphaCardPile->hide();
+ }
+ return;
+ }
+ }
+
+ mousePress( e->pos() );
+}
+
+/*
+//
+// Should have some intelligent way to make double clicking on a
+// card send it to the most appropriate pile
+//
+void CanvasCardGame::contentsMouseDoubleClickEvent(QMouseEvent *e) {
+ QCanvasItemList l = canvas()->collisions( e->pos() );
+ for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
+ if ( (*it)->rtti() == canvasCardId ) {
+ CanvasCard *card = (CanvasCard *)*it;
+
+ if ( card->animated() )
+ return;
+
+ if ( card->getCardPile()->isAllowedToBeMoved(card) ) {
+ if (card->getCardPile()->cardInfront(card) == NULL) {
+ CardPile *pile = first();
+ if (pile && pile->isAllowedOnTop(card)) {
+ // move card to this pile
+ return;
+ }
+ }
+ }
+ }
+ }
+}
+*/
+
+void CanvasCardGame::contentsMouseMoveEvent(QMouseEvent *e) {
+
+ QPoint p = e->pos();
+
+ if ( moving ) {
+
+ moved = TRUE;
+
+ if (moving->isFacing() != TRUE)
+ return;
+
+ int tx = (int)p.x() - cardXOff;
+ int ty = (int)p.y() - cardYOff;
+
+ if (snapOn == TRUE) {
+ CardPile *pile = closestPile( tx, ty, 50 );
+ if ( pile && pile->isAllowedOnTop( moving ) ) {
+ QPoint p = pile->getHypertheticalNextCardPos();
+ if ( alphaCardPile )
+ alphaCardPile->move( p.x(), p.y() );
+ return;
+ }
+ }
+
+ if ( alphaCardPile )
+ alphaCardPile->move( tx, ty );
+ }
+
+}
+
+
+void CanvasCardGame::contentsMouseReleaseEvent(QMouseEvent *e)
+{
+ QPoint p = e->pos();
+
+ Q_UNUSED(p);
+
+ if ( moving ) {
+
+ CanvasCard *item = moving;
+
+ if ( item->animated() )
+ return;
+
+ if ( alphaCardPile )
+ if ( moved ) {
+
+ CardPile *pile = closestPile((int)alphaCardPile->x(), (int)alphaCardPile->y(), 30);
+
+ if (pile && pile->isAllowedOnTop(item)) {
+ CardPile *oldPile = item->getCardPile();
+ Card *c = NULL;
+ if ( oldPile != pile) {
+ while ( item ) {
+ item->show();
+ if ( oldPile ) {
+ c = oldPile->cardInfront(item);
+ oldPile->removeCard(item);
+ }
+ pile->addCardToTop(item);
+ item->setCardPile(pile);
+ //item->move( pile->getCardPos(item) );
+ QPoint p = pile->getCardPos(item);
+ item->setPos( p.x(), p.y(), highestZ );
+ highestZ++;
+
+ if (item->getValue() == king && haveWeWon()) {
+ alphaCardPile->hide();
+ gameWon();
+ moving = NULL;
+ return;
+ }
+
+ if (oldPile) {
+ item = (CanvasCard *)c;
+ } else {
+ item = NULL;
+ }
+ }
+ alphaCardPile->hide();
+ moving = NULL;
+ return;
+ }
+ }
+
+ alphaCardPile->animatedMove();
+ }
+ }
+
+ moved = FALSE;
+}
+
+
+void CanvasCardGame::readPile( Config& cfg, CardPile *pile, QString name, int& highestZ )
+{
+ cfg.setGroup( name );
+ int numberOfCards = cfg.readNumEntry("NumberOfCards", 0);
+ Card *card = NULL;
+ for ( int i = 0; i < numberOfCards; i++ ) {
+ QString cardStr;
+ cardStr.sprintf( "%i", i );
+ int val = cfg.readNumEntry( "Card" + cardStr );
+ bool facing = cfg.readBoolEntry( "CardFacing" + cardStr );
+ card = cards[ val ];
+ card->setFace(facing);
+ pile->addCardToTop(card);
+ card->setCardPile(pile);
+ QPoint p = pile->getCardPos( card );
+ card->setPos( p.x(), p.y(), highestZ );
+ card->showCard();
+ highestZ++;
+ }
+}
+
+