/* * ksokoban - a Sokoban game for TDE * Copyright (C) 1998 Anders Widell * * 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. * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "PlayField.h" #include "ModalLabel.h" #include "LevelMap.h" #include "Move.h" #include "History.h" #include "PathFinder.h" #include "MapDelta.h" #include "MoveSequence.h" #include "StaticImage.h" #include "HtmlPrinter.h" #include "Bookmark.h" #include "LevelCollection.h" #include "PlayField.moc" PlayField::PlayField(TQWidget *parent, const char *name, WFlags f) : TQWidget(parent, name, f|WResizeNoErase), imageData_(0), lastLevel_(-1), moveSequence_(0), moveInProgress_(false), dragInProgress_(false), xOffs_(0), yOffs_(0), wheelDelta_(0), levelText_(i18n("Level:")), stepsText_(i18n("Steps:")), pushesText_(i18n("Pushes:")), statusFont_(TDEGlobalSettings::generalFont().family(), 18, TQFont::Bold), statusMetrics_(statusFont_) { setFocusPolicy(TQ_StrongFocus); setFocus(); setBackgroundMode(TQt::NoBackground); setMouseTracking(true); highlightX_ = highlightY_ = 0; KConfig *cfg = (TDEApplication::kApplication())->config(); cfg->setGroup("settings"); imageData_ = new StaticImage; animDelay_ = cfg->readNumEntry("animDelay", 2); if (animDelay_ < 0 || animDelay_ > 3) animDelay_ = 2; history_ = new History; background_.setPixmap(imageData_->background()); floor_ = TQBrush(TQColor(0x66,0x66,0x66)); levelMap_ = new LevelMap; mapDelta_ = new MapDelta(levelMap_); mapDelta_->end(); levelChange(); } PlayField::~PlayField() { KConfig *cfg = (TDEApplication::kApplication())->config(); cfg->setGroup("settings"); cfg->writeEntry("animDelay", animDelay_, true, false, false); delete mapDelta_; delete history_; delete levelMap_; delete imageData_; } void PlayField::changeCursor(const TQCursor* c) { if (cursor_ == c) return; cursor_ = c; if (c == 0) unsetCursor(); else setCursor(*c); } int PlayField::level() const { if (levelMap_ == 0) return 0; return levelMap_->level(); } const TQString & PlayField::collectionName() { static TQString error = "????"; if (levelMap_ == 0) return error; return levelMap_->collectionName(); } int PlayField::totalMoves() const { if (levelMap_ == 0) return 0; return levelMap_->totalMoves(); } int PlayField::totalPushes() const{ if (levelMap_ == 0) return 0; return levelMap_->totalPushes(); } void PlayField::levelChange() { stopMoving(); stopDrag(); history_->clear(); setSize(width(), height()); updateLevelXpm(); updateStepsXpm(); updatePushesXpm(); highlight(); } void PlayField::paintSquare(int x, int y, TQPainter &paint) { if (levelMap_->xpos() == x && levelMap_->ypos() == y) { if (levelMap_->goal(x, y)) imageData_->saveman(paint, x2pixel(x), y2pixel(y)); else imageData_->man(paint, x2pixel(x), y2pixel(y)); return; } if (levelMap_->empty(x, y)) { if (levelMap_->floor(x, y)) { if (levelMap_->goal(x, y)) imageData_->goal(paint, x2pixel(x), y2pixel(y)); else paint.fillRect(x2pixel(x), y2pixel(y), size_, size_, floor_); } else { paint.fillRect(x2pixel(x), y2pixel(y), size_, size_, background_); } return; } if (levelMap_->wall(x, y)) { imageData_->wall(paint, x2pixel(x), y2pixel(y), x+y*(MAX_X+1), levelMap_->wallLeft(x, y), levelMap_->wallRight(x, y)); return; } if (levelMap_->object(x, y)) { if (highlightX_ == x && highlightY_ == y) { if (levelMap_->goal(x, y)) imageData_->brightTreasure(paint, x2pixel(x), y2pixel(y)); else imageData_->brightObject(paint, x2pixel(x), y2pixel(y)); } else { if (levelMap_->goal(x, y)) imageData_->treasure(paint, x2pixel(x), y2pixel(y)); else imageData_->object(paint, x2pixel(x), y2pixel(y)); } return; } } void PlayField::paintDelta() { TQPainter paint(this); // the following line is a workaround for a bug in TQt 2.0.1 // (and possibly earlier versions) paint.setBrushOrigin(0, 0); for (int y=0; yheight(); y++) { for (int x=0; xwidth(); x++) { if (mapDelta_->hasChanged(x, y)) paintSquare(x, y, paint); } } } void PlayField::paintEvent(TQPaintEvent *e) { TQPainter paint(this); // the following line is a workaround for a bug in TQt 2.0.1 // (and possibly earlier versions) paint.setBrushOrigin(0, 0); paint.setClipRegion(e->region()); paint.setClipping(true); paintPainter(paint, e->rect()); } void PlayField::paintPainterClip(TQPainter &paint, int x, int y, int w, int h) { TQRect rect(x, y, w, h); paint.setClipRect(rect); paint.setClipping(true); paintPainter(paint, rect); } void PlayField::paintPainter(TQPainter &paint, const TQRect &rect) { if (size_ <= 0) return; int minx = pixel2x(rect.x()); int miny = pixel2y(rect.y()); int maxx = pixel2x(rect.x()+rect.width()-1); int maxy = pixel2y(rect.y()+rect.height()-1); if (minx < 0) minx = 0; if (miny < 0) miny = 0; if (maxx >= levelMap_->width()) maxx = levelMap_->width()-1; if (maxy >= levelMap_->height()) maxy = levelMap_->height()-1; { int x1, x2, y1, y2; y1 = y2pixel(miny); if (y1 > rect.y()) paint.fillRect(rect.x(), rect.y(), rect.width(), y1-rect.y(), background_); int bot=rect.y()+rect.height(); if (bot > height()-collRect_.height()) bot = height()-collRect_.height(); y2 = y2pixel(maxy+1); if (y2 < bot) paint.fillRect(rect.x(), y2, rect.width(), bot-y2, background_); x1 = x2pixel(minx); if (x1 > rect.x()) paint.fillRect(rect.x(), y1, x1-rect.x(), y2-y1, background_); x2 = x2pixel(maxx+1); if (x2 < rect.x()+rect.width()) paint.fillRect(x2, y1, rect.x()+rect.width()-x2, y2-y1, background_); // paint.eraseRect } for (int y=miny; y<=maxy; y++) { for (int x=minx; x<=maxx; x++) { paintSquare(x, y, paint); } } if (collRect_.intersects(rect)) paint.drawPixmap(collRect_.x(), collRect_.y(), collXpm_); if (ltxtRect_.intersects(rect)) paint.drawPixmap(ltxtRect_.x(), ltxtRect_.y(), ltxtXpm_); if (lnumRect_.intersects(rect)) paint.drawPixmap(lnumRect_.x(), lnumRect_.y(), lnumXpm_); if (stxtRect_.intersects(rect)) paint.drawPixmap(stxtRect_.x(), stxtRect_.y(), stxtXpm_); if (snumRect_.intersects(rect)) paint.drawPixmap(snumRect_.x(), snumRect_.y(), snumXpm_); if (ptxtRect_.intersects(rect)) paint.drawPixmap(ptxtRect_.x(), ptxtRect_.y(), ptxtXpm_); if (pnumRect_.intersects(rect)) paint.drawPixmap(pnumRect_.x(), pnumRect_.y(), pnumXpm_); } void PlayField::resizeEvent(TQResizeEvent *e) { setSize(e->size().width(), e->size().height()); } void PlayField::mouseMoveEvent(TQMouseEvent *e) { lastMouseXPos_ = e->x(); lastMouseYPos_ = e->y(); if (!dragInProgress_) return highlight(); int old_x = dragX_, old_y = dragY_; dragX_ = lastMouseXPos_ - mousePosX_; dragY_ = lastMouseYPos_ - mousePosY_; { int x = pixel2x(dragX_ + size_/2); int y = pixel2y(dragY_ + size_/2); if (x >= 0 && x < levelMap_->width() && y >= 0 && y < levelMap_->height() && pathFinder_.canDragTo(x, y)) { x = x2pixel(x); y = y2pixel(y); if (dragX_ >= x - size_/4 && dragX_ < x + size_/4 && dragY_ >= y - size_/4 && dragY_ < y + size_/4) { dragX_ = x; dragY_ = y; } } } if (dragX_ == old_x && dragY_ == old_y) return; TQRect rect(dragX_, dragY_, size_, size_); dragXpm_.resize(size_, size_); TQPainter paint; paint.begin(&dragXpm_); paint.setBackgroundColor(backgroundColor()); paint.setBrushOrigin(- dragX_, - dragY_); paint.translate((double) (- dragX_), (double) (- dragY_)); paintPainter(paint, rect); paint.end(); dragImage_ = dragXpm_; for (int yy=0; yyobjectImg().pixel(xx, yy); int r1 = tqRed(rgb1); int g1 = tqGreen(rgb1); int b1 = tqBlue(rgb1); if (r1 != g1 || r1 != b1 || r1 == 255) { TQRgb rgb2 = dragImage_.pixel(xx, yy); int r2 = tqRed(rgb2); int g2 = tqGreen(rgb2); int b2 = tqBlue(rgb2); r2 = (int) (0.75 * r1 + 0.25 * r2 + 0.5); g2 = (int) (0.75 * g1 + 0.25 * g2 + 0.5); b2 = (int) (0.75 * b1 + 0.25 * b2 + 0.5); dragImage_.setPixel(xx, yy, tqRgb(r2, g2, b2)); } } } paint.begin(this); // the following line is a workaround for a bug in TQt 2.0.1 // (and possibly earlier versions) paint.setBrushOrigin(0, 0); dragXpm_.convertFromImage(dragImage_, OrderedDither|OrderedAlphaDither| ColorOnly|AvoidDither); paint.drawPixmap(dragX_, dragY_, dragXpm_); { int dx = dragX_ - old_x; int dy = dragY_ - old_y; int y2 = old_y; if (dy > 0) { paintPainterClip(paint, old_x, old_y, size_, dy); // NOTE: clipping is now activated in the TQPainter paint y2 += dy; } else if (dy < 0) { paintPainterClip(paint, old_x, old_y+size_+dy, size_, -dy); // NOTE: clipping is now activated in the TQPainter paint dy = -dy; } if (dx > 0) { paintPainterClip(paint, old_x, y2, dx, size_-dy); // NOTE: clipping is now activated in the TQPainter paint } else if (dx < 0) { paintPainterClip(paint, old_x+size_+dx, y2, -dx, size_-dy); // NOTE: clipping is now activated in the TQPainter paint } } paint.end(); } void PlayField::highlight() { // FIXME: the line below should not be needed if (size_ == 0) return; int x=pixel2x(lastMouseXPos_); int y=pixel2y(lastMouseYPos_); if (x < 0 || y < 0 || x >= levelMap_->width() || y >= levelMap_->height()) return; if (x == highlightX_ && y == highlightY_) return; if (pathFinder_.canDrag(x, y)) { TQPainter paint(this); if (highlightX_ >= 0) { int x = highlightX_, y = highlightY_; highlightX_ = -1; paintSquare(x, y, paint); } else changeCursor(&sizeAllCursor); if (levelMap_->goal(x, y)) imageData_->brightTreasure(paint, x2pixel(x), y2pixel(y)); else imageData_->brightObject(paint, x2pixel(x), y2pixel(y)); highlightX_ = x; highlightY_ = y; } else { if (pathFinder_.canWalkTo(x, y)) changeCursor(&crossCursor); else changeCursor(0); if (highlightX_ >= 0) { TQPainter paint(this); int x = highlightX_, y = highlightY_; highlightX_ = -1; paintSquare(x, y, paint); } } } void PlayField::stopMoving() { TQT_TQOBJECT(this)->killTimers(); delete moveSequence_; moveSequence_ = 0; moveInProgress_ = false; updateStepsXpm(); updatePushesXpm(); TQPainter paint(this); paint.drawPixmap(snumRect_.x(), snumRect_.y(), snumXpm_); paint.drawPixmap(pnumRect_.x(), pnumRect_.y(), pnumXpm_); pathFinder_.updatePossibleMoves(); } void PlayField::startMoving(Move *m) { startMoving(new MoveSequence(m, levelMap_)); } void PlayField::startMoving(MoveSequence *ms) { static const int delay[4] = {0, 15, 35, 60}; assert(moveSequence_ == 0 && !moveInProgress_); moveSequence_ = ms; moveInProgress_ = true; if (animDelay_) startTimer(delay[animDelay_]); timerEvent(0); } void PlayField::timerEvent(TQTimerEvent *) { assert(moveInProgress_); if (moveSequence_ == 0) { TQT_TQOBJECT(this)->killTimers(); moveInProgress_ = false; return; } bool more=false; mapDelta_->start(); if (animDelay_) more = moveSequence_->next(); else { while (moveSequence_->next()) if (levelMap_->completed()) break; more = true; // FIXME: clean this up stopMoving(); } mapDelta_->end(); if (more) { paintDelta(); if (levelMap_->completed()) { stopMoving(); ModalLabel::message(i18n("Level completed"), this); nextLevel(); return; } } else stopMoving(); } void PlayField::step(int _x, int _y) { if (!canMoveNow()) return; int oldX=levelMap_->xpos(); int oldY=levelMap_->ypos(); int x=oldX, y=oldY; int dx=0, dy=0; if (_x>oldX) dx=1; if (_xoldY) dy=1; if (_ystep(x+dx, y+dy)) { x += dx; y += dy; } if (x!=oldX || y!=oldY) { Move *m = new Move(oldX, oldY); m->step(x, y); m->finish(); history_->add(m); m->undo(levelMap_); startMoving(m); } } void PlayField::push(int _x, int _y) { if (!canMoveNow()) return; int oldX=levelMap_->xpos(); int oldY=levelMap_->ypos(); int x=oldX, y=oldY; int dx=0, dy=0; if (_x>oldX) dx=1; if (_xoldY) dy=1; if (_ystep(x+dx, y+dy)) { x += dx; y += dy; } int objX=x, objY=y; while (!(x==_x && y==_y) && levelMap_->push(x+dx, y+dy)) { x += dx; y += dy; } if (x!=oldX || y!=oldY) { Move *m = new Move(oldX, oldY); if (objX!=oldX || objY!=oldY) m->step(objX, objY); if (objX!=x || objY!=y) { m->push(x, y); objX += dx; objY += dy; } m->finish(); history_->add(m); m->undo(levelMap_); startMoving(m); } } void PlayField::keyPressEvent(TQKeyEvent * e) { int x=levelMap_->xpos(); int y=levelMap_->ypos(); switch (e->key()) { case Key_Up: if (e->state() & ControlButton) step(x, 0); else if (e->state() & ShiftButton) push(x, 0); else push(x, y-1); break; case Key_Down: if (e->state() & ControlButton) step(x, MAX_Y); else if (e->state() & ShiftButton) push(x, MAX_Y); else push(x, y+1); break; case Key_Left: if (e->state() & ControlButton) step(0, y); else if (e->state() & ShiftButton) push(0, y); else push(x-1, y); break; case Key_Right: if (e->state() & ControlButton) step(MAX_X, y); else if (e->state() & ShiftButton) push(MAX_X, y); else push(x+1, y); break; case Key_Q: TDEApplication::kApplication()->closeAllWindows(); break; case Key_Backspace: case Key_Delete: if (e->state() & ControlButton) redo(); else undo(); break; #if 0 case Key_X: levelMap_->random(); levelChange(); repaint(false); break; case Key_R: level(levelMap_->level()); return; break; case Key_N: nextLevel(); return; break; case Key_P: previousLevel(); return; break; case Key_U: undo(); return; break; case Key_I: history_->redo(levelMap_); repaint(false); return; break; case Key_S: { TQString buf; history_->save(buf); printf("%s\n", (char *) buf); } return; break; case Key_L: stopMoving(); history_->clear(); level(levelMap_->level()); { char buf[4096]="r1*D1*D1*r1*@r1*D1*"; //scanf("%s", buf); history_->load(levelMap_, buf); } updateStepsXpm(); updatePushesXpm(); repaint(false); return; break; #endif case Key_Print: HtmlPrinter::printHtml(levelMap_); break; default: e->ignore(); return; break; } } void PlayField::stopDrag() { if (!dragInProgress_) return; changeCursor(0); TQPainter paint(this); // the following line is a workaround for a bug in TQt 2.0.1 // (and possibly earlier versions) paint.setBrushOrigin(0, 0); int x = highlightX_, y = highlightY_; paintSquare(x, y, paint); paintPainterClip(paint, dragX_, dragY_, size_, size_); // NOTE: clipping is now activated in the TQPainter paint dragInProgress_ = false; } void PlayField::dragObject(int xpixel, int ypixel) { int x=pixel2x(xpixel - mousePosX_ + size_/2); int y=pixel2y(ypixel - mousePosY_ + size_/2); if (x == highlightX_ && y == highlightY_) return; printf("drag %d,%d to %d,%d\n", highlightX_, highlightY_, x, y); pathFinder_.drag(highlightX_, highlightY_, x, y); stopDrag(); } void PlayField::mousePressEvent(TQMouseEvent *e) { if (!canMoveNow()) return; if (dragInProgress_) { if (e->button() == Qt::LeftButton) dragObject(e->x(), e->y()); else stopDrag(); return; } int x=pixel2x(e->x()); int y=pixel2y(e->y()); if (x < 0 || y < 0 || x >= levelMap_->width() || y >= levelMap_->height()) return; if (e->button() == Qt::LeftButton && pathFinder_.canDrag(x, y)) { TQPainter paint(this); changeCursor(&sizeAllCursor); if (levelMap_->goal(x, y)) imageData_->brightTreasure(paint, x2pixel(x), y2pixel(y)); else imageData_->brightObject(paint, x2pixel(x), y2pixel(y)); highlightX_ = x; highlightY_ = y; pathFinder_.updatePossibleDestinations(x, y); dragX_ = x2pixel(x); dragY_ = y2pixel(y); mousePosX_ = e->x() - dragX_; mousePosY_ = e->y() - dragY_; dragInProgress_ = true; } Move *m; switch (e->button()) { case Qt::LeftButton: m = pathFinder_.search(levelMap_, x, y); if (m != 0) { history_->add(m); startMoving(m); } break; case Qt::MidButton: undo(); return; break; case Qt::RightButton: push(x, y); break; default: return; } } void PlayField::wheelEvent(TQWheelEvent *e) { wheelDelta_ += e->delta(); if (wheelDelta_ >= 120) { wheelDelta_ %= 120; redo(); } else if (wheelDelta_ <= -120) { wheelDelta_ = -(-wheelDelta_ % 120); undo(); } } void PlayField::mouseReleaseEvent(TQMouseEvent *e) { if (dragInProgress_) dragObject(e->x(), e->y()); } void PlayField::focusInEvent(TQFocusEvent *) { //printf("PlayField::focusInEvent\n"); } void PlayField::focusOutEvent(TQFocusEvent *) { //printf("PlayField::focusOutEvent\n"); } void PlayField::leaveEvent(TQEvent *) { stopDrag(); } void PlayField::setSize(int w, int h) { int sbarHeight = statusMetrics_.height(); int sbarNumWidth = statusMetrics_.boundingRect("88888").width()+8; int sbarLevelWidth = statusMetrics_.boundingRect(levelText_).width()+8; int sbarStepsWidth = statusMetrics_.boundingRect(stepsText_).width()+8; int sbarPushesWidth = statusMetrics_.boundingRect(pushesText_).width()+8; pnumRect_.setRect(w-sbarNumWidth, h-sbarHeight, sbarNumWidth, sbarHeight); ptxtRect_.setRect(pnumRect_.x()-sbarPushesWidth, h-sbarHeight, sbarPushesWidth, sbarHeight); snumRect_.setRect(ptxtRect_.x()-sbarNumWidth, h-sbarHeight, sbarNumWidth, sbarHeight); stxtRect_.setRect(snumRect_.x()-sbarStepsWidth, h-sbarHeight, sbarStepsWidth, sbarHeight); lnumRect_.setRect(stxtRect_.x()-sbarNumWidth, h-sbarHeight, sbarNumWidth, sbarHeight); ltxtRect_.setRect(lnumRect_.x()-sbarLevelWidth, h-sbarHeight, sbarLevelWidth, sbarHeight); collRect_.setRect(0, h-sbarHeight, ltxtRect_.x(), sbarHeight); collXpm_.resize(collRect_.size()); ltxtXpm_.resize(ltxtRect_.size()); lnumXpm_.resize(lnumRect_.size()); stxtXpm_.resize(stxtRect_.size()); snumXpm_.resize(snumRect_.size()); ptxtXpm_.resize(ptxtRect_.size()); pnumXpm_.resize(pnumRect_.size()); h -= sbarHeight; int cols = levelMap_->width(); int rows = levelMap_->height(); // FIXME: the line below should not be needed if (cols == 0 || rows == 0) return; int xsize = w / cols; int ysize = h / rows; if (xsize < 8) xsize = 8; if (ysize < 8) ysize = 8; size_ = imageData_->resize(xsize > ysize ? ysize : xsize); xOffs_ = (w - cols*size_) / 2; yOffs_ = (h - rows*size_) / 2; updateCollectionXpm(); updateTextXpm(); updateLevelXpm(); updateStepsXpm(); updatePushesXpm(); } void PlayField::nextLevel() { if (levelMap_->level()+1 >= levelMap_->noOfLevels()) { ModalLabel::message(i18n("\ This is the last level in\n\ the current collection."), this); return; } if (levelMap_->level() >= levelMap_->completedLevels()) { ModalLabel::message(i18n("\ You have not completed\n\ this level yet."), this); return; } level(levelMap_->level()+1); levelChange(); repaint(false); } void PlayField::previousLevel() { if (levelMap_->level() <= 0) { ModalLabel::message(i18n("\ This is the first level in\n\ the current collection."), this); return; } level(levelMap_->level()-1); levelChange(); repaint(false); } void PlayField::undo() { if (!canMoveNow()) return; startMoving(history_->deferUndo(levelMap_)); } void PlayField::redo() { if (!canMoveNow()) return; startMoving(history_->deferRedo(levelMap_)); } void PlayField::restartLevel() { stopMoving(); history_->clear(); level(levelMap_->level()); updateStepsXpm(); updatePushesXpm(); repaint(false); } void PlayField::changeCollection(LevelCollection *collection) { if (levelMap_->collection() == collection) return; levelMap_->changeCollection(collection); levelChange(); //erase(collRect_); repaint(false); } void PlayField::updateCollectionXpm() { if (collXpm_.isNull()) return; TQPainter paint(&collXpm_); paint.setBrushOrigin(- collRect_.x(), - collRect_.y()); paint.fillRect(0, 0, collRect_.width(), collRect_.height(), background_); paint.setFont(statusFont_); paint.setPen(TQColor(0,255,0)); paint.drawText(0, 0, collRect_.width(), collRect_.height(), AlignLeft, collectionName()); } void PlayField::updateTextXpm() { if (ltxtXpm_.isNull()) return; TQPainter paint; paint.begin(<xtXpm_); paint.setBrushOrigin(- ltxtRect_.x(), - ltxtRect_.y()); paint.fillRect(0, 0, ltxtRect_.width(), ltxtRect_.height(), background_); paint.setFont(statusFont_); paint.setPen(TQColor(128,128,128)); paint.drawText(0, 0, ltxtRect_.width(), ltxtRect_.height(), AlignLeft, levelText_); paint.end(); paint.begin(&stxtXpm_); paint.setBrushOrigin(- stxtRect_.x(), - stxtRect_.y()); paint.fillRect(0, 0, stxtRect_.width(), stxtRect_.height(), background_); paint.setFont(statusFont_); paint.setPen(TQColor(128,128,128)); paint.drawText(0, 0, stxtRect_.width(), stxtRect_.height(), AlignLeft, stepsText_); paint.end(); paint.begin(&ptxtXpm_); paint.setBrushOrigin(- ptxtRect_.x(), - ptxtRect_.y()); paint.fillRect(0, 0, ptxtRect_.width(), ptxtRect_.height(), background_); paint.setFont(statusFont_); paint.setPen(TQColor(128,128,128)); paint.drawText(0, 0, ptxtRect_.width(), ptxtRect_.height(), AlignLeft, pushesText_); paint.end(); } void PlayField::updateLevelXpm() { if (lnumXpm_.isNull()) return; TQPainter paint(&lnumXpm_); paint.setBrushOrigin(- lnumRect_.x(), - lnumRect_.y()); paint.fillRect(0, 0, lnumRect_.width(), lnumRect_.height(), background_); TQString str; paint.setFont(statusFont_); paint.setPen(TQColor(255,0,0)); paint.drawText(0, 0, lnumRect_.width(), lnumRect_.height(), AlignLeft, str.sprintf("%05d", level()+1)); } void PlayField::updateStepsXpm() { if (snumXpm_.isNull()) return; TQPainter paint(&snumXpm_); paint.setBrushOrigin(- snumRect_.x(), - snumRect_.y()); paint.fillRect(0, 0, snumRect_.width(), snumRect_.height(), background_); TQString str; paint.setFont(statusFont_); paint.setPen(TQColor(255,0,0)); paint.drawText(0, 0, snumRect_.width(), snumRect_.height(), AlignLeft, str.sprintf("%05d", totalMoves())); } void PlayField::updatePushesXpm() { if (pnumXpm_.isNull()) return; TQPainter paint(&pnumXpm_); paint.setBrushOrigin(- pnumRect_.x(), - pnumRect_.y()); paint.fillRect(0, 0, pnumRect_.width(), pnumRect_.height(), background_); TQString str; paint.setFont(statusFont_); paint.setPen(TQColor(255,0,0)); paint.drawText(0, 0, pnumRect_.width(), pnumRect_.height(), AlignLeft, str.sprintf("%05d", totalPushes())); } void PlayField::changeAnim(int num) { assert(num >= 0 && num <= 3); animDelay_ = num; } // FIXME: clean up bookmark stuff // static const int bookmark_id[] = { // 0, 1, 8, 2, 9, 3, 5, 6, 7, 4 // }; void PlayField::setBookmark(Bookmark *bm) { if (!levelMap_->goodLevel()) return; if (collection()->id() < 0) { KMessageBox::sorry(this, i18n("Sorry, bookmarks for external levels\n" "is not implemented yet.")); return; } bm->set(collection()->id(), levelMap_->level(), levelMap_->totalMoves(), history_); } void PlayField::goToBookmark(Bookmark *bm) { level(bm->level()); levelChange(); if (!bm->goTo(levelMap_, history_)) fprintf(stderr, "Warning: bad bookmark\n"); //updateLevelXpm(); updateStepsXpm(); updatePushesXpm(); repaint(false); } bool PlayField::canMoveNow() { if (moveInProgress_) return false; if (!levelMap_->goodLevel()) { ModalLabel::message(i18n("This level is broken"), this); return false; } return true; }