Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

score.cpp

Go to the documentation of this file.
00001 
00002 #include "portable.h"
00003 
00004 #if defined( KDE2_PORT )
00005 #include <score.h>
00006 #include <score.moc>
00007 
00008 #include <kaccel.h>
00009 #include <kapp.h>
00010 #include <kconfig.h>
00011 #include <kstddirs.h>
00012 #include <kmessagebox.h>
00013 #elif defined( QPE_PORT )
00014 #include <qaccel.h>
00015 #include <qpe/config.h>
00016 #include "score.h"
00017 #endif
00018 
00019 #include <stdlib.h>
00020 #include <ctype.h>
00021 
00022 #include <qtimer.h>
00023 
00024 
00025 Score::Score(QWidget *parent, const char *name, int Scheme, int Mode, Bitfont *font) : QWidget(parent, name)
00026 {
00027     setFocusPolicy(QWidget::StrongFocus);
00028 
00029     paused = FALSE;
00030 
00031     lastScore = -1;
00032     lastPlayer = -1;
00033 
00034     cursorBlinkTimer = 0;
00035     cursorBlinkMS = -1;
00036     cursor.x = -1;
00037     cursor.y = -1;
00038     cursor.on = FALSE;
00039     cursor.chr = QChar('?');
00040 
00041     initKeys();
00042 
00043     scheme = Scheme;
00044     mode = Mode;
00045     confScheme();
00046 
00047     bitfont = font;
00048 
00049     highscoreFile.setName(locateHighscoreFilePath().filePath());
00050     read();
00051 
00052     for (int p = 0; p < maxPlayer; p++) {
00053         playerScore[p] = 0;
00054         playerName[p] = getenv("LOGNAME");
00055         if (playerName[p].length() < minPlayerNameLength)
00056             playerName[p].setExpand(minPlayerNameLength-1, ' ');
00057 
00058         for (uint i = 0; i < playerName[p].length(); i++)
00059             if (playerName[p].at(i) < bitfont->firstChar() ||
00060                 playerName[p].at(i) > bitfont->lastChar())
00061                 playerName[p].at(i) = playerName[p].at(i).upper();
00062     }
00063 }
00064 
00065 Score::~Score()
00066 {
00067     // write();
00068 }
00069 
00070 void Score::paintEvent( QPaintEvent *e)
00071 {
00072     if (rect(1, 0, tr("  1UP ")).intersects(e->rect())) {
00073         QPixmap pix;
00074         QColor fg = BLACK;
00075         if (cursor.on || paused || lastPlayer != 0)
00076             fg = WHITE;
00077         pix = bitfont->text(tr("  1UP "), fg, BLACK);
00078         bitBlt(this, x(1), y(0), &pix);
00079     }
00080 
00081     if (rect(8, 0, tr(" HIGH SCORE ")).intersects(e->rect())) {
00082             QPixmap pix = bitfont->text(tr(" HIGH SCORE "), WHITE, BLACK);
00083         bitBlt(this, x(8), y(0), &pix);
00084     }
00085 
00086     if (maxPlayer > 1 && rect(21, 0, tr("  2UP ")).intersects(e->rect())) {
00087         QPixmap pix;
00088         QColor fg = BLACK;
00089         if (cursor.on || paused || lastPlayer != 1)
00090             fg = WHITE;
00091         pix = bitfont->text(tr("  2UP "), fg, BLACK);
00092         bitBlt(this, x(21), y(0), &pix);
00093     }
00094 
00095     QString s;
00096 
00097     s.sprintf("%6d0", playerScore[0]/10);
00098     if (rect(0, 1, s).intersects(e->rect())) {
00099             QPixmap pix = bitfont->text(s, WHITE, BLACK);
00100             bitBlt(this, x(0), y(1), &pix);
00101     }
00102 
00103     s.sprintf("%8d0", HighScore/10);
00104     if (rect(8, 1, s).intersects(e->rect())) {
00105             QPixmap pix = bitfont->text(s, WHITE, BLACK);
00106             bitBlt(this, x(8), y(1), &pix);
00107     }
00108 
00109     if (lastScore >= 0) {
00110         if (rect(1, 4*1.25, tr("     CONGRATULATIONS      ")).intersects(e->rect())) {
00111             QPixmap pix = bitfont->text(tr("     CONGRATULATIONS      "), YELLOW, BLACK);
00112             bitBlt(this, x(1), y(4*1.25), &pix);
00113         }
00114         if (rect(1, 6*1.25, tr("    YOU HAVE ARCHIEVED    ")).intersects(e->rect())) {
00115             QPixmap pix = bitfont->text(tr("    YOU HAVE ARCHIEVED    "), CYAN, BLACK);
00116             bitBlt(this, x(1), y(6*1.25), &pix);
00117         }
00118         if (rect(1, 7*1.25, tr("  A SCORE IN THE TOP 10.  ")).intersects(e->rect())) {
00119             QPixmap pix = bitfont->text(tr("  A SCORE IN THE TOP 10.  "), CYAN, BLACK);
00120             bitBlt(this, x(1), y(7*1.25), &pix);
00121         }
00122         if (rect(1, 8*1.25, tr("                          ")).intersects(e->rect())) {
00123             QPixmap pix = bitfont->text(tr("                          "), CYAN, BLACK);
00124             bitBlt(this, x(1), y(8*1.25), &pix);
00125         }
00126     }
00127 
00128     if (rect(1, 9.5*1.25, tr("RNK   SCORE  NAME   DATE")).intersects(e->rect())) {
00129             QPixmap pix = bitfont->text(tr("RNK   SCORE  NAME   DATE"), WHITE, BLACK);
00130         bitBlt(this, x(1), y(9.5*1.25), &pix);
00131     }
00132 
00133     for (int i = 0; i < 10; i++) {
00134         s.sprintf("%2d%9d  %-3.3s  %-8.8s",
00135             i+1, hallOfFame[i].points, hallOfFame[i].name.utf8().data(),
00136             formatDate(hallOfFame[i].moment.date()).data());
00137         if (rect(1, (11+i)*1.25, s).intersects(e->rect())) {
00138             QPixmap pix = bitfont->text(s, (i == lastScore) ? YELLOW : WHITE, BLACK);
00139             bitBlt(this, x(1), y((11+i)*1.25), &pix);
00140         }
00141     }
00142 
00143     if (cursor.x != -1 && cursor.y != -1 && cursor.on) {
00144         if (rect(cursor.x, (cursor.y*1.25), cursor.chr).intersects(e->rect())) {
00145             QPixmap pix = bitfont->text(cursor.chr, BLACK, YELLOW);
00146             bitBlt(this, x(cursor.x), y(cursor.y*1.25), &pix);
00147         }
00148     }
00149 
00150     if (paused) {
00151 
00152         QPixmap pix = bitfont->text(tr("PAUSED"), RED, BLACK);
00153         QRect r = bitfont->rect(tr("PAUSED"));
00154         r.moveCenter(QPoint(this->width()/2, this->height()/2));
00155 
00156         bitBlt(this, r.x(), r.y(), &pix);
00157     }
00158 }
00159 
00160 void Score::timerEvent(QTimerEvent*)
00161 {
00162     cursor.on = !cursor.on;
00163 
00164     if (paused)
00165         return;
00166 
00167     if (cursor.x != -1 && cursor.y != -1)
00168         repaint(rect(cursor.x, cursor.y*1.25, cursor.chr), FALSE);
00169     scrollRepeat = FALSE;
00170 
00171     if (lastPlayer == 0)
00172         repaint(rect(1, 0, tr("  1UP ")), FALSE);
00173 
00174     if (lastPlayer == 1)
00175         repaint(rect(21, 0, tr("  2UP ")), FALSE);
00176 }
00177 
00178 void Score::keyPressEvent(QKeyEvent *k)
00179 {
00180     if (lastScore < 0 || lastPlayer < 0 || lastPlayer >= maxPlayer || paused) {
00181         k->ignore();
00182         return;
00183     }
00184 
00185     int x = cursor.x;
00186     int y = cursor.y;
00187 
00188     uint key = k->key();
00189 
00190     if (scrollRepeat && (key == UpKey || key == Key_Up || key == DownKey || key == Key_Down)) {
00191         k->ignore();
00192         return;
00193     }
00194 
00195     if (key != Key_Return) {
00196         if (key == RightKey || key == Key_Right)
00197             if (++cursor.x > 16)
00198                 cursor.x = 14;
00199         if (key == LeftKey || key == Key_Left)
00200             if (--cursor.x < 14)
00201                 cursor.x = 16;
00202         if (key == UpKey || key == Key_Up)
00203             if (cursor.chr.unicode() < bitfont->lastChar())
00204                 cursor.chr = cursor.chr.unicode()+1;
00205             else
00206                 cursor.chr = bitfont->firstChar();
00207         if (key == DownKey || key == Key_Down)
00208             if (cursor.chr.unicode() > bitfont->firstChar())
00209                 cursor.chr = cursor.chr.unicode()-1;
00210             else
00211                 cursor.chr = bitfont->lastChar();
00212 
00213         if (cursor.x == x && cursor.y == y &&
00214             cursor.chr == hallOfFame[lastScore].name.at(cursor.x-14)) {
00215             uint ascii = k->ascii();
00216 
00217             if (ascii < bitfont->firstChar() || ascii > bitfont->lastChar())
00218                 ascii = toupper(ascii);
00219 
00220             if (ascii >= bitfont->firstChar() && ascii <= bitfont->lastChar()) {
00221                 cursor.chr = ascii;
00222                 hallOfFame[lastScore].name.at(cursor.x-14) = cursor.chr;
00223                 if (++cursor.x > 16)
00224                     cursor.x = 14;
00225             }
00226         }
00227     }
00228 
00229     if (key == Key_Return) {
00230         playerName[lastPlayer] = hallOfFame[lastScore].name;
00231         write();
00232         read();
00233         lastScore = -1;
00234         cursor.x = -1;
00235         cursor.y = -1;
00236 //      killTimers();
00237         emit toggleNew();
00238         end();
00239     }
00240 
00241     if (x != cursor.x || y != cursor.y) {
00242         if (cursor.x != -1)
00243             cursor.chr = hallOfFame[lastScore].name.at(cursor.x-14);
00244         scrollRepeat = FALSE;
00245         repaint(rect(x, y*1.25, cursor.chr), FALSE);
00246     } else
00247         hallOfFame[lastScore].name.at(cursor.x-14) = cursor.chr;
00248 
00249     if (key == UpKey || key == Key_Up || key == DownKey || key == Key_Down)
00250        scrollRepeat = TRUE;
00251     else
00252        repaint(rect(cursor.x, cursor.y*1.25, cursor.chr), FALSE);
00253 }
00254 
00255 void Score::initKeys()
00256 {
00257     APP_CONFIG_BEGIN( cfg );
00258     QString up("Up");
00259     up = cfg->readEntry("upKey", (const char*) up);
00260     UpKey    = KAccel::stringToKey(up);
00261 
00262     QString down("Down");
00263     down = cfg->readEntry("downKey", (const char*) down);
00264     DownKey  = KAccel::stringToKey(down);
00265 
00266     QString left("Left");
00267     left = cfg->readEntry("leftKey", (const char*) left);
00268     LeftKey  = KAccel::stringToKey(left);
00269 
00270     QString right("Right");
00271     right = cfg->readEntry("rightKey", (const char*) right);
00272     RightKey = KAccel::stringToKey(right);
00273     APP_CONFIG_END( cfg );
00274 }
00275 
00276 void Score::confTiming(bool defGroup)
00277 {
00278     APP_CONFIG_BEGIN( cfg );
00279     if (defGroup || cfg->hasKey("CursorBlinkMS"))
00280         cursorBlinkMS = cfg->readNumEntry("CursorBlinkMS", 250);
00281     if (defGroup || cfg->hasKey("HallOfFameMS"))
00282         hallOfFameMS = cfg->readNumEntry("HallOfFameMS", 7000);
00283     if (defGroup || cfg->hasKey("AfterPauseMS"))
00284         afterPauseMS = cfg->readNumEntry("AfterPauseMS", 1000);
00285     APP_CONFIG_END( cfg );
00286 }
00287 
00288 void Score::confScheme()
00289 {
00290     APP_CONFIG_BEGIN( cfg );
00291     SAVE_CONFIG_GROUP( cfg, oldgroup );
00292     QString newgroup;
00293 
00294     // if not set, read mode and scheme from the configfile
00295     if (mode == -1 && scheme == -1) {
00296         scheme = cfg->readNumEntry("Scheme", -1);
00297         mode = cfg->readNumEntry("Mode", -1);
00298 
00299         // if mode is not set in the defGroup-group, lookup the scheme group
00300         if (scheme != -1 || mode == -1) {
00301             newgroup.sprintf("Scheme %d", scheme);
00302             cfg->setGroup(newgroup);
00303 
00304             mode = cfg->readNumEntry("Mode", -1);
00305             RESTORE_CONFIG_GROUP( cfg, oldgroup );
00306         }
00307     }
00308 
00309     int oldCursorBlinkMS = cursorBlinkMS;
00310 
00311     confTiming();
00312 
00313     if (mode != -1) {
00314         newgroup.sprintf("Mode %d", mode);
00315         cfg->setGroup(newgroup);
00316 
00317         confTiming(FALSE);
00318     }
00319 
00320     if (scheme != -1) {
00321         newgroup.sprintf("Scheme %d", scheme);
00322         cfg->setGroup(newgroup);
00323 
00324         confTiming(FALSE);
00325     }
00326 
00327     if (cursorBlinkMS != oldCursorBlinkMS) {
00328         if (cursorBlinkTimer)
00329             killTimer(cursorBlinkTimer);
00330         cursorBlinkTimer = startTimer(cursorBlinkMS);
00331     }
00332 
00333     RESTORE_CONFIG_GROUP( cfg, oldgroup );
00334     APP_CONFIG_END( cfg );
00335 }
00336 
00337 void Score::setScheme(int Scheme, int Mode, Bitfont *font)
00338 {
00339     mode = Mode;
00340     scheme = Scheme;
00341 
00342     confScheme();
00343 
00344     bitfont = font;
00345 
00346     for (int p = 0; p < maxPlayer; p++)
00347         for (uint i = 0; i < playerName[p].length(); i++)
00348             if (playerName[p].at(i) < bitfont->firstChar() ||
00349                 playerName[p].at(i) > bitfont->lastChar())
00350                 playerName[p].at(i) = playerName[p].at(i).upper();
00351 
00352     for (int i = 0; i < 10; i++)
00353         for (uint j = 0; j < hallOfFame[i].name.length(); j++)
00354             if (hallOfFame[i].name.at(j) < bitfont->firstChar() ||
00355                 hallOfFame[i].name.at(j) > bitfont->lastChar())
00356                 hallOfFame[i].name.at(j) = hallOfFame[i].name.at(j).upper();
00357 
00358     if (cursor.chr.unicode() < bitfont->firstChar() ||
00359         cursor.chr.unicode() > bitfont->lastChar())
00360         cursor.chr = cursor.chr.upper();
00361 }
00362 
00363 void Score::set(int score)
00364 {
00365     set(score, 0);
00366 }
00367 
00368 void Score::set(int score, int player)
00369 {
00370     if (player < 0 || player >= maxPlayer)
00371         return;
00372 
00373     lastPlayer = player;
00374     playerScore[lastPlayer] = score;
00375 
00376     QString s;
00377 
00378     s.sprintf("%6d0", playerScore[lastPlayer]/10);
00379     repaint(rect(0, 1, s), FALSE);
00380 
00381     if (score > HighScore) {
00382             HighScore = score;
00383             s.sprintf("%8d0", HighScore/10);
00384             repaint(rect(8, 1, s), FALSE);
00385     }
00386 }
00387 
00388 /*
00389  * Set the score for player after the game if over. If the score is in the
00390  * high scores then the hall of fame is updated (shifted) and the scoreboard
00391  * is shown.
00392  */
00393 
00394 void Score::setScore(int level, int player)
00395 {
00396     lastScore = -1;
00397 
00398     if (player < 0 || player >= maxPlayer || level == 0) {
00399         if (level != 0)
00400             emit toggleNew();
00401         QTimer::singleShot(hallOfFameMS, this, SLOT(end()));
00402         return;
00403     }
00404 
00405     lastPlayer = player;
00406 
00407     for (int i = 0; i < 10; i++)
00408         if ( playerScore[lastPlayer] > hallOfFame[i].points) {
00409             lastScore = i;
00410             break;
00411         }
00412 
00413     if (lastScore < 0) {
00414         emit toggleNew();
00415         QTimer::singleShot(hallOfFameMS, this, SLOT(end()));
00416         return;
00417     }
00418 
00419     for (int i = 9; i > lastScore && i > 0; i--)
00420         hallOfFame[i] = hallOfFame[i-1];
00421 
00422     hallOfFame[lastScore].points = playerScore[lastPlayer];
00423     hallOfFame[lastScore].levels = level;
00424     hallOfFame[lastScore].moment = QDateTime::currentDateTime();
00425     hallOfFame[lastScore].name = playerName[lastPlayer];
00426 
00427     cursor.x = 14;
00428     cursor.y = 11+lastScore;
00429     cursor.chr = hallOfFame[lastScore].name.at(cursor.x-14);
00430 
00431 //  startTimer(cursorBlinkMS);
00432     setFocus();
00433 }
00434 
00435 /*
00436  * Read the highscores, if no file or a file shorter than 4 bytes (versions before 0.2.4 stores only
00437  * the points of one highscore) exists - the highscores were initialized with default values.
00438  */
00439 void Score::read()
00440 {
00441     if (highscoreFile.exists() && highscoreFile.size() > 4) {
00442         if (highscoreFile.open(IO_ReadOnly)) {
00443             QDataStream s(&highscoreFile);
00444             char *name;
00445             for (int i = 0; i < 10; i++) {
00446                 s >> hallOfFame[i].points >> hallOfFame[i].levels >> hallOfFame[i].duration >>
00447                      hallOfFame[i].moment >> name;
00448                 hallOfFame[i].name = QString::fromLatin1(name);
00449                 delete(name);
00450             }
00451             highscoreFile.close();
00452         }
00453     } else {
00454         for (int i = 0; i < 10; i++) {
00455             hallOfFame[i].points = 5000;
00456             hallOfFame[i].levels = 0;
00457             hallOfFame[i].duration = QTime();
00458             hallOfFame[i].moment = QDateTime();
00459             hallOfFame[i].name = "???";
00460         }
00461         // write();
00462     }
00463 
00464     for (int i = 0; i < 10; i++)
00465         for (uint j = 0; j < hallOfFame[i].name.length(); j++)
00466             if (hallOfFame[i].name.at(j) < bitfont->firstChar() ||
00467                 hallOfFame[i].name.at(j) > bitfont->lastChar())
00468                 hallOfFame[i].name.at(j) = hallOfFame[i].name.at(j).upper();
00469 
00470     HighScore = hallOfFame[0].points;
00471 }
00472 
00473 void Score::write()
00474 {
00475     if (highscoreFile.open(IO_WriteOnly)) {
00476         QDataStream s(&highscoreFile);
00477         for (int i = 0; i < 10; i++)
00478             s << hallOfFame[i].points << hallOfFame[i].levels << hallOfFame[i].duration <<
00479                  hallOfFame[i].moment << hallOfFame[i].name.latin1();
00480         highscoreFile.close();
00481     }
00482 }
00483 
00484 void Score::setPause(bool Paused)
00485 {
00486     paused = Paused;
00487 
00488     QRect r = bitfont->rect(tr("PAUSED"));
00489     r.moveCenter(QPoint(this->width()/2, this->height()/2));
00490     repaint(r, TRUE);
00491 
00492     // repaint 1UP or 2UP
00493     repaint(FALSE);
00494 }
00495 
00496 void Score::end()
00497 {
00498     if (paused) {
00499         QTimer::singleShot(afterPauseMS, this, SLOT(end()));
00500         return;
00501     }
00502 
00503     // repaint 1UP or 2UP
00504     lastPlayer = -1;
00505     repaint(FALSE);
00506 
00507     emit forcedHallOfFame(FALSE);
00508 }
00509 
00510 /*
00511  * Return the date in a formatted QString. The format can be changed using internationalization
00512  * of the string "YY/MM/DD". Invalid QDate's where returned as "00/00/00".
00513  */
00514 QString Score::formatDate(QDate date)
00515 {
00516     QString s = tr("@YY@/@MM@/@DD@");
00517 
00518     QString dd;
00519     dd.sprintf("%02d", date.isValid() ? date.year() % 100 : 0);
00520     s.replace(QRegExp("@YY@"), dd);
00521     dd.sprintf("%02d", date.isValid() ? date.month() : 0);
00522     s.replace(QRegExp("@MM@"), dd);
00523     dd.sprintf("%02d", date.isValid() ? date.day() : 0);
00524     s.replace(QRegExp("@DD@"), dd);
00525 
00526     return s;
00527 }
00528 
00529 QRect Score::rect(int col, float row, QString str, int align)
00530 {
00531     QRect r = bitfont->rect(str);
00532     r.moveBy(x(col), y(row));
00533 
00534     int dx = 0;
00535     int dy = 0;
00536 
00537     if (align & AlignLeft || align & AlignRight) {
00538         dx = (str.length()-1) * (bitfont->width()/2);
00539         if (align & AlignRight)
00540             dx *= -1;
00541     }
00542 
00543     if (align & AlignTop || align & AlignBottom) {
00544         dy = bitfont->height()/2;
00545         if (align & AlignBottom)
00546             dy *= -1;
00547     }
00548 
00549     if (dx != 0 || dy != 0)
00550         r.moveBy(dx, dy);
00551 
00552     return r;
00553 }
00554 
00555 int Score::x(int col)
00556 {
00557     return col*bitfont->width();
00558 }
00559 
00560 int Score::y(float row)
00561 {
00562     return (int) (row*(bitfont->height()+bitfont->height()/4));
00563 }
00564 
00572 QFileInfo Score::locateHighscoreFilePath()
00573 {
00574     return privateHighscoreFileInfo;
00575 }

Generated on Sat Nov 5 16:17:22 2005 for OPIE by  doxygen 1.4.2