canvascardgame.cpp
来自「Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3」· C++ 代码 · 共 455 行
CPP
455 行
/************************************************************************ Copyright (C) 2000-2005 Trolltech AS. All rights reserved.**** This file is part of the Qtopia Environment.** ** 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.** ** A copy of the GNU GPL license version 2 is included in this package as ** LICENSE.GPL.**** 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.**** In addition, as a special exception Trolltech gives permission to link** the code of this program with Qtopia applications copyrighted, developed** and distributed by Trolltech under the terms of the Qtopia Personal Use** License Agreement. You must comply with the GNU General Public License** in all respects for all of the code used other than the applications** licensed under the Qtopia Personal Use License Agreement. If you modify** this file, you may extend this exception to your version of the file,** but you are not obligated to do so. If you do not wish to do so, delete** this exception statement from your version.** ** 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 <qtopia/config.h>#include <qtopia/global.h>#include <qtopia/contextbar.h>#include <qmessagebox.h>#include <stdlib.h>#include "canvasshapes.h"#include "canvascard.h"#include "canvascardgame.h"#include "canvascardpile.h"#include "cardmetrics.h"#include "canvasitemtimer.h"CanvasCardGame::CanvasCardGame(QCanvas *c, QCanvasView *view, bool snap, bool casinoRules) : QObject(view), moving(0), alphaCardPile(c), cardOffset(0,0), canvasPtr(c), canvasView(view), state(SelectingCard), selectingCardRect(QPoint(0, 0), c), selectingCardRectGhost(QPoint(0, 0), c), casino(casinoRules), snapOn(snap), numberToDraw(1){ selectingCardRect.setSelectionMode(CanvasRoundRect::enabledSelection); selectingCardRect.setZ(INT_MAX - 20); selectingCardRectGhost.setSelectionMode(CanvasRoundRect::partiallySelected); selectingCardRectGhost.setZ(INT_MAX - 21); alphaCardPile.hide(); alphaCardPile.setZ(INT_MAX - 30); connect(&alphaCardPile,SIGNAL(finished()),this,SLOT(doneMoving())); selectingCard = 0; selectingCardI = 0; selectingPileI = -1;}CanvasCardGame::~CanvasCardGame(){}void CanvasCardGame::gameWon(){ ((CanvasCardView *)canvasView)->setZoomViewEnabled(FALSE); ((CanvasCardView *)canvasView)->showWinText(TRUE); 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 = (rand() % (canvas()->width() * 2)) - (canvas()->width()/2); int y = canvas()->height() + (rand() % (canvas()->height() / 3)); ((CanvasCard *)*it)->moveTo(QPoint(x, y), 3000); } }}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 ) { CanvasCard *card = (CanvasCard *)*it; if ( card->isFlipping() ) continue; selectingCardI = find(card->cardPile()) - 1; selectingCard = card; state = SelectingPile; if ( cardSelected(card) ) { alphaCardPile.hide(); resetCardSelection(CurrentCard); } else { beginMovingCards(card); cardOffset = e->pos() - card->pos(); updateCurSelectingCard(); } return; } } for (CardPile *p = first(); p; p = next()) { if (p->pileRect().contains(e->pos())) { if (pileSelected(p)) { selectingCardI = find(p) - 1; selectingCard = 0; state = SelectingPile; resetCardSelection(CurrentCard); return; } } }}// ### Should have some intelligent way to make double clicking on a// card send it to the most appropriate pilevoid CanvasCardGame::contentsMouseDoubleClickEvent(QMouseEvent *e){ QCanvasItemList l = canvas()->collisions( e->pos() ); for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) { if ( (*it)->rtti() == canvasCardId ) {// autoMove((Card *)*it); } }}void CanvasCardGame::contentsMouseMoveEvent(QMouseEvent *e){ updateMovingCards(e->pos() - cardOffset);}void CanvasCardGame::contentsMouseReleaseEvent(QMouseEvent *){ endMovingCards();}void CanvasCardGame::beginMovingCards(CanvasCard *card){ if ( moving ) return; moving = card; alphaCardPile.addCards(moving); alphaCardPile.show(); cardOffset = QPoint(0,0);}void CanvasCardGame::updateMovingCards(QPoint pnt){ if ( !moving ) return; if ( snapOn ) { CardPile *pile = closestPile(pnt, CardMetrics::width()/2); if ( pile && pile->isAllowedOnTop(moving) ) pnt = pile->hypertheticalNextCardPos(); } alphaCardPile.setPos(pnt);}void CanvasCardGame::cancelMovingCards(){ alphaCardPile.animatedMove(); resetCardSelection(Last);}void CanvasCardGame::endMovingCards(){ // Check it is okay to be here if ( !moving ) return; CardPile *pile = closestPile(alphaCardPile.pos(), CardMetrics::width() / 2); CardPile *oldPile = moving->cardPile(); // Will it be valid to move here or should we reject and reset this move if ( !pile || !pile->isAllowedOnTop(moving) || oldPile == pile ) { cancelMovingCards(); return; } // If it is valid, start moving the cards to the new pile Card *item = moving; while ( item ) { Card *next = 0; item->setVisible(true); if ( oldPile ) { next = oldPile->cardInfront(item); oldPile->removeCard(item); } pile->addCardToTop(item); item = next; } selectingPileI = find(pile) - 1; // Finish up and check if this move causes us to win the game alphaCardPile.hide(); moving = 0; if ( haveWeWon() ) gameWon(); resetCardSelection(CurrentPile);}void CanvasCardGame::doneMoving(){ moving = 0; updateSelectionRects(); emit(moveFinished());}CanvasCardPile *CanvasCardGame::canvasCardPileFromInt( int pile ){ // pile+1 to take into account invisible dealing pile return (CanvasCardPile*)at(pile+1);}void CanvasCardGame::resetCardSelection( Movement movement ){#ifdef QTOPIA_PHONE ContextBar::setLabel(canvasView, Key_Back, ContextBar::Back, ContextBar::Modal);#endif switch ( movement ) { case CurrentCard: selectingCard = 0; break; case CurrentPile: selectingCard = 0; selectingCardI = selectingPileI; break; case Last: selectingPileI = selectingCardI; break; } updateCurSelectingCard(); state = SelectingCard;}void CanvasCardGame::updateSelectionRects(){ switch ( state ) { case SelectingCard: updateCurSelectingCard(); break; case SelectingPile: updateCurSelectingPile(); break; default: break; }}void CanvasCardGame::updateCurSelectingCard(){ int h = 0; if ( !selectingCard ) selectingCard = canvasCardPileFromInt(selectingCardI)->cardOnTop(); selectingCardRect.setSelectionMode(CanvasRoundRect::enabledSelection); if ( selectingCard ) { Card *prevCard2 = selectingCard; Card *nextCard2 = CardPile::cardInfront(prevCard2); while ( nextCard2 ) { prevCard2 = nextCard2; nextCard2 = CardPile::cardInfront(prevCard2); } h = prevCard2->pos().y() - selectingCard->pos().y(); selectingCardRect.setPos(selectingCard->pos()); if ( !selectingCard->canBeMoved() ) selectingCardRect.setSelectionMode(CanvasRoundRect::disabledSelection); } else { selectingCardRect.setPos(canvasCardPileFromInt(selectingCardI)->pos()); } selectingCardRect.setSize(CardMetrics::width(),CardMetrics::height()+h); selectingCardRectGhost.move(selectingCardRect.x(),selectingCardRect.y()); selectingCardRectGhost.setSize(CardMetrics::width(),CardMetrics::height()+h);}void CanvasCardGame::updateCurSelectingPile(){ QRect r = canvasCardPileFromInt(selectingPileI)->boundingRect(); int y = r.height() - CardMetrics::height(); int x = r.width() - CardMetrics::width(); if ( selectingCardI == selectingPileI ) { y += CardMetrics::height(); y -= alphaCardPile.height() + CardMetrics::offsetDown(); } selectingCardRect.setPos(QPoint(r.x()+x, r.y()+y)); updateMovingCards(r.topLeft()+QPoint(x,y));}void CanvasCardGame::setupSelectingPile(){ if ( moving ) return; if ( !pileSelected(canvasCardPileFromInt(selectingCardI)) ) {#ifdef QTOPIA_PHONE ContextBar::setLabel(canvasView, Key_Back, ContextBar::Cancel, ContextBar::Modal);#endif state = SelectingPile; if ( selectingCard && selectingCard->canBeMoved() ) { beginMovingCards((CanvasCard*)selectingCard); selectingPileI = selectingCardI; return; } } resetCardSelection(CurrentCard);}void CanvasCardGame::keyPressEvent(QKeyEvent *ke){ switch ( state ) { case SelectingCard: switch ( ke->key() ) { case Key_Left: selectingCard = 0; selectingCardI = pileForKey(selectingCardI,0); break; case Key_Right: selectingCard = 0; selectingCardI = pileForKey(selectingCardI,1); break; case Key_Up: if ( selectingCard ) selectingCard = CardPile::cardBehind(selectingCard); if ( !selectingCard || !selectingCard->isSelectable() ) { selectingCard = 0; selectingCardI = pileForKey(selectingCardI,2); } break; case Key_Down: if ( selectingCard ) selectingCard = CardPile::cardInfront(selectingCard); if ( !selectingCard || !selectingCard->isSelectable() ) { selectingCard = 0; selectingCardI = pileForKey(selectingCardI,3); } if ( !selectingCard ) { selectingCard = canvasCardPileFromInt(selectingCardI)->cardOnTop(); Card *next = selectingCard; while ( next && next->isSelectable() ) { selectingCard = next; next = CardPile::cardBehind(next); } } break;#ifdef QTOPIA_PHONE case Key_Back: case Key_No:#endif case Key_Escape: selectingCard = 0;#ifdef QTOPIA_PHONE // Causes app to be closed in phone mode if( !Global::mousePreferred() ) canvasView->setModalEditing(false); else ke->ignore();#endif return;#ifdef QTOPIA_PHONE case Key_Select:#endif case Key_Space: case Key_Enter: setupSelectingPile(); return; } updateCurSelectingCard(); return; case SelectingPile: switch ( ke->key() ) { case Key_Left: selectingPileI = pileForKey(selectingPileI,4); break; case Key_Right: selectingPileI = pileForKey(selectingPileI,5); break; case Key_Up: selectingPileI = pileForKey(selectingPileI,6); break; case Key_Down: selectingPileI = pileForKey(selectingPileI,7); break;#ifdef QTOPIA_PHONE case Key_Back: case Key_No:#endif case Key_Escape: cancelMovingCards(); return;#ifdef QTOPIA_PHONE case Key_Select:#endif case Key_Space: case Key_Enter: // Move moving pile to drop location or back to start loc. endMovingCards(); return; } updateCurSelectingPile(); return; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?