#include #include #include #include #include #include #include #include #include #include #include #include #include "board.h" #include "pacman.h" #include "monster.h" #include "fruit.h" #include "painter.h" Referee::Referee( QWidget *parent, const char *name, int Scheme, int Mode, Bitfont *font) : QWidget( parent, name ) { gameState.resize(12); gameTimer = 0; energizerTimer = 0; focusedPause = false; setFocusPolicy(QWidget::StrongFocus); initKeys(); scheme = Scheme; mode = Mode; confScheme(); board = new Board(BoardWidth*BoardHeight); pix = new Painter(board, this, scheme, mode, font); setFixedSize(pix->levelPix().size()); pacman = new Pacman(board); fruit = new Fruit(board); monsters = new QList; monsters->setAutoDelete(TRUE); monsterRect = new QList; monsterRect->setAutoDelete(TRUE); energizers = new QList; energizers->setAutoDelete(TRUE); energizerRect = new QList; energizerRect->setAutoDelete(TRUE); pacmanRect.setRect(0, 0, 0, 0); fruitRect.setRect(0, 0, 0, 0); QTime midnight( 0, 0, 0 ); srand( midnight.secsTo(QTime::currentTime()) ); lifes = 0; points = 0; emit setLifes(lifes); emit setPoints(points); intro(); } void Referee::paintEvent( QPaintEvent *e) { if (gameState.testBit(HallOfFame)) return; QRect rect = e->rect(); if (!rect.isEmpty()) { QPixmap p = pix->levelPix(); bitBlt(this, rect.x(), rect.y(), &p, rect.x(), rect.y(), rect.width(), rect.height()); } if ((gameState.testBit(GameOver) || gameState.testBit(Demonstration)) && rect.intersects(pix->rect(board->position(fruithome), i18n("GAME OVER")))) pix->draw(board->position(fruithome), Widget, i18n("GAME OVER"), RED); for (Energizer *e = energizers->first(); e != 0; e = energizers->next()) { if (e && e->state() == on && rect.intersects(pix->rect(e->position(), EnergizerPix)) && !(e->position() == pacman->position() && gameState.testBit(Scoring))) { if (e->pix() != -1) pix->draw(e->position(), Widget, EnergizerPix, e->pix()); } } if (!gameState.testBit(Init)) { if (!gameState.testBit(Dying) && (fruit->pix() != -1)) if (fruit->state() != active) { if (rect.intersects(pix->rect(fruit->position(), FruitScorePix, fruit->pix()))) pix->draw(fruit->position(), Widget, FruitScorePix, fruit->pix()); } else { if (rect.intersects(pix->rect(fruit->position(), FruitPix, fruit->pix()))) pix->draw(fruit->position(), Widget, FruitPix, fruit->pix()); } for (Monster *m = monsters->first(); m != 0; m = monsters->next()) if (m && m->state() == harmless && rect.intersects(pix->rect(m->position(), MonsterPix)) && !(m->position() == pacman->position() && gameState.testBit(Scoring))) { if (m->body() != -1) pix->draw(m->position(), Widget, MonsterPix, m->body()); if (m->eyes() != -1) pix->draw(m->position(), Widget, EyesPix, m->eyes()); } if (!gameState.testBit(Scoring) && !gameState.testBit(LevelDone) && rect.intersects(pix->rect(pacman->position(), PacmanPix)) && pacman->pix() != -1) pix->draw(pacman->position(), Widget, PacmanPix, pacman->pix()); for (Monster *m = monsters->first(); m != 0; m = monsters->next()) if (m && m->state() != harmless && rect.intersects(pix->rect(m->position(), MonsterPix)) && !(m->position() == pacman->position() && gameState.testBit(Scoring))) { if (m->body() != -1) pix->draw(m->position(), Widget, MonsterPix, m->body()); if (m->eyes() != -1) pix->draw(m->position(), Widget, EyesPix, m->eyes()); } } if (gameState.testBit(Scoring) && rect.intersects(pix->rect(pacman->position(), MonsterScorePix, monstersEaten-1))) pix->draw(pacman->position(), Widget, MonsterScorePix, monstersEaten-1); if (gameState.testBit(Init) && gameState.testBit(Dying) && timerCount < pix->maxPixmaps(DyingPix) && rect.intersects(pix->rect(pacman->position(), PacmanPix))) pix->draw(pacman->position(), Widget, DyingPix, timerCount); if (gameState.testBit(LevelDone) && rect.intersects(pix->rect(pacman->position(), PacmanPix))) pix->draw(pacman->position(), Widget, PacmanPix, pacman->pix()); if (gameState.testBit(Player) && rect.intersects(pix->rect(board->position(monsterhome, 0), i18n("PLAYER ONE")))) pix->draw(board->position(monsterhome, 0), Widget, i18n("PLAYER ONE"), CYAN); if (gameState.testBit(Ready) && rect.intersects(pix->rect(board->position(fruithome), i18n("READY!")))) pix->draw(board->position(fruithome), Widget, i18n("READY!"), YELLOW); if (gameState.testBit(Paused) && rect.intersects(pix->rect((BoardWidth*BoardHeight)/2-BoardWidth, i18n("PAUSED")))) pix->draw((BoardWidth*BoardHeight)/2-BoardWidth, Widget, i18n("PAUSED"), RED, BLACK); } void Referee::timerEvent( QTimerEvent *e ) { if (gameState.testBit(HallOfFame)) return; QRect lastRect; int lastPix; bool moved = FALSE; int eated = 0; if (e->timerId() == energizerTimer) { for (int e = 0; e < board->energizers(); e++) { lastRect = pix->rect(energizers->at(e)->position(), EnergizerPix); lastPix = energizers->at(e)->pix(); if (energizers->at(e)->move()) { moved = TRUE; *energizerRect->at(e) = pix->rect(energizers->at(e)->position(), EnergizerPix); if (lastPix == energizers->at(e)->pix() && lastRect == pix->rect(energizers->at(e)->position(), EnergizerPix)) energizerRect->at(e)->setRect(0, 0, 0, 0); else *energizerRect->at(e) = pix->rect(*energizerRect->at(e), lastRect); } } for (int e = 0; e < board->energizers(); e++) if (!energizerRect->at(e)->isNull()) repaint(*energizerRect->at(e), FALSE); return; } timerCount++; lastRect = pix->rect(pacman->position(), PacmanPix); lastPix = pacman->pix(); if (moved = pacman->move()) { // pacman really moved pacmanRect = pix->rect(pacman->position(), PacmanPix); if (lastPix == pacman->pix() && lastRect == pix->rect(pacman->position(), PacmanPix)) pacmanRect.setRect(0, 0, 0, 0); // nothing to do, because the pixmap else // and the position isn't changed. pacmanRect = pix->rect(pacmanRect, lastRect); } else pacmanRect.setRect(0, 0, 0, 0); int pos = pacman->position(); if (moved && board->isMonster(pos) && !gameState.testBit(Dying)) { for (Monster *m = monsters->first(); m != 0; m = monsters->next()) if (m && m->position() == pos) { if (m->state() == harmless && !gameState.testBit(Dying)) { m->setREM(remTicks[level]); m->setDirection(X); // prevent movement before eaten() eated++; if (gameState.testBit(Introducing)) m->setPosition(OUT); } if (m->state() == dangerous && !gameState.testBit(Dying)) killed(); } } if (moved && !gameState.testBit(Dying)) { if (board->isPoint(pos)) { board->reset(pos, Point); score(pointScore); pix->erase(pos, PointPix); } if (board->isEnergizer(pos)) { for (int e = 0; e < board->energizers();e++) { if (energizers->at(e)->position() == pos) { energizers->at(e)->setOff(); energizers->remove(e); energizerRect->remove(e); e = board->energizers(); } } board->reset(pos, energizer); score(energizerScore); monstersEaten = 0; for (Monster *m = monsters->first(); m != 0; m = monsters->next()) if (m && m->state() != rem) { m->setHarmless(harmlessTicks[level], harmlessDurTicks[level], harmlessWarnTicks[level]); if (gameState.testBit(Introducing)) m->setDirection(board->turn(m->direction())); } } if (pos == fruit->position() && fruit->state() == active) { fruit->setEaten(fruitScoreDurTicks[level]); initFruit(FALSE); score(fruitScore[fruit->pix()]); } } if (!gameState.testBit(Introducing)) { if (fruit->state() != active && fruit->pix() >= 0) lastRect = pix->rect(fruit->position(), FruitScorePix, fruit->pix()); else lastRect = pix->rect(fruit->position(), FruitPix, fruit->pix()); lastPix = fruit->pix(); if (fruit->move()) { if (pos == fruit->position() && fruit->state() == active) { fruit->setEaten(fruitScoreDurTicks[level]); initFruit(FALSE); score(fruitScore[fruit->pix()]); } if (fruit->state() != active && fruit->pix() >= 0) fruitRect = pix->rect(fruit->position(), FruitScorePix, fruit->pix()); else fruitRect = pix->rect(fruit->position(), FruitPix, fruit->pix()); if (lastPix == fruit->pix() && lastRect == fruitRect) fruitRect.setRect(0, 0, 0, 0); else fruitRect = pix->rect(fruitRect, lastRect); } else fruitRect.setRect(0, 0, 0, 0); } else fruitRect.setRect(0, 0, 0, 0); int lastBodyPix; int lastEyesPix; for (Monster *m = monsters->first(); m != 0; m = monsters->next()) if (m) { lastRect = pix->rect(m->position(), MonsterPix); lastBodyPix = m->body(); lastEyesPix = m->eyes(); if (m->move()) { moved = TRUE; *monsterRect->at(m->id()) = pix->rect(m->position(), MonsterPix); if (lastBodyPix == m->body() && lastEyesPix == m->eyes() && lastRect == pix->rect(m->position(), MonsterPix)) monsterRect->at(m->id())->setRect(0, 0, 0, 0); else *monsterRect->at(m->id()) = pix->rect(*monsterRect->at(m->id()), lastRect); if (m->position() == pos && !gameState.testBit(Dying)) { if (m->state() == harmless && !gameState.testBit(Dying)) { m->setREM(remTicks[level]); eated++; if (gameState.testBit(Introducing)) { m->setPosition(OUT); m->setDirection(X); } } if (m->state() == dangerous && !gameState.testBit(Dying)) killed(); } } else monsterRect->at(m->id())->setRect(0, 0, 0, 0); } for (int m = 0; m < board->monsters(); m++) if (pacmanRect.intersects(*monsterRect->at(m))) { pacmanRect = pix->rect(pacmanRect, *monsterRect->at(m)); monsterRect->at(m)->setRect(0, 0, 0, 0); } else for (int im = m+1; im < board->monsters(); im++) if (monsterRect->at(m)->intersects(*monsterRect->at(im))) { *monsterRect->at(m) = pix->rect(*monsterRect->at(m), *monsterRect->at(im)); monsterRect->at(im)->setRect(0, 0, 0, 0); } if (!pacmanRect.isNull()) repaint(pacmanRect, FALSE); if (!fruitRect.isNull()) repaint(fruitRect, FALSE); for (int m = 0; m < board->monsters(); m++) if (!monsterRect->at(m)->isNull()) repaint(*monsterRect->at(m), FALSE); if (board->points() == 0 && !gameState.testBit(Dying)) levelUp(); if (eated > 0 && !gameState.testBit(Dying)) { timerCount = eated; eaten(); } if (gameState.testBit(Introducing) && moved) introPlay(); } void Referee::repaintFigures() { pacmanRect = pix->rect(pacman->position(), PacmanPix); for (int e = 0; e < board->energizers(); e++) { *energizerRect->at(e) = pix->rect(board->position(energizer, e), EnergizerPix); if (pacmanRect.intersects(*energizerRect->at(e))) { pacmanRect = pix->rect(pacmanRect, *energizerRect->at(e)); energizerRect->at(e)->setRect(0, 0, 0, 0); } else for (int ie = e+1; ie < board->energizers(); ie++) if (energizerRect->at(e)->intersects(*energizerRect->at(ie))) { *energizerRect->at(e) = pix->rect(*energizerRect->at(e), *energizerRect->at(ie)); energizerRect->at(ie)->setRect(0, 0, 0, 0); } } if (fruit->pix() != -1 && fruit->state() != active) fruitRect = pix->rect(fruit->position(), FruitScorePix, fruit->pix()); else fruitRect = pix->rect(fruit->position(), FruitPix, fruit->pix()); if (pacmanRect.intersects(fruitRect)) { pacmanRect = pix->rect(pacmanRect, fruitRect); fruitRect.setRect(0, 0, 0, 0); } for (int m = 0; m < board->monsters(); m++) { *monsterRect->at(m) = pix->rect(board->position(monster, m), MonsterPix); if (pacmanRect.intersects(*monsterRect->at(m))) { pacmanRect = pix->rect(pacmanRect, *monsterRect->at(m)); monsterRect->at(m)->setRect(0, 0, 0, 0); } else for (int im = m+1; im < board->monsters(); im++) if (monsterRect->at(m)->intersects(*monsterRect->at(im))) { *monsterRect->at(m) = pix->rect(*monsterRect->at(m), *monsterRect->at(im)); monsterRect->at(im)->setRect(0, 0, 0, 0); } } if (!pacmanRect.isNull()) repaint(pacmanRect, FALSE); if (!fruitRect.isNull()) repaint(fruitRect, FALSE); for (int m = 0; m < board->monsters(); m++) if (!monsterRect->at(m)->isNull()) repaint(*monsterRect->at(m), FALSE); for (int e = 0; e < board->energizers(); e++) if (!energizerRect->at(e)->isNull()) repaint(*energizerRect->at(e), FALSE); } void Referee::initKeys() { QString up("Up"); up = kapp->config()->readEntry("upKey", (const char*) up); UpKey = KAccel::stringToKey(up); QString down("Down"); down = kapp->config()->readEntry("downKey", (const char*) down); DownKey = KAccel::stringToKey(down); QString left("Left"); left = kapp->config()->readEntry("leftKey", (const char*) left); LeftKey = KAccel::stringToKey(left); QString right("Right"); right = kapp->config()->readEntry("rightKey", (const char*) right); RightKey = KAccel::stringToKey(right); } void Referee::fillArray(QArray &array, QString values, int max) { if (max < 0) max = values.contains(',')+1; array.resize(max); int last = 0; bool ok; QString value; for (uint i = 0; i < array.size(); i++) { if (values.find(',') < 0 && values.length() > 0) { value = values; values = ""; } if (values.find(',') >= 0) { value = values.left(values.find(',')); values.remove(0,values.find(',')+1); } array[i] = value.toInt(&ok); if (ok) last = array[i]; else array[i] = last; } } void Referee::fillStrList(QStrList &list, QString values, int max) { if (!list.isEmpty()) list.clear(); QString last = ""; QString value; for (uint i = 0; i < (uint) max; i++) { if (values.find(',') < 0 && values.length() > 0) { value = values; values = ""; } if (values.find(',') >= 0) { value = values.left(values.find(',')); values.remove(0,values.find(',')+1); } if (!value.isEmpty()) last = value; list.append(last); } } void Referee::fillMapName() { QStrList list = mapName; if (!mapName.isEmpty()) mapName.clear(); QString map; QFileInfo fileInfo; for (uint i = 0; i < list.count(); i++) { map = list.at(i); if (map.left(1) != "/" && map.left(1) != "~") map = KGlobal::dirs()->findResource("appdata", mapDirectory+map); fileInfo.setFile(map); if (!fileInfo.isReadable()) map = ""; mapName.append(map); } } void Referee::confLevels(bool defGroup) { if (defGroup || kapp->config()->hasKey("Levels")) maxLevel = kapp->config()->readNumEntry("Levels", 13); } void Referee::confMisc(bool defGroup) { if (defGroup || kapp->config()->hasKey("PixmapDirectory")) { pixmapDirectory = kapp->config()->readEntry("PixmapDirectory"); if (pixmapDirectory.left(1) != "/" && pixmapDirectory.left(1) != "~") pixmapDirectory.insert(0, "pics/"); if (pixmapDirectory.right(1) != "/") pixmapDirectory.append("/"); } if (defGroup || kapp->config()->hasKey("MapDirectory")) { mapDirectory = kapp->config()->readEntry("MapDirectory"); if (mapDirectory.left(1) != "/" && mapDirectory.left(1) != "~") mapDirectory.insert(0, "maps/"); if (mapDirectory.right(1) != "/") mapDirectory.append("/"); } if (defGroup || kapp->config()->hasKey("MapName")) fillStrList(mapName, kapp->config()->readEntry("MapName", "map"), maxLevel+1); if (defGroup || kapp->config()->hasKey("MonsterIQ")) fillArray(monsterIQ, kapp->config()->readEntry("MonsterIQ", "0,170,180,170,180,170,180"), maxLevel+1); if (defGroup || kapp->config()->hasKey("FruitIQ")) fillArray(fruitIQ, kapp->config()->readEntry("FruitIQ", "0,170,180,170,180,170,180"), maxLevel+1); if (defGroup || kapp->config()->hasKey("FruitIndex")) fillArray(fruitIndex, kapp->config()->readEntry("FruitIndex", "0"), maxLevel+1); } void Referee::confTiming(bool defGroup) { if (defGroup || kapp->config()->hasKey("SpeedMS")) fillArray(speed, kapp->config()->readEntry("SpeedMS", "20"), maxLevel+1); if (defGroup || kapp->config()->hasKey("PacmanTicks")) fillArray(pacmanTicks,kapp->config()->readEntry("PacmanTicks", "3"), maxLevel+1); if (defGroup || kapp->config()->hasKey("RemTicks")) fillArray(remTicks, kapp->config()->readEntry("RemTicks", "1"), maxLevel+1); if (defGroup || kapp->config()->hasKey("DangerousTicks")) fillArray(dangerousTicks, kapp->config()->readEntry("DangerousTicks", "3"), maxLevel+1); if (defGroup || kapp->config()->hasKey("HarmlessTicks")) fillArray(harmlessTicks, kapp->config()->readEntry("HarmlessTicks", "7,6,,5,,4"), maxLevel+1); if (defGroup || kapp->config()->hasKey("HarmlessDurationTicks")) fillArray(harmlessDurTicks, kapp->config()->readEntry("HarmlessDurationTicks", "375,,,300,,250,200,150"), maxLevel+1); if (defGroup || kapp->config()->hasKey("HarmlessWarningTicks")) fillArray(harmlessWarnTicks, kapp->config()->readEntry("HarmlessWarningTicks", "135"), maxLevel+1); if (defGroup || kapp->config()->hasKey("ArrestTicks")) fillArray(arrestTicks, kapp->config()->readEntry("ArrestTicks", "6"), maxLevel+1); if (defGroup || kapp->config()->hasKey("ArrestDurationTicks")) fillArray(arrestDurTicks, kapp->config()->readEntry("ArrestDurationTicks", "200,,,150"), maxLevel+1); if (defGroup || kapp->config()->hasKey("FruitTicks")) fillArray(fruitTicks, kapp->config()->readEntry("FruitTicks", "7,6,,5,,4"), maxLevel+1); if (defGroup || kapp->config()->hasKey("FruitAppearsTicks")) fillArray(fruitAppearsTicks, kapp->config()->readEntry("FruitAppearsTicks", "1000,,1500,2000,2500,3000,3500,4000"), maxLevel+1); if (defGroup || kapp->config()->hasKey("FruitDurationTicks")) fillArray(fruitDurTicks, kapp->config()->readEntry("FruitDurationTicks", "500,,,400,350,300,,250,200,150"), maxLevel+1); if (defGroup || kapp->config()->hasKey("FruitScoreDurationTicks")) fillArray(fruitScoreDurTicks, kapp->config()->readEntry("FruitScoreDurationTicks", "150"), maxLevel+1); if (defGroup || kapp->config()->hasKey("MonsterScoreDurationMS")) monsterScoreDurMS = kapp->config()->readNumEntry("MonsterScoreDurationMS", 1000); if (defGroup || kapp->config()->hasKey("PlayerDurationMS")) playerDurMS = kapp->config()->readNumEntry("PlayerDurationMS", 3000); if (defGroup || kapp->config()->hasKey("ReadyDurationMS")) readyDurMS = kapp->config()->readNumEntry("ReadyDurationMS", 2000); if (defGroup || kapp->config()->hasKey("GameOverDurationMS")) gameOverDurMS = kapp->config()->readNumEntry("GameOverDurationMS", 3000); if (defGroup || kapp->config()->hasKey("AfterPauseMS")) afterPauseMS = kapp->config()->readNumEntry("AfterPauseMS", 1000); if (defGroup || kapp->config()->hasKey("DyingPreAnimationMS")) dyingPreAnimationMS = kapp->config()->readNumEntry("DyingPreAnimationMS", 1000); if (defGroup || kapp->config()->hasKey("DyingAnimationMS")) dyingAnimationMS = kapp->config()->readNumEntry("DyingAnimationMS", 100); if (defGroup || kapp->config()->hasKey("DyingPostAnimationMS")) dyingPostAnimationMS = kapp->config()->readNumEntry("DyingPostAnimationMS", 500); if (defGroup || kapp->config()->hasKey("IntroAnimationMS")) introAnimationMS = kapp->config()->readNumEntry("IntroAnimationMS", 800); if (defGroup || kapp->config()->hasKey("IntroPostAnimationMS")) introPostAnimationMS = kapp->config()->readNumEntry("IntroPostAnimationMS", 1000); if (defGroup || kapp->config()->hasKey("LevelUpPreAnimationMS")) levelUpPreAnimationMS = kapp->config()->readNumEntry("LevelUpPreAnimationMS", 2000); if (defGroup || kapp->config()->hasKey("LevelUpAnimationMS")) levelUpAnimationMS = kapp->config()->readNumEntry("LevelUpAnimationMS", 2000); if (defGroup || kapp->config()->hasKey("EnergizerAnimationMS")) energizerAnimationMS = kapp->config()->readNumEntry("EnergizerAnimationMS", 200); } void Referee::confScoring(bool defGroup) { if (defGroup || kapp->config()->hasKey("PointScore")) pointScore = kapp->config()->readNumEntry("PointScore", 10); if (defGroup || kapp->config()->hasKey("EnergizerScore")) energizerScore = kapp->config()->readNumEntry("EnergizerScore", 50); if (defGroup || kapp->config()->hasKey("FruitScore")) fillArray(fruitScore, kapp->config()->readEntry("FruitScore", "100,300,500,,700,,1000,,2000,,3000,,5000"), maxLevel+1); if (defGroup || kapp->config()->hasKey("MonsterScore")) fillArray(monsterScore, kapp->config()->readEntry("MonsterScore", "200,400,800,1600"), 4); if (defGroup || kapp->config()->hasKey("ExtraLifeScore")) fillArray(extraLifeScore, kapp->config()->readEntry("ExtraLifeScore", "10000"), -1); } void Referee::confScheme() { QString oldgroup = kapp->config()->group(); QString newgroup; // if not set, read mode and scheme from the configfile if (mode == -1 && scheme == -1) { scheme = kapp->config()->readNumEntry("Scheme", -1); mode = kapp->config()->readNumEntry("Mode", -1); // if mode is not set in the defGroup-group, lookup the scheme group if (scheme != -1 || mode == -1) { newgroup.sprintf("Scheme %d", scheme); kapp->config()->setGroup(newgroup); mode = kapp->config()->readNumEntry("Mode", -1); kapp->config()->setGroup(oldgroup); } } confLevels(); if (mode != -1) { newgroup.sprintf("Mode %d", mode); kapp->config()->setGroup(newgroup); confLevels(FALSE); } if (scheme != -1) { newgroup.sprintf("Scheme %d", scheme); kapp->config()->setGroup(newgroup); confLevels(FALSE); } kapp->config()->setGroup(oldgroup); confMisc(); confTiming(); confScoring(); if (mode != -1) { newgroup.sprintf("Mode %d", mode); kapp->config()->setGroup(newgroup); confMisc(FALSE); confTiming(FALSE); confScoring(FALSE); } if (scheme != -1) { newgroup.sprintf("Scheme %d", scheme); kapp->config()->setGroup(newgroup); confMisc(FALSE); confTiming(FALSE); confScoring(FALSE); } fillMapName(); kapp->config()->setGroup(oldgroup); } void Referee::setScheme(int Scheme, int Mode, Bitfont *font) { mode = Mode; scheme = Scheme; confScheme(); pix->setScheme(scheme, mode, font); pacman->setMaxPixmaps(pix->maxPixmaps(PacmanPix)); fruit->setMaxPixmaps(pix->maxPixmaps(FruitPix)); for (Monster *m = monsters->first(); m != 0; m = monsters->next()) if (m) m->setMaxPixmaps(pix->maxPixmaps(MonsterPix), pix->maxPixmaps(EyesPix)); for (Energizer *e = energizers->first(); e != 0; e = energizers->next()) if (e) e->setMaxPixmaps(pix->maxPixmaps(EnergizerPix)); if (gameState.testBit(Introducing)) for (int i = 0; i < (gameState.testBit(Init) ? timerCount : 15); i++) introPaint(i); setFixedSize(pix->levelPix().size()); repaint(); } void Referee::keyPressEvent( QKeyEvent *k ) { if (gameState.testBit(Paused) || gameState.testBit(HallOfFame) || gameState.testBit(Demonstration) || gameState.testBit(Dying) || gameState.testBit(Ready) || gameState.testBit(LevelDone) || !gameState.testBit(Playing)) return; uint key = k->key(); if (key == UpKey) pacman->setDirection(N); else if (key == DownKey) pacman->setDirection(S); else if (key == RightKey) pacman->setDirection(E); else if (key == LeftKey) pacman->setDirection(W); #ifdef CHEATS else if (key == Key_L) { printf("levelUp()\n"); levelUp(); } else if (key == Key_F) { printf("fruit->move(TRUE)\n"); fruit->move(TRUE); repaint(FALSE); } else if (key == Key_E) { printf("setLifes(++lifes)\n"); emit setLifes(++lifes); } #endif else { k->ignore(); return; } k->accept(); } void Referee::score(int p) { if (!gameState.testBit(Playing)) return; if ((points += p) < 0) points = 0; emit setPoints(points); if (points >= nextExtraLifeScore) { emit setLifes(++lifes); if (extraLifeScoreIndex < (int) extraLifeScore.size()-1) extraLifeScoreIndex++; if (extraLifeScore[extraLifeScoreIndex] < 0) nextExtraLifeScore = extraLifeScore[extraLifeScoreIndex] * -1; else nextExtraLifeScore += extraLifeScore[extraLifeScoreIndex]; } } void Referee::eaten() { if (gameState.testBit(Ready)) return; stop(); if (monstersEaten < 4) monstersEaten++; gameState.setBit(Scoring); score(monsterScore[monstersEaten-1]); repaint(pix->rect(pix->rect(pacman->position(), MonsterPix), pix->rect(pacman->position(), MonsterScorePix, monstersEaten-1))); if (--timerCount > 0) QTimer::singleShot( monsterScoreDurMS, this, SLOT(eaten())); else { for (Monster *m = monsters->first(); m != 0; m = monsters->next()) if (m && m->direction() == X && !gameState.testBit(Introducing)) m->setDirection(N); if (monstersEaten != 4 || !gameState.testBit(Introducing)) QTimer::singleShot( monsterScoreDurMS, this, SLOT(start())); } } void Referee::toggleHallOfFame() { gameState.toggleBit(HallOfFame); } void Referee::hallOfFame() { if (gameState.testBit(HallOfFame)) // If the HallOfFame is switched on manually, toggle the toggleHallOfFame(); // bit twice. emit setLevel(0); // Clear status display for hall of fame emit setScore(level, 0); emit forcedGameHighscores(); } void Referee::pause() { static int pausedTimer = 0; if (!gameState.testBit(Paused)) { pausedTimer = gameTimer; stop(); stopEnergizer(); gameState.setBit(Paused); repaint(pix->rect((BoardWidth*BoardHeight)/2-BoardWidth, i18n("PAUSED")), FALSE); } else { gameState.clearBit(Paused); repaint(pix->rect((BoardWidth*BoardHeight)/2-BoardWidth, i18n("PAUSED")), FALSE); if (pausedTimer) { pausedTimer = 0; start(); } // manual pause deactivating (also) deactivates a focusedPause focusedPause = false; } //0.3.2 emit gamePause(); } void Referee::intro() { stop(); stopEnergizer(); bool paused = gameState.testBit(Paused); gameState.fill(FALSE); gameState.setBit(Introducing); gameState.setBit(Init); if (paused) gameState.setBit(Paused); level = 0; emit setLevel(level); board->init(Intro); pix->setLevel(level); initPacman(); initFruit(); initMonsters(); initEnergizers(); repaint(); monstersEaten = 0; timerCount = 0; introPlay(); } void Referee::introMonster(int id) { Monster *m = new Monster(board, id); m->setPosition((10+id*6)*BoardWidth+10); m->setDirection(E); m->setDangerous(dangerousTicks[level], monsterIQ[level]); m->setMaxPixmaps(pix->maxPixmaps(MonsterPix), pix->maxPixmaps(EyesPix)); if (m->body() != -1) pix->draw(m->position(), RoomPix, MonsterPix, m->body()); if (m->eyes() != -1) pix->draw(m->position(), RoomPix, EyesPix, m->eyes()); repaint(pix->rect(m->position(), MonsterPix), FALSE); m->setPosition(OUT); } void Referee::introPaint(int t) { QString pts; switch (t) { case 0 : repaint(pix->draw(16, 6, RoomPix, i18n("CHARACTER"), WHITE, QColor(), AlignLeft), FALSE); repaint(pix->draw(36, 6, RoomPix, i18n("/"), WHITE, QColor(), AlignLeft), FALSE); repaint(pix->draw(40, 6, RoomPix, i18n("NICKNAME"), WHITE, QColor(), AlignLeft), FALSE); break; case 1 : introMonster(0); break; case 2 : repaint(pix->draw(16, 10, RoomPix, i18n("-SHADOW"), RED, QColor(), AlignLeft), FALSE); break; case 3 : repaint(pix->draw(38, 10, RoomPix, i18n("\"BLINKY\""), RED, QColor(), AlignLeft), FALSE); break; case 4 : introMonster(1); break; case 5 : repaint(pix->draw(16, 16, RoomPix, i18n("-SPEEDY"), PINK, QColor(), AlignLeft), FALSE); break; case 6 : repaint(pix->draw(38, 16, RoomPix, i18n("\"PINKY\""), PINK, QColor(), AlignLeft), FALSE); break; case 7 : introMonster(2); break; case 8 : repaint(pix->draw(16, 22, RoomPix, i18n("-BASHFUL"), CYAN, QColor(), AlignLeft), FALSE); break; case 9 : repaint(pix->draw(38, 22, RoomPix, i18n("\"INKY\""), CYAN, QColor(), AlignLeft), FALSE); break; case 10 : introMonster(3); break; case 11 : repaint(pix->draw(16, 28, RoomPix, i18n("-POKEY"), ORANGE, QColor(), AlignLeft), FALSE); break; case 12 : repaint(pix->draw(38, 28, RoomPix, i18n("\"CLYDE\""), ORANGE, QColor(), AlignLeft), FALSE); break; case 13 : pts.sprintf("%d", pointScore); repaint(pix->draw(28, 44, RoomPix, pts.data(), WHITE, QColor(), AlignRight), FALSE); repaint(pix->draw(31, 44, RoomPix, "\x1C\x1D\x1E", WHITE, QColor(), AlignLeft), FALSE); pts.sprintf("%d", energizerScore); repaint(pix->draw(28, 48, RoomPix, pts.data(), WHITE, QColor(), AlignRight), FALSE); repaint(pix->draw(31, 48, RoomPix, "\x1C\x1D\x1E", WHITE, QColor(), AlignLeft), FALSE); break; case 14 : // "@ 1980 MIDWAY MFG.CO." repaint(pix->draw(30, 58, RoomPix, "© 1998-2003 J.THÖNNISSEN", PINK), FALSE); break; } } void Referee::introPlay() { if (!gameState.testBit(Introducing) || gameState.testBit(Ready)) return; if (gameState.testBit(Paused) || gameState.testBit(HallOfFame)) { QTimer::singleShot(afterPauseMS, this, SLOT(introPlay())); return; } if (!gameState.testBit(Init)) { if (monstersEaten == 4) { stop(); QTimer::singleShot(introPostAnimationMS, this, SLOT(demo())); } if (pacman->direction() == W) { int id = -1; if (pacman->position() == 37*BoardWidth-6) id = 0; else if (board->isMonster(37*BoardWidth-6)) for (Monster *m = monsters->first(); m != 0; m = monsters->next()) if (m && m->position() == 37*BoardWidth-6) { id = m->id(); id++; break; } if (id >= 0 && id <= 4) for (Monster *m = monsters->first(); m != 0; m = monsters->next()) if (m && m->id() == id && m->position() == OUT) { m->setPosition(37*BoardWidth-1); m->setDirection(W); m->setDangerous(dangerousTicks[level], monsterIQ[level]); board->set(37*BoardWidth-1, monsterhome, id); repaint(pix->rect(m->position(), MonsterPix)); break; } } return; } if (timerCount < 15) introPaint(timerCount); switch (timerCount) { case 13 : board->set(44*BoardWidth+22, Point); pix->drawPoint(44*BoardWidth+22); repaint(pix->rect(44*BoardWidth+22, PointPix), FALSE); energizers->at(0)->setPosition(48*BoardWidth+22); energizers->at(0)->setOn(); repaint(pix->rect(48*BoardWidth+22, EnergizerPix), FALSE); break; case 14 : energizers->at(1)->setPosition(36*BoardWidth+10); energizers->at(1)->setOn(); repaint(pix->rect(36*BoardWidth+10, EnergizerPix), FALSE); for (int pos = 8; pos < BoardWidth; pos++) { board->set(34*BoardWidth+pos, out); board->set(38*BoardWidth+pos, out); } board->set(36*BoardWidth+8, out); break; case 15 : gameState.clearBit(Init); initPacman(); pacman->setDemo(TRUE); pacman->setPosition(37*BoardWidth-1); repaintFigures(); start(); return; } if (timerCount++ < 15) QTimer::singleShot(introAnimationMS, this, SLOT(introPlay())); } void Referee::demo() { if (gameState.testBit(Ready)) return; if (gameState.testBit(Paused) || gameState.testBit(HallOfFame)) { QTimer::singleShot(afterPauseMS, this, SLOT(demo())); return; } stop(); stopEnergizer(); gameState.fill(FALSE); gameState.setBit(Init); gameState.setBit(Demonstration); level = 0; emit setLevel(level); board->init(Demo, mapName.at(0)); pix->setLevel(level); initPacman(); initFruit(); initMonsters(); initEnergizers(); gameState.clearBit(Init); repaint(); timerCount = 0; QTimer::singleShot(playerDurMS, this, SLOT(start())); } void Referee::play() { stop(); stopEnergizer(); gameState.fill(FALSE); gameState.setBit(Init); gameState.setBit(Playing); gameState.setBit(Player); gameState.setBit(Ready); lifes = 3; level = 1; points = 0; extraLifeScoreIndex = 0; nextExtraLifeScore = extraLifeScore[extraLifeScoreIndex]; if (nextExtraLifeScore < 0) nextExtraLifeScore *= -1; board->init(Level, mapName.at(level)); pix->setLevel(level); initPacman(); initFruit(); initMonsters(); initEnergizers(); repaint(); //0.3.2 emit toggleNew(); emit setLifes(lifes); emit setLevel(level); emit setPoints(points); repaint(pix->rect(board->position(monsterhome, 0), i18n("PLAYER ONE")), FALSE); repaint(pix->rect(board->position(fruithome), i18n("READY!")), FALSE); timerCount = 0; QTimer::singleShot(playerDurMS, this, SLOT(ready())); } void Referee::ready() { if (gameState.testBit(Paused) || gameState.testBit(HallOfFame)) { QTimer::singleShot(afterPauseMS, this, SLOT(ready())); return; } if (gameState.testBit(Player)) { emit setLifes(--lifes); gameState.clearBit(Player); gameState.clearBit(Init); repaint(pix->rect(board->position(monsterhome, 0), i18n("PLAYER ONE")), FALSE); repaintFigures(); QTimer::singleShot(playerDurMS, this, SLOT(ready())); return; } if (gameState.testBit(Ready)) { gameState.clearBit(Ready); repaint(pix->rect(board->position(fruithome), i18n("READY!")), FALSE); start(); } else { gameState.setBit(Ready); gameState.clearBit(Init); repaint(pix->rect(board->position(fruithome), i18n("READY!")), FALSE); QTimer::singleShot(readyDurMS, this, SLOT(ready())); } } void Referee::levelUp() { stop(); stopEnergizer(); gameState.setBit(LevelDone); pacman->setPosition(pacman->position()); // set mouthPosition to "0" repaint(pix->rect(pacman->position(), PacmanPix)); timerCount = 0; QTimer::singleShot(levelUpPreAnimationMS, this, SLOT(levelUpPlay())); } void Referee::levelUpPlay() { if (gameState.testBit(Ready)) return; if (gameState.testBit(Paused) || gameState.testBit(HallOfFame)) { QTimer::singleShot(afterPauseMS, this, SLOT(levelUpPlay())); return; } switch (timerCount) { case 0 : gameState.setBit(Init); setOnEnergizers(); repaintFigures(); break; case 1 : gameState.clearBit(LevelDone); repaint(pix->rect(pacman->position(), PacmanPix)); break; } if (timerCount++ < 2) { QTimer::singleShot(levelUpAnimationMS, this, SLOT(levelUpPlay())); return; } gameState.clearBit(Init); if (gameState.testBit(Demonstration)) { hallOfFame(); return; } if (level < maxLevel) level++; board->init(Level, mapName.at(level)); pix->setLevel(level); initPacman(); initFruit(); initMonsters(); initEnergizers(); repaint(); emit setLevel(level); ready(); } void Referee::start() { if (gameState.testBit(Ready)) return; if (gameState.testBit(Paused) || gameState.testBit(HallOfFame)) { QTimer::singleShot(afterPauseMS, this, SLOT(start())); return; } if (gameState.testBit(Scoring)) { gameState.clearBit(Scoring); repaint(pix->rect(pix->rect(pacman->position(), MonsterPix), pix->rect(pacman->position(), MonsterScorePix, monstersEaten-1))); } if (!gameTimer) gameTimer = startTimer( speed [level] ); if (!energizerTimer) energizerTimer = startTimer( energizerAnimationMS ); } void Referee::start(int t) { gameTimer = startTimer(t); } void Referee::stop() { if (gameTimer) { killTimer (gameTimer); gameTimer = 0; } } void Referee::stopEnergizer() { if (energizerTimer) { killTimer (energizerTimer); energizerTimer = 0; } } void Referee::killed() { if (gameState.testBit(Ready)) return; if (!gameState.testBit(Dying)) { gameState.setBit(Dying); pacman->setDirection(X, TRUE); for (Monster *m = monsters->first(); m != 0; m = monsters->next()) if (m) m->setDirection(X); QTimer::singleShot(dyingPreAnimationMS, this, SLOT(killed())); } else { stop(); if (gameState.testBit(Paused) || gameState.testBit(HallOfFame)) { QTimer::singleShot(afterPauseMS, this, SLOT(killed())); return; } gameState.setBit(Init); repaintFigures(); timerCount = 0; killedPlay(); } } void Referee::killedPlay() { if (!gameState.testBit(Dying) || gameState.testBit(Ready)) return; if (gameState.testBit(Paused) || gameState.testBit(HallOfFame)) { QTimer::singleShot(afterPauseMS, this, SLOT(killedPlay())); return; } if (timerCount <= pix->maxPixmaps(DyingPix)) { repaint(pix->rect(pacman->position(), PacmanPix), FALSE); if (timerCount >= pix->maxPixmaps(DyingPix)-1 || timerCount == 0) QTimer::singleShot(dyingPostAnimationMS, this, SLOT(killedPlay())); else QTimer::singleShot(dyingAnimationMS, this, SLOT(killedPlay())); timerCount++; } else { gameState.clearBit(Dying); stopEnergizer(); if (lifes == 0) { gameState.setBit(GameOver); gameState.clearBit(Playing); for (int e = 0; e < board->energizers(); e++) { energizers->at(e)->setOff(); repaint(pix->rect(board->position(energizer, e), EnergizerPix), FALSE); } repaint(pix->rect(board->position(fruithome), i18n("GAME OVER")), FALSE); QTimer::singleShot(gameOverDurMS, this, SLOT(hallOfFame())); } else { gameState.clearBit(Init); initPacman(); initFruit(); initMonsters(); initEnergizers(); emit setLifes(--lifes); repaintFigures(); ready(); } } } void Referee::initPacman() { pacman->setMaxPixmaps(pix->maxPixmaps(PacmanPix)); pacman->setDemo(gameState.testBit(Demonstration)); pacman->setPosition(board->position(pacmanhome)); pacman->setDirection(W, TRUE); pacman->setAlive(pacmanTicks[level]); } void Referee::initFruit(bool fullInitialization) { if (fullInitialization) { fruit->setMaxPixmaps(pix->maxPixmaps(FruitPix)); if (fruitIndex[level] == 0) fruit->setLevel(level, fruitAppearsTicks[level], fruitDurTicks[level], fruitTicks[level]); else if (fruitIndex[level] < 0) fruit->setLevel(pix->maxPixmaps(FruitPix)+1, fruitAppearsTicks[level], fruitDurTicks[level], fruitTicks[level]); else fruit->setLevel(fruitIndex[level], fruitAppearsTicks[level], fruitDurTicks[level], fruitTicks[level]); } if (board->tunnels() > 0) fruit->setMovement(board->position(tunnel, rand() % board->tunnels()), board->position(tunnel, rand() % board->tunnels()), fruitIQ[level]); } void Referee::initMonsters() { if( !monsters->isEmpty()) monsters->clear(); if( !monsterRect->isEmpty()) monsterRect->clear(); for (int id = 0; id < (gameState.testBit(Introducing) ? 4 : board->monsters()); id++) { Monster *m = new Monster(board, id); monsters->append(m); QRect *r = new QRect(); monsterRect->append(r); if (!gameState.testBit(Introducing)) { m->setFreedom(board->position(prisonexit)); m->setDangerous(dangerousTicks[level], monsterIQ[level]); if (id == 0) m->setPrison(board->position(prisonentry)); else { m->setPrison(board->position(monsterhome, id)); m->setArrested(arrestTicks[level], arrestDurTicks[level]*id); } m->setPosition(board->position(monsterhome, id)); switch(id) { case 0 : m->setDirection(W); break; case 1 : m->setDirection(N); break; default : m->setDirection(S); } } m->setMaxPixmaps(pix->maxPixmaps(MonsterPix), pix->maxPixmaps(EyesPix)); } } void Referee::initEnergizers() { if( !energizers->isEmpty()) energizers->clear(); if( !energizerRect->isEmpty()) energizerRect->clear(); for (int id = 0; id < (gameState.testBit(Introducing) ? 2 : board->energizers()); id++) { Energizer *e = new Energizer(board); energizers->append(e); QRect *r = new QRect(); energizerRect->append(r); if (!gameState.testBit(Introducing)) { e->setPosition(board->position(energizer, id)); e->setOn(); } e->setMaxPixmaps(pix->maxPixmaps(EnergizerPix)); } } void Referee::setOnEnergizers() { for (int e = 0; e < board->energizers(); e++) { energizers->at(e)->setOn(); } } void Referee::setFocusOutPause(bool FocusOutPause) { focusOutPause = FocusOutPause; } void Referee::setFocusInContinue(bool FocusInContinue) { focusInContinue = FocusInContinue; } void Referee::focusInEvent(QFocusEvent *) { if (focusInContinue && focusedPause && gameState.testBit(Paused) && gameState.testBit(Playing)) { focusedPause = false; // this also calls the Referee::pause() function emit focusedGamePause(); } } void Referee::focusOutEvent(QFocusEvent *) { if (focusOutPause && !focusedPause && !gameState.testBit(Paused) && gameState.testBit(Playing)) { focusedPause = true; // this also calls the Referee::pause() function emit focusedGamePause(); } }