#include "board.h" #include "board.moc" #include #include #include #include "piece.h" #include "factory.h" #include "baseprefs.h" using namespace KGrid2D; //----------------------------------------------------------------------------- FixedCanvasView::FixedCanvasView(TQWidget *parent, const char *name) : TQCanvasView(parent, name, WNoAutoErase) {} TQSize FixedCanvasView::sizeHint() const { if ( canvas()==0 ) return TQSize(); return canvas()->size() + 2 * TQSize(frameWidth(), frameWidth()); } void FixedCanvasView::adjustSize() { setFixedSize(sizeHint()); } //----------------------------------------------------------------------------- const BaseBoard::DirectionData BaseBoard::DIRECTION_DATA[Nb_Direction] = { { SquareBase::Left, Left }, { SquareBase::Right, Right }, { SquareBase::Down, Up }, { SquareBase::Up, Down } }; BaseBoard::BaseBoard(bool graphic, TQWidget *parent) : FixedCanvasView(parent, "board"), GenericTetris(bfactory->bbi.width, bfactory->bbi.height, bfactory->bbi.withPieces, graphic), state(GameOver), timer(this), sequences(0), main(0), _next(0), _arcade(false) { if (graphic) { setVScrollBarMode(AlwaysOff); setHScrollBarMode(AlwaysOff); setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); sequences = new SequenceArray; main = new BlockInfo(*sequences); setCanvas(main); if (bfactory->bbi.withPieces) _next = new BlockInfo(*sequences); setBlockInfo(main, _next); connect(&timer, TQT_SIGNAL(timeout()), TQT_SLOT(timeout())); Piece::info().loadColors(); KZoomMainWindow::addWidget(this); } } void BaseBoard::copy(const GenericTetris &g) { GenericTetris::copy(g); state = static_cast(g).state; } void BaseBoard::settingsChanged() { Q_ASSERT( graphic() ); Piece::info().loadColors(); } void BaseBoard::adjustSize() { int size = BasePrefs::blockSize(); sequences->setBlockSize(size); main->resize(matrix().width() * size, matrix().height() * size); for (uint i=0; iresize(c.first * size, c.second * size); _nextPiece->moveCenter(); } FixedCanvasView::adjustSize(); } BaseBoard::~BaseBoard() { if ( graphic() ) { setBlockInfo(0, 0); // destruct all sprites before deleting canvas delete _next; delete main; delete sequences; } } void BaseBoard::init(bool arcade) { _arcade = arcade; _arcadeStageDone = false; } void BaseBoard::start(const GTInitData &data) { Q_ASSERT( graphic() ); if ( !_arcadeStageDone || _arcadeStage==bfactory->bbi.nbArcadeStages ) _arcadeStage = 0; _arcadeStageDone = false; state = Normal; GenericTetris::start(data); // NB: the timer is started by updateLevel ! if (_arcade) arcadePrepare(); } void BaseBoard::stop() { timer.stop(); state = GameOver; } void BaseBoard::pause() { Q_ASSERT( graphic() ); timer.stop(); _oldState = state; state = Paused; showBoard(false); } void BaseBoard::gameOver() { stop(); emit gameOverSignal(); } void BaseBoard::showCanvas(TQCanvas *c, bool show) { TQCanvasItemList l = c->allItems(); TQCanvasItemList::Iterator it; for (it=l.begin(); it!=l.end(); ++it) { if (show) (*it)->show(); else (*it)->hide(); } c->update(); } void BaseBoard::showBoard(bool show) { showCanvas(main, show); } void BaseBoard::unpause() { Q_ASSERT( graphic() ); showBoard(true); state = _oldState; startTimer(); } void BaseBoard::updateRemoved(uint newRemoved) { GenericTetris::updateRemoved(newRemoved); emit removedUpdated(); } void BaseBoard::updateScore(uint newScore) { GenericTetris::updateScore(newScore); emit scoreUpdated(); } int BaseBoard::firstColumnBlock(uint col) const { for (int j=firstClearLine()-1; j>=0; j--) { Coord c(col, j); if ( matrix()[c]!=0 ) return j; } return -1; } //----------------------------------------------------------------------------- void BaseBoard::_beforeRemove(bool first) { if ( graphic() ) { state = ( beforeRemove(first) ? BeforeRemove : Normal ); if ( state==BeforeRemove ) { startTimer(); return; } } remove(); _afterRemove(true); } void BaseBoard::remove() { for (uint j=0; jupdate(); KNotifyClient::event(winId(), "removed", i18n("Blocks removed")); } } bool BaseBoard::doFall(bool doAll, bool first, bool lineByLine) { Q_ASSERT( !lineByLine || !doAll ); if ( !doAll ) { if (first) loop = 0; else loop++; } bool final = (doAll || lineByLine || loop==bfactory->bbi.nbFallStages); for (uint i=0; i heights(matrix().height()); for (uint j=1; j=arcadeTodo() ) { _arcadeStage++; _arcadeStageDone = true; gameOver(); return; } if ( !afterAfterRemove() ) gameOver(); else if ( graphic() ) startTimer(); } bool BaseBoard::timeout() { Q_ASSERT( graphic() ); if ( state==GameOver ) return true; switch (state) { case BeforeRemove: _beforeRemove(FALSE); break; case AfterRemove: _afterRemove(FALSE); break; default: return false; } main->update(); return true; } bool BaseBoard::startTimer() { Q_ASSERT( graphic() ); if ( state==GameOver ) return true; switch (state) { case BeforeRemove: timer.start(bfactory->bbi.beforeRemoveTime, true); break; case AfterRemove: timer.start(bfactory->bbi.afterRemoveTime, true); break; default: return false; } return true; } bool BaseBoard::beforeRemove(bool first) { if (first) loop = 0; else loop++; for (uint j=0; jtoggleLight(); } return ( loop!=bfactory->bbi.nbToggles ); } //----------------------------------------------------------------------------- void BaseBoard::partialBlockFall(const Coord &src, const Coord &dest) { Q_ASSERT( loopbbi.nbFallStages ); float c = float(loop+1) / bfactory->bbi.nbFallStages * BasePrefs::blockSize(); int xdec = dest.first - src.first; int ydec = src.second - dest.second; TQPoint p(int(xdec * c), int(ydec * c)); partialMoveBlock(src, p); } uint BaseBoard::findGroup(Square &field, const Coord &c) const { uint nb = 0; _findGroup(field, c, nb, false); return nb; } void BaseBoard::setGroup(Square &field, const Coord &c, uint nb) const { _findGroup(field, c, nb, true); } void BaseBoard::_findGroup(Square &field, const Coord &c, uint &nb, bool set) const { if (!set) nb++; field[c] = (set ? (int)nb : -1); uint value = matrix()[c]->value(); CoordList n = matrix().neighbours(c, true, true); for (CoordList::const_iterator i = n.begin(); i!=n.end(); ++i) blockInGroup(field, *i, value, nb, set); } void BaseBoard::blockInGroup(Square &field, const Coord &c, uint value, uint &nb, bool set) const { if ( matrix()[c]==0 ) return; if ( matrix()[c]->value()!=value ) return; if ( field[c]!=(set ? -1 : 0) ) return; _findGroup(field, c, nb, set); } TQMemArray BaseBoard::findGroups(Square &field, uint minSize, bool exitAtFirstFound) const { field.fill(0); TQMemArray groups; for (uint j=0; jisGarbage() ) continue; if ( field[c]!=0 ) continue; uint nb = findGroup(field, c); setGroup(field, c, nb); if ( nb>=minSize ) { uint s = groups.size(); groups.resize(s+1); groups[s] = nb; if (exitAtFirstFound) return groups; } } return groups; } uint BaseBoard::drawCode(const Coord &c) const { uint v = matrix()[c]->value(); uint code = 0; for (uint i=0; ivalue()!=v ) continue; code |= DIRECTION_DATA[i].direction; } return code; } void BaseBoard::computeNeighbours() { for (uint j=0; jisGarbage() ) continue; matrix()[c]->sprite()->setFrame( drawCode(c) ); } }