summaryrefslogtreecommitdiffstats
path: root/kpat/card.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kpat/card.cpp')
-rw-r--r--kpat/card.cpp380
1 files changed, 380 insertions, 0 deletions
diff --git a/kpat/card.cpp b/kpat/card.cpp
new file mode 100644
index 00000000..983a901d
--- /dev/null
+++ b/kpat/card.cpp
@@ -0,0 +1,380 @@
+/******************************************************
+
+ Card.cpp -- support classes for patience type card games
+
+ Copyright (C) 1995 Paul Olav Tvete
+
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * This file is provided AS IS with no warranties of any kind. The author
+ * shall have no liability with respect to the infringement of copyrights,
+ * trade secrets or any patents by this file or any part thereof. In no
+ * event will the author be liable for any lost revenue or profits or
+ * other special, indirect and consequential damages.
+
+*******************************************************/
+
+#include <math.h>
+#include <assert.h>
+
+#include <qpainter.h>
+
+#include <kdebug.h>
+
+#include "card.h"
+#include "pile.h"
+#include "cardmaps.h"
+
+
+static const char *suit_names[] = {"Clubs", "Diamonds", "Hearts", "Spades"};
+static const char *rank_names[] = {"Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight",
+ "Nine", "Ten", "Jack", "Queen", "King" };
+
+// Run time type id
+const int Card::RTTI = 1001;
+
+
+Card::Card( Rank r, Suit s, QCanvas* _parent )
+ : QCanvasRectangle( _parent ),
+ m_suit( s ), m_rank( r ),
+ m_source(0), scaleX(1.0), scaleY(1.0), tookDown(false)
+{
+ // Set the name of the card
+ // FIXME: i18n()
+ m_name = QString("%1 %2").arg(suit_names[s-1]).arg(rank_names[r-1]).utf8();
+
+ // Default for the card is face up, standard size.
+ m_faceup = true;
+ setSize( cardMap::CARDX(), cardMap::CARDY() );
+
+ m_destX = 0;
+ m_destY = 0;
+ m_destZ = 0;
+
+ m_flipping = false;
+ m_animSteps = 0;
+ m_flipSteps = 0;
+}
+
+
+Card::~Card()
+{
+ // If the card is in a pile, remove it from there.
+ if (source())
+ source()->remove(this);
+
+ hide();
+}
+
+
+// ----------------------------------------------------------------
+// Member functions regarding graphics
+
+
+// Return the pixmap of the card
+//
+QPixmap Card::pixmap() const
+{
+ return cardMap::self()->image( m_rank, m_suit );
+}
+
+
+// Turn the card if necessary. If the face gets turned up, the card
+// is activated at the same time.
+//
+void Card::turn( bool _faceup )
+{
+ if (m_faceup != _faceup) {
+ m_faceup = _faceup;
+ setActive(!isActive()); // abuse
+ }
+}
+
+// Draw the card on the painter 'p'.
+//
+void Card::draw( QPainter &p )
+{
+ QPixmap side;
+
+ // Get the image to draw (front / back)
+ if( isFaceUp() )
+ side = cardMap::self()->image( m_rank, m_suit, isSelected());
+ else
+ side = cardMap::self()->backSide();
+
+ // Rescale the image if necessary.
+ if (scaleX <= 0.98 || scaleY <= 0.98) {
+ QWMatrix s;
+ s.scale( scaleX, scaleY );
+ side = side.xForm( s );
+ int xoff = side.width() / 2;
+ int yoff = side.height() / 2;
+ p.drawPixmap( int(x() + cardMap::CARDX()/2 - xoff),
+ int(y() + cardMap::CARDY()/2 - yoff), side );
+ } else
+ p.drawPixmap( int(x()), int(y()), side );
+}
+
+
+void Card::moveBy(double dx, double dy)
+{
+ QCanvasRectangle::moveBy(dx, dy);
+}
+
+
+// Return the X of the cards real position. This is the destination
+// of the animation if animated, and the current X otherwise.
+//
+int Card::realX() const
+{
+ if (animated())
+ return m_destX;
+ else
+ return int(x());
+}
+
+
+// Return the Y of the cards real position. This is the destination
+// of the animation if animated, and the current Y otherwise.
+//
+int Card::realY() const
+{
+ if (animated())
+ return m_destY;
+ else
+ return int(y());
+}
+
+
+// Return the > of the cards real position. This is the destination
+// of the animation if animated, and the current Z otherwise.
+//
+int Card::realZ() const
+{
+ if (animated())
+ return m_destZ;
+ else
+ return int(z());
+}
+
+
+// Return the "face up" status of the card.
+//
+// This is the destination of the animation if animated and animation
+// is more than half way, the original if animated and animation is
+// less than half way, and the current "face up" status otherwise.
+//
+
+bool Card::realFace() const
+{
+ if (animated() && m_flipping) {
+ bool face = isFaceUp();
+ if ( m_animSteps >= m_flipSteps / 2 - 1 )
+ return !face;
+ else
+ return face;
+ } else
+ return isFaceUp();
+}
+
+
+/// the following copyright is for the flipping code
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qt Palmtop 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.
+**
+**********************************************************************/
+
+
+// Used to create an illusion of the card being lifted while flipped.
+static const double flipLift = 1.2;
+
+// The current maximum Z value. This is used so that new cards always
+// get placed on top of the old ones and don't get placed in the
+// middle of a destination pile.
+int Card::Hz = 0;
+
+
+void Card::setZ(double z)
+{
+ QCanvasRectangle::setZ(z);
+ if (z > Hz)
+ Hz = int(z);
+}
+
+
+// Start a move of the card using animation.
+//
+// 'steps' is the number of steps the animation should take.
+//
+void Card::moveTo(int x2, int y2, int z2, int steps)
+{
+ m_destX = x2;
+ m_destY = y2;
+ m_destZ = z2;
+
+ double x1 = x();
+ double y1 = y();
+ double dx = x2 - x1;
+ double dy = y2 - y1;
+
+ if (!dx && !dy) {
+ setZ(z2);
+ return;
+ }
+ setZ(Hz++);
+
+ if (steps) {
+ // Ensure a good speed
+ while ( fabs(dx/steps)+fabs(dy/steps) < 5.0 && steps > 4 )
+ steps--;
+
+ setAnimated(true);
+ setVelocity(dx/steps, dy/steps);
+
+ m_animSteps = steps;
+
+ } else {
+ // _really_ fast
+ setAnimated(true);
+ setAnimated(false);
+ emit stoped(this);
+ }
+}
+
+
+// Animate a move to (x2, y2), and at the same time flip the card.
+//
+void Card::flipTo(int x2, int y2, int steps)
+{
+ // Check that we are not already animating.
+ assert(!animated());
+
+ int x1 = (int)x();
+ int y1 = (int)y();
+ double dx = x2 - x1;
+ double dy = y2 - y1;
+
+ // Mark this animation as a flip as well.
+ m_flipping = true;
+ m_flipSteps = steps;
+
+ // Set the target of the animation
+ m_destX = x2;
+ m_destY = y2;
+ m_destZ = int(z());
+
+ // Let the card be above all others during the animation.
+ setZ(Hz++);
+
+ m_animSteps = steps;
+ setVelocity(dx/m_animSteps, dy/m_animSteps-flipLift);
+
+ setAnimated(TRUE);
+}
+
+
+// Advance a card animation one step. This function adds flipping of
+// the card to the translation animation that QCanvasRectangle offers.
+//
+void Card::advance(int stage)
+{
+ if ( stage==1 ) {
+ // If the animation is finished, emit stoped. (FIXME: name)
+ if ( m_animSteps-- <= 0 ) {
+ setAnimated(false);
+ emit stoped(this);
+ } else {
+ // Animation is not finished. Check for flipping and add
+ // that animation to the simple translation.
+ if ( m_flipping ) {
+ if ( m_animSteps > m_flipSteps / 2 ) {
+ // animSteps = flipSteps .. flipSteps/2 (flip up) -> 1..0
+ scaleX = ((double)m_animSteps/m_flipSteps-0.5)*2;
+ } else {
+ // animSteps = flipSteps/2 .. 0 (flip down) -> 0..1
+ scaleX = 1-((double)m_animSteps/m_flipSteps)*2;
+ }
+ if ( m_animSteps == m_flipSteps / 2-1 ) {
+ setYVelocity(yVelocity()+flipLift*2);
+ turn( !isFaceUp() );
+ }
+ }
+ }
+ }
+
+ // Animate the translation of the card.
+ QCanvasRectangle::advance(stage);
+}
+
+
+// Set 'animated' status to a new value, and set secondary values as
+// well.
+//
+void Card::setAnimated(bool anim)
+{
+ // If no more animation, reset some other values as well.
+ if (animated() && !anim) {
+ // Reset all things that might have changed during the animation.
+ scaleX = 1.0;
+ scaleY = 1.0;
+ m_flipping = FALSE;
+ setVelocity(0, 0);
+
+ // Move the card to its destination immediately.
+ move(m_destX, m_destY);
+ setZ(m_destZ);
+ }
+
+ QCanvasRectangle::setAnimated(anim);
+}
+
+
+void Card::setTakenDown(bool td)
+{
+ if (td)
+ kdDebug(11111) << "took down " << name() << endl;
+ tookDown = td;
+}
+
+
+bool Card::takenDown() const
+{
+ return tookDown;
+}
+
+
+// Get the card to the top.
+
+void Card::getUp(int steps)
+{
+ m_destZ = int(z());
+ m_destX = int(x());
+ m_destY = int(y());
+ setZ(Hz+1);
+
+ // Animation
+ m_animSteps = steps;
+ setVelocity(0, 0);
+ setAnimated(TRUE);
+}
+
+#include "card.moc"