diff options
Diffstat (limited to 'tdepacman')
38 files changed, 6771 insertions, 0 deletions
diff --git a/tdepacman/CMakeL10n.txt b/tdepacman/CMakeL10n.txt new file mode 100644 index 0000000..3e90f50 --- /dev/null +++ b/tdepacman/CMakeL10n.txt @@ -0,0 +1,8 @@ +##### create translation templates ############## + +tde_l10n_create_template( "messages/tdepacman" ) + +tde_l10n_create_template( + CATALOG "desktop_files/tdepacman.desktop/" + SOURCES tdepacman.desktop +) diff --git a/tdepacman/CMakeLists.txt b/tdepacman/CMakeLists.txt new file mode 100644 index 0000000..f01bedd --- /dev/null +++ b/tdepacman/CMakeLists.txt @@ -0,0 +1,63 @@ +include_directories( + ${CMAKE_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} + ${TDEGAMES_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} + ${TDE_LIB_DIR} + ${TDEGAMES_LIBRARY_DIRS} +) + + +##### tdepacman (executable) + +tde_add_executable( ${PROJECT_NAME} AUTOMOC + + SOURCES + tdepacmanview.cpp + referee.cpp + status.cpp + painter.cpp + score.cpp + pacman.cpp + monster.cpp + keys.cpp + fruit.cpp + energizer.cpp + board.cpp + bitfont.cpp + tdepacman.cpp + main.cpp + LINK + tdeui-shared + tdecore-shared + ${TDEGAMES_LIBRARIES} + + DESTINATION ${BIN_INSTALL_DIR} +) + + +##### other data + +install( + FILES tdepacmanui.rc + DESTINATION ${DATA_INSTALL_DIR}/${PROJECT_NAME} +) + +install( + FILES tdepacmanrc + DESTINATION ${CONFIG_INSTALL_DIR} +) + + +tde_create_translated_desktop( ${PROJECT_NAME}.desktop ) + + +##### icons + +tde_install_icons( ${PROJECT_NAME} ) diff --git a/tdepacman/bitfont.cpp b/tdepacman/bitfont.cpp new file mode 100644 index 0000000..f1535fb --- /dev/null +++ b/tdepacman/bitfont.cpp @@ -0,0 +1,71 @@ +#include "bitfont.h" + +Bitfont::Bitfont(TQString fontname, uchar firstChar, uchar lastChar) +{ + if (!fontname.isEmpty()) + font.load(fontname); + if (font.width() == font.height()) { + fontWidth = fontHeight = font.width() / 16; + fontFirstChar = 1; + fontLastChar = 255; + } else { + fontWidth = font.width()/(lastChar-firstChar+1); + fontHeight = font.height(); + fontFirstChar = firstChar; + fontLastChar = lastChar; + } +} + +TQRect Bitfont::rect(TQString str) +{ + return TQRect(0, 0, str.length()*fontWidth, fontHeight); +} + +TQPixmap Bitfont::text(TQString str, TQColor fg, TQColor bg) +{ + TQPixmap FG(str.length()*fontWidth, fontHeight); + TQBitmap MASK(str.length()*fontWidth, fontHeight, TRUE); + + const uchar *s = reinterpret_cast<const unsigned char *>(str.latin1()); + for (uint i = 0; i < str.length(); i++) { + if (font.width() == font.height()) + bitBlt(&MASK, i*fontWidth, 0, &font, + (*s%16)*fontWidth, (*s/16)*fontWidth, fontWidth, fontHeight); + else + if (*s >= fontFirstChar && *s <= fontLastChar) + bitBlt(&MASK, i*fontWidth, 0, &font, + (*s-fontFirstChar)*fontWidth, 0, fontWidth, fontHeight); + s++; + } + + FG.fill(fg); + FG.setMask(MASK); + + if (bg.isValid()) { + TQPixmap BG(str.length()*fontWidth, fontHeight); + BG.fill(bg); + bitBlt(&BG, 0, 0, &FG); + return BG; + } else + return FG; +} + +uchar Bitfont::firstChar() +{ + return fontFirstChar; +} + +uchar Bitfont::lastChar() +{ + return fontLastChar; +} + +int Bitfont::width() +{ + return fontWidth; +} + +int Bitfont::height() +{ + return fontHeight; +} diff --git a/tdepacman/bitfont.h b/tdepacman/bitfont.h new file mode 100644 index 0000000..029383e --- /dev/null +++ b/tdepacman/bitfont.h @@ -0,0 +1,30 @@ +#ifndef BITFONT_H +#define BITFONT_H + +#include <tqstring.h> +#include <tqbitmap.h> +#include <tqpixmap.h> +#include <tqrect.h> + +#include "colors.h" + +class Bitfont +{ +public: + Bitfont(TQString fontname, uchar firstChar, uchar lastChar); + + TQPixmap text(TQString str, TQColor fg = BLACK, TQColor bg = TQColor()); + TQRect rect(TQString str); + int width(); + int height(); + uchar firstChar(); + uchar lastChar(); +private: + TQBitmap font; + int fontWidth; + int fontHeight; + uchar fontFirstChar; + uchar fontLastChar; +}; + +#endif // BITFONT_H diff --git a/tdepacman/bitmaps.h b/tdepacman/bitmaps.h new file mode 100644 index 0000000..f430384 --- /dev/null +++ b/tdepacman/bitmaps.h @@ -0,0 +1,67 @@ +static unsigned char demo_bits[] = { + "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + "++*******************************************************++" + "+*********************************************************+" + "+** *** **+" + "+** . . . . . . . . . . . . *** . . . . . . . . . . . . **+" + "+** *** **+" + "+** . ******* . ********* . *** . ********* . ******* . **+" + "+** ******* ********* *** ********* ******* **+" + "+** o ******* . ********* . *** . ********* . ******* o **+" + "+** ******* ********* *** ********* ******* **+" + "+** . ******* . ********* . *** . ********* . ******* . **+" + "+** **+" + "+** . . . . . . . . . . . . . . . . . . . . . . . . . . **+" + "+** **+" + "+** . ******* . *** . *************** . *** . ******* . **+" + "+** ******* *** *************** *** ******* **+" + "+** . ******* . *** . *************** . *** . ******* . **+" + "+** *** *** *** **+" + "+** . . . . . . *** . . . . *** . . . . *** . . . . . . **+" + "+** *** *** *** **+" + "+************ . ********* *** ********* . ************+" + "++*********** ********* *** ********* ***********++" + "+++++++++++** . ********* *** ********* . **+++++++++++" + "+++++++++++** *** *** **+++++++++++" + "+++++++++++** . *** 0 *** . **+++++++++++" + "+++++++++++** *** *** **+++++++++++" + "+++++++++++** . *** ######---###### *** . **+++++++++++" + "+************ *** ######---###### *** ************+" + "+************ . *** ## ## *** . ************+" + " ## ## " + " . ## 2 1 3 ## . " + " ## ## " + "+************ . *** ## ## *** . ************+" + "+************ *** ############### *** ************+" + "+++++++++++** . *** ############### *** . **+++++++++++" + "+++++++++++** *** *** **+++++++++++" + "+++++++++++** . *** F *** . **+++++++++++" + "+++++++++++** *** *** **+++++++++++" + "+++++++++++** . *** *************** *** . **+++++++++++" + "++*********** *** *************** *** ***********++" + "+************ . *** *************** *** . ************+" + "+** *** **+" + "+** . . . . . . . . . . . . *** . . . . . . . . . . . . **+" + "+** *** **+" + "+** . ******* . ********* . *** . ********* . ******* . **+" + "+** ******* ********* *** ********* ******* **+" + "+** . ******* . ********* . *** . ********* . ******* . **+" + "+** *** *** **+" + "+** o . . *** . . . . . . . P . . . . . . . *** . . o **+" + "+** *** *** **+" + "+****** . *** . *** . *************** . *** . *** . ******+" + "+****** *** *** *************** *** *** ******+" + "+****** . *** . *** . *************** . *** . *** . ******+" + "+** *** *** *** **+" + "+** . . . . . . *** . . . . *** . . . . *** . . . . . . **+" + "+** *** *** *** **+" + "+** . ******************* . *** . ******************* . **+" + "+** ******************* *** ******************* **+" + "+** . ******************* . *** . ******************* . **+" + "+** **+" + "+** . . . . . . . . . . . . . . . . . . . . . . . . . . **+" + "+** **+" + "+*********************************************************+" + "++*******************************************************++" + "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" +}; diff --git a/tdepacman/board.cpp b/tdepacman/board.cpp new file mode 100644 index 0000000..621a086 --- /dev/null +++ b/tdepacman/board.cpp @@ -0,0 +1,421 @@ +#include <kapp.h> + +#include <tdelocale.h> + +#include <tqrect.h> +#include <tqregexp.h> +#include <tqmessagebox.h> +#include <tqfile.h> +#include <tqtextstream.h> + +#include "board.h" +#include "bitmaps.h" + +Board::Board(int size) : TQMemArray<int> (size) +{ + sz = size; // set size of board + + map = ""; + mapName = ""; // no map loaded so far + + init(None); // initialize varibales +} + +void Board::init(Image image, TQString levelName) +{ + prisonEntry = OUT; + prisonExit = OUT; + fruitHome = OUT; + fruitPosition = OUT; + pacmanHome = OUT; + pacmanPosition = OUT; + for (int m = 0; m < 8; m++) { + monsterHome[m] = OUT; + monsterPosition[m] = OUT; + } + for (int e = 0; e < 8; e++) { + energizerPosition[e] = OUT; + } + for (int e = 0; e < 8; e++) { + tunnelPosition[e] = OUT; + } + + fill(0); + numPoints = 0; + numEnergizers = 0; + numMonsters = 0; + numTunnels = 0; + + if (!levelName.isNull() && !levelName.isEmpty()) + if (mapName == levelName) + image = File; + else { + TQFile levelFile(levelName); + if (!levelFile.open(IO_ReadOnly)) { + + TQString msg = i18n("The levelmap could not be constructed.\n\n" + "The file '@LEVELNAME@' does not exist,\n" + "or could not be opened for reading."); + msg.replace(TQRegExp("@LEVELNAME@"), levelName); + // TQMessageBox::information(0, i18n("Initialization Error"), msg); + printf("%s\n", msg.local8Bit().data()); + } else { + map.fill(' ', BoardHeight*BoardWidth); + int height = 0; + + TQTextStream levelStream(&levelFile); + while (!levelStream.eof() && height < BoardHeight) { + TQString line = levelStream.readLine(); + + if (line.find(TQRegExp("^ *;")) == -1) { + + line.replace(TQRegExp(";.*"), ""); // strip off comments + line.replace(TQRegExp("\" *$"), ""); // strip off trailing " + line.replace(TQRegExp("^ *\""), ""); // strip off leading " + + map.replace(height*BoardWidth, + (line.length() > BoardWidth) ? BoardWidth : line.length(), + line.latin1()); + + height++; + } + } + mapName = levelName; + levelFile.close(); + image = File; + } + } + + switch (image) { + case Intro : // setup(demo_bits); + break; + case Demo : setup(demo_bits); + break; + case Level : setup(demo_bits); + break; + case File : setup(reinterpret_cast<const unsigned char *>(map.latin1())); + break; + default : break; + } +} + +void Board::setup(const uchar *buf) +{ + for ( int index = 0; buf[index] != 0 && index < BoardWidth*BoardHeight; index++ ) { + switch (buf[index]) { + case '*' : set(index, brick); break; + case '+' : set(index, out); break; + case '#' : set(index, prison); break; + case '-' : set(index, gate); break; + case 'E' : set(index, tunnel); break; + case '.' : set(index, Point); break; + case 'o' : set(index, energizer); break; + case 'I' : set(index, prisonentry); break; + case 'O' : set(index, prisonexit); break; + case 'F' : set(index, fruithome); break; + case 'P' : set(index, pacmanhome); break; + default : if (buf[index] >= '0' && buf[index] <= '7') { + set(index, monsterhome, buf[index]-(uchar)'0'); + } + } + } +} + +bool Board::inBounds(int pos) +{ + return ( pos < 0 || pos > sz-1 ? FALSE : TRUE); +} + +void Board::set(int pos, Square sq, int m) +{ + if (inBounds(pos)) + switch (sq) { + case out : at(pos) = OUT; break; + case Point : at(pos) |= pointBit; numPoints++; break; + case tunnel : at(pos) = sq; + for (int e = 0; e < numTunnels; e++) { // if tunnel is already on board + if (tunnelPosition[e] == pos) // don't do it again. + pos = OUT; + } + if (pos != OUT) { + tunnelPosition[numTunnels] = pos; + numTunnels++; + } + break; + case energizer : at(pos) |= energizerBit; + for (int e = 0; e < numEnergizers; e++) { + if (energizerPosition[e] == pos) + pos = OUT; + } + if (pos != OUT) { + energizerPosition[numEnergizers] = pos; + numEnergizers++; + } + break; + case fruit : at(pos) |= fruitBit; fruitPosition = pos; break; + case pacman : at(pos) |= pacmanBit; pacmanPosition = pos; break; + case monster : at(pos) |= (monsterBit << m); + monsterPosition[m] = pos; break; + case prisonentry : prisonEntry = pos; at(pos) = empty; break; + case prisonexit : prisonExit = pos; at(pos) = empty; break; + case fruithome : fruitHome = pos; at(pos) = empty; break; + case pacmanhome : pacmanHome = pos; at(pos) = empty; break; + case monsterhome : monsterHome[m] = pos; at(pos) = empty; + if (m == 0 && prisonExit == OUT) + prisonExit = pos; + if (m == 1 && prisonEntry == OUT) + prisonEntry = pos; + numMonsters++; + break; + default : at(pos) = sq; + } +} + +void Board::reset(int pos, Square sq, int m) +{ + bool found = FALSE; + if (inBounds(pos)) + switch (sq) { + case out : at(pos) = empty; break; + case Point : at(pos) &= ~ pointBit; numPoints--; break; + case energizer : at(pos) &= ~ energizerBit; + for (int e = 0; e < numEnergizers; e++) { // delete the position of the eaten + if (found) // energizer in the position array + energizerPosition[e-1] = energizerPosition[e]; + if (energizerPosition[e] == pos) + found = TRUE; + } + energizerPosition[numEnergizers--] = OUT; + break; + case fruit : at(pos) &= ~ fruitBit; fruitPosition = OUT; break; + case pacman : at(pos) &= ~ pacmanBit; pacmanPosition = OUT; break; + case monster : at(pos) &= ~ (monsterBit << m); + monsterPosition[m] = OUT; break; + default : at(pos) = at(pos) & varBits; + } +} + +int Board::position(Square sq, int m) +{ + switch(sq) { + case prisonentry : return prisonEntry; + case prisonexit : return prisonExit; + case fruit : return fruitPosition; + case fruithome : return fruitHome; + case pacman : return pacmanPosition; + case pacmanhome : return pacmanHome; + case monster : return monsterPosition[m]; + case monsterhome : return monsterHome[m]; + case energizer : return energizerPosition[m]; + case tunnel : return tunnelPosition[m]; + default : return OUT; + } +} + +bool Board::isOut(int pos) +{ + if (inBounds(pos)) + return (at(pos) == OUT ? TRUE : FALSE); + return TRUE; +} + +bool Board::isEmpty(int pos) +{ + if (inBounds(pos)) + return ((at(pos) & fixBits) == empty ? TRUE : FALSE); + return TRUE; +} + +bool Board::isBrick(int pos) +{ + if (inBounds(pos)) + return ((at(pos) & fixBits) == brick ? TRUE : FALSE); + return FALSE; +} + +bool Board::isPrison(int pos) +{ + if (inBounds(pos)) + return ((at(pos) & fixBits) == prison ? TRUE : FALSE); + return FALSE; +} + +bool Board::isGate(int pos) +{ + if (inBounds(pos)) + return ((at(pos) & fixBits) == gate ? TRUE : FALSE); + return FALSE; +} + +bool Board::isTunnel(int pos) +{ + if (inBounds(pos)) + return ((at(pos) & fixBits) == tunnel ? TRUE : FALSE); + return FALSE; +} + +bool Board::isPoint(int pos) +{ + if (inBounds(pos) && at(pos) != OUT) + return ((at(pos) & pointBit) != 0 ? TRUE : FALSE); + return FALSE; +} + +bool Board::isEnergizer(int pos) +{ + if (inBounds(pos) && at(pos) != OUT) + return ((at(pos) & energizerBit) != 0 ? TRUE : FALSE); + return FALSE; +} + +bool Board::isFruit(int pos) +{ + if (inBounds(pos) && at(pos) != OUT) + return ((at(pos) & fruitBit) != 0 ? TRUE : FALSE); + return FALSE; +} + +bool Board::isPacman(int pos) +{ + if (inBounds(pos) && at(pos) != OUT) + return ((at(pos) & pacmanBit) != 0 ? TRUE : FALSE); + return FALSE; +} + +bool Board::isMonster(int pos) +{ + if (inBounds(pos) && at(pos) != OUT) + return ((at(pos) & monsterBits) != 0 ? TRUE : FALSE); + return FALSE; +} + +bool Board::isWay(int pos, int dir, Square sq) { + int p1 = move(pos, dir, 2); + if (p1 == OUT) + return (sq == out ? TRUE : FALSE); + int p2, p3; + if (dir == N || dir == S) { + p2 = move(p1, E); + p3 = move(p1, W); + } else { + p2 = move(p1, N); + p3 = move(p1, S); + } + switch (sq) { + case out : return isOut(p1) | isOut(p2) | isOut(p3); + case empty : return isEmpty(p1) & isEmpty(p2) & isEmpty(p3); + case brick : return isBrick(p1) | isBrick(p2) | isBrick(p3); + case prison : return isPrison(p1) | isPrison(p2) | isPrison(p3); + case gate : return isGate(p1) & isGate(p2) & isGate(p3); + case tunnel : return isTunnel(p1) & + (isTunnel(p2) || isEmpty(p2)) & + (isTunnel(p3) || isEmpty(p3)); + default : return FALSE; + } +} + +bool Board::isJump(int pos, int dir) { + switch (dir) { + case NW: return pos < BoardWidth || x(pos) == 0; + case N: return pos < BoardWidth; + case NE: return pos < BoardWidth || x(pos) == BoardWidth-1; + case W: return x(pos) == 0; + case E: return x(pos) == BoardWidth-1; + case SW: return pos >= sz-BoardWidth || x(pos) == 0; + case S: return pos >= sz-BoardWidth; + case SE: return pos >= sz-BoardWidth || x(pos) == BoardWidth-1; + } + return FALSE; +} + +int Board::move(int pos, int dir, int steps) +{ + if (steps < 0) { // move backwards + dir = turn(dir); // turn around and do your steps + steps *= -1; + } + + while (steps-- != 0) { // until all steps are gone + switch (dir) { + case NW: pos = pos >= BoardWidth && x(pos) > 0 ? (pos-BoardWidth)-1 : sz-1; + break; + case N: pos = pos >= BoardWidth ? pos-BoardWidth : (sz-BoardWidth)+x(pos); + break; + case NE: pos = pos >= BoardWidth && x(pos) < BoardWidth-1 ? + (pos-BoardWidth)+1 : sz-BoardWidth; + break; + case W: pos = x(pos) > 0 ? pos-1 : pos+(BoardWidth-1); + break; + case E: pos = x(pos) < BoardWidth-1 ? pos+1 : pos-(BoardWidth-1); + break; + case SW: pos = pos < sz-BoardWidth && x(pos) > 0 ? (pos+BoardWidth)-1 : BoardWidth-1; + break; + case S: pos = pos < sz-BoardWidth ? pos+BoardWidth : x(pos); + break; + case SE: pos = pos < sz-BoardWidth && x(pos) < BoardWidth-1 ? (pos+BoardWidth)+1 : 0; + break; + } + } + return pos; // here we are +} + +int Board::closeup(int pos, int dir, int target) +{ + if (dir == N || dir == S) { + if (x(target) < x(pos)) + return W; + if (x(target) > x(pos)) + return E; + } else { + if (y(target) < y(pos)) + return N; + if (y(target) > y(pos)) + return S; + } + return dir; +} + +int Board::x(int pos) +{ + return pos % BoardWidth; +} + +int Board::y(int pos) +{ + return pos/BoardWidth; +} + +int Board::turn(int dir) +{ + switch (dir) { + case N : return S; + case NE : return SW; + case E : return W; + case SE : return NW; + case S : return N; + case SW : return NE; + case W : return E; + case NW : return SE; + default : return dir; + } +} + +int Board::points() +{ + return numPoints; +} + +int Board::energizers() +{ + return numEnergizers; +} + +int Board::monsters() +{ + return numMonsters; +} + +int Board::tunnels() +{ + return numTunnels; +} diff --git a/tdepacman/board.h b/tdepacman/board.h new file mode 100644 index 0000000..3b56973 --- /dev/null +++ b/tdepacman/board.h @@ -0,0 +1,102 @@ +#ifndef BOARD_H +#define BOARD_H + +#include <tqmemarray.h> +#include <tqstring.h> +#include <tqptrlist.h> +#include <tqrect.h> + +#define OUT -1 + +enum Square {out = OUT, empty, brick, prison, gate, tunnel, prisonentry, prisonexit, + Point, energizer, fruit, pacman, monster, + fruithome, pacmanhome, monsterhome}; + +enum Image { None, Intro, Demo, Level, File }; + +#define X -1 +#define N 0 +#define S 1 +#define E 2 +#define W 3 +#define NE 4 +#define SE 5 +#define NW 6 +#define SW 7 + +#define BoardWidth 59 +#define BoardHeight 65 + +#define fixBits 0x0007 +#define varBits 0xFFF8 +#define monsterBits 0xFF00 + +#define pointBit 0x0008 +#define energizerBit 0x0010 +#define fruitBit 0x0020 +#define pacmanBit 0x0040 +#define monsterBit 0x0100 + +class Board : public TQMemArray<int> +{ +public: + Board (int size); + ~Board() {}; + void init(Image image, TQString levelName=0); + void setup(const uchar *buf); + + void set(int pos, Square sq, int m = 0); + void reset(int pos, Square sq, int m = 0); + int position(Square sq, int m = 0); + + bool isOut(int pos); + bool isEmpty(int pos); + bool isBrick(int pos); + bool isPrison(int pos); + bool isGate(int pos); + bool isTunnel(int pos); + bool isPoint(int pos); + bool isEnergizer(int pos); + bool isFruit(int pos); + bool isPacman(int pos); + bool isMonster(int pos); + bool isWay(int pos, int dir, Square sq); + bool isJump(int pos, int dir); + + int move(int pos, int dir, int steps = 1); + int closeup(int pos, int dir, int target); + int x(int pos); + int y(int pos); + int turn(int dir); + + int points(); + int energizers(); + int monsters(); + int tunnels(); + +private: + bool inBounds(int pos); + int sz; // size of board + + TQString map; + TQString mapName; // Filename of the latest loaded map + + int prisonEntry; // position of prisonentry + int prisonExit; // position of prisonexit + int pacmanHome; // startposition of pacman + int monsterHome[8]; // startposition of monsters + int fruitHome; // startposition of fruit + + int pacmanPosition; // actual position of pacman + int monsterPosition[8]; // actual position of monsters + int fruitPosition; // actual position of fruit + int energizerPosition[8]; // actual position of energizers + int tunnelPosition[8]; // position of tunnels + + int numMonsters; // number of monsters on the board + int numPoints; // number of points (left) on the board + int numEnergizers; // number of energizers (left) + int numTunnels; // number of tunnels on the board +}; + +#endif // BOARD_H diff --git a/tdepacman/colors.h b/tdepacman/colors.h new file mode 100644 index 0000000..33beae2 --- /dev/null +++ b/tdepacman/colors.h @@ -0,0 +1,21 @@ +#ifndef COLORS_H +#define COLORS_H + +#include <tqcolor.h> + +#define BLACK TQColor(TQt::black) +#define RED TQColor(TQt::red) +#define BROWN TQColor(0xde, 0x95, 0x41) +#define PINK TQColor(0xff, 0xba, 0xde) +#define CYAN TQColor(0x00, 0xff, 0xde) +#define LIGHTBLUE TQColor(0x41, 0xba, 0xde) +#define ORANGE TQColor(0xff, 0xba, 0x41) +#define YELLOW TQColor(TQt::yellow) +#define BLUE TQColor(0x20, 0x20, 0xde) +#define GREEN TQColor(TQt::green) +#define LIGHTGREEN TQColor(0x41, 0xba, 0x94) +#define FLESH TQColor(0xff, 0xba, 0x94) +#define WHITE TQColor(0xd8, 0xdc, 0xd8) + +#endif // COLORS_H + diff --git a/tdepacman/energizer.cpp b/tdepacman/energizer.cpp new file mode 100644 index 0000000..ca08f3b --- /dev/null +++ b/tdepacman/energizer.cpp @@ -0,0 +1,61 @@ +#include "energizer.h" + +Energizer::Energizer(Board *b) +{ + board = b; + setOn(); + actualPosition = OUT; + maxPixmaps = 0; +} + +void Energizer::setMaxPixmaps(int max) +{ + maxPixmaps = max; +} + +void Energizer::setOff() +{ + actualState = off; +} + +void Energizer::setOn() +{ + actualState = on; + actualPix = 0; +} + +void Energizer::setPosition(int pos) +{ + board->reset(actualPosition, energizer); + actualPosition = pos; + board->set(actualPosition, energizer); +} + +energizerState Energizer::state() +{ + return actualState; +} + +int Energizer::position() +{ + return actualPosition; +} + +bool Energizer::move() +{ + if (actualPosition == OUT) + return FALSE; + + if (++actualPix >= maxPixmaps) + actualPix = 0; + + return TRUE; +} + +int Energizer::pix() +{ + if (actualPosition == OUT || actualState == off) + return -1; + + return actualPix; +} diff --git a/tdepacman/energizer.h b/tdepacman/energizer.h new file mode 100644 index 0000000..377cd02 --- /dev/null +++ b/tdepacman/energizer.h @@ -0,0 +1,30 @@ +#ifndef ENERGIZER_H +#define ENERGIZER_H + +#include "board.h" + +enum energizerState { on, off }; + +class Energizer { +public: + Energizer(Board *b); + void setMaxPixmaps(int max); + void setOff(); + void setOn(); + void setPosition(int pos); + energizerState state(); + int position(); + bool move(); + int pix(); + +private: + Board *board; + + energizerState actualState; // the state of energizer + + int actualPix; // last Pixmap-index + int maxPixmaps; // Number of Pixmaps (1..) + int actualPosition; // actual position on board +}; + +#endif // ENERGIZER_H diff --git a/tdepacman/fruit.cpp b/tdepacman/fruit.cpp new file mode 100644 index 0000000..e6ad2d5 --- /dev/null +++ b/tdepacman/fruit.cpp @@ -0,0 +1,176 @@ +#include <stdlib.h> + +#include "fruit.h" + +Fruit::Fruit(Board *b) +{ + board = b; + maxPixmaps = 0; + setLevel(0, 0, 0, 0); +} + +void Fruit::setEaten(int duration) +{ + actualState = eaten; + timeLeft = duration; + actualDirection = X; +} + +void Fruit::setLevel(int level, int wDuration, int fDuration, int ticks) +{ + actualLevel = level; + waitDuration = wDuration; + fruitDuration = fDuration; + pauseDuration = ticks; + pause = 0; + actualState = inactive; + timeLeft = waitDuration; + lastPosition = OUT; + setPosition(OUT); + setMovement(OUT, OUT, 0); + actualDirection = X; + setMaxPixmaps(maxPixmaps); +} + +void Fruit::setMaxPixmaps(int max) +{ + maxPixmaps = max; + if (actualLevel-1 < maxPixmaps) + actualPix = actualLevel == 0 ? 0 : actualLevel-1; + else if (maxPixmaps > 0) + actualPix = rand() % maxPixmaps; + else + actualPix = -1; +} + +void Fruit::setMovement(int entry, int tunnel, int iq) +{ + homePosition = board->position(fruithome); + entryPosition = entry; + tunnelPosition = tunnel; + IQ = iq; +} + +void Fruit::setPosition(int pos) +{ + board->reset(lastPosition, fruit); + actualPosition = lastPosition = pos; + board->set(actualPosition, fruit); +} + +void Fruit::setDirection(int dir) +{ + actualDirection = dir; +} + +fruitState Fruit::state() +{ + return actualState; +} + +int Fruit::position() +{ + return actualPosition; +} + +int Fruit::direction() +{ + return actualDirection; +} + +bool Fruit::move(bool activate) +{ + if (timeLeft > 0) { + timeLeft--; + } + + if (actualDirection == X || actualState == inactive) { + if (timeLeft == 0 || (activate && actualState == inactive)) { + if (actualState == inactive) { + if (entryPosition == OUT || tunnelPosition == OUT) { + setPosition(board->position(fruithome)); + } else { + setPosition(entryPosition); + actualDirection = 0; + while (!board->isWay(actualPosition, actualDirection, empty) || + board->isJump(actualPosition, actualDirection)) + actualDirection++; + } + timeLeft = fruitDuration; + setMaxPixmaps(maxPixmaps); + actualState = active; + } else { + actualState = inactive; + setPosition(OUT); + timeLeft = waitDuration; + actualDirection = X; + } + return TRUE; + } + return FALSE; + } + + if (pause-- > 0) + return FALSE; + else + pause = pauseDuration; + + if (actualPosition == OUT) + return FALSE; + + if (actualDirection == X) + return TRUE; + + int d = actualDirection; + + if (rand() % (int) ((190-IQ)/10) == 0) + if (timeLeft > 0) // coming home or leaving again + d = board->closeup(actualPosition, d, homePosition); + else + d = board->closeup(actualPosition, d, tunnelPosition); + else + do // try new direction, but not the opposite + d = rand() % 4; // direction, to prevent hectic movement. + while (d == board->turn(actualDirection)); + + while ((!board->isWay(actualPosition, d, empty) && + !board->isWay(actualPosition, d, tunnel)) || + d == board->turn(actualDirection)) { + if (d != actualDirection) // if new direction is not possible, + d = actualDirection; // try current direction first. + else + d = rand() % 4; + } + + actualDirection = d; + actualPosition = board->move(actualPosition, actualDirection); + + if (actualPosition == homePosition) { + timeLeft = 0; + } + + if (board->isTunnel(actualPosition)) { + setPosition(OUT); + timeLeft = waitDuration; + actualState = inactive; + actualDirection = X; + if (board->tunnels() > 0) { + entryPosition = board->position(tunnel, rand() % board->tunnels()); + tunnelPosition = board->position(tunnel, rand() % board->tunnels()); + } + } + + if (actualPosition != lastPosition) { + setPosition(actualPosition); + } + + return TRUE; +} + +int Fruit::pix() +{ + if (actualPosition == OUT || actualState == inactive) + return -1; + else + return actualPix; +} diff --git a/tdepacman/fruit.h b/tdepacman/fruit.h new file mode 100644 index 0000000..fbbd9c0 --- /dev/null +++ b/tdepacman/fruit.h @@ -0,0 +1,53 @@ +#ifndef FRUIT_H +#define FRUIT_H + +#include <stdlib.h> + +#include "board.h" + +enum fruitState { inactive, active, eaten }; + +class Fruit { +public: + Fruit(Board *b); + void setEaten(int duration); + void setLevel(int level, int wDuration, int fDuration, int ticks = -1); + void setMaxPixmaps(int max); + void setMovement(int entry, int tunnel, int iq); + void setPosition(int pos); + void setDirection(int dir); + fruitState state(); + int position(); + int direction(); + bool move(bool activate=FALSE); + int pix(); + +private: + Board *board; + + int IQ; // Intelligence of movement (0 = dumb..180=smart) + + fruitState actualState; // the state of fruit + + int pauseDuration; // number of ticks before next movement + int pause; // actual ticks before movement (0 = move) + + int timeLeft; // Ticks remaining of current state + + int waitDuration; // Time before fruit appears + int fruitDuration; // Length of active-time in ticks + + int actualDirection; // actual direction of the fruit + int actualPosition; // actual position on board + int lastPosition; // the last position of the fruit + int actualLevel; // level for kind of fruit and score + int actualPix; + int maxPixmaps; // Number of Pixmaps (1..) + + int entryPosition; // where to come in + int homePosition; // where to go, on the way in + int tunnelPosition; // where to exit +}; + +#endif // FRUIT_H + diff --git a/tdepacman/hi16-app-tdepacman.png b/tdepacman/hi16-app-tdepacman.png Binary files differnew file mode 100644 index 0000000..7dc8172 --- /dev/null +++ b/tdepacman/hi16-app-tdepacman.png diff --git a/tdepacman/hi32-app-tdepacman.png b/tdepacman/hi32-app-tdepacman.png Binary files differnew file mode 100644 index 0000000..2c2d2e6 --- /dev/null +++ b/tdepacman/hi32-app-tdepacman.png diff --git a/tdepacman/keys.cpp b/tdepacman/keys.cpp new file mode 100644 index 0000000..df8f980 --- /dev/null +++ b/tdepacman/keys.cpp @@ -0,0 +1,192 @@ +#include <kapp.h> +#include <kstddirs.h> + +#include <tdeconfig.h> +#include <tdelocale.h> +#include <tdeaccel.h> +#include <tqpushbt.h> +#include <tqlabel.h> +#include <tqframe.h> +#include <tqkeycode.h> +#include <tqpixmap.h> +#include <tqstring.h> + +#include "keys.h" + +PKeys::PKeys( TQWidget *parent, const char *name) + : TQDialog( parent, name, TRUE, 0 ) +{ + TDEStandardDirs *dirs = TDEGlobal::dirs(); + + TQPushButton *okButton = new TQPushButton(this); + okButton->setText(i18n("Ok")); + okButton->setFixedSize(okButton->size()); + connect( okButton, SIGNAL(clicked()),this, SLOT(ok()) ); + okButton->move(20,210); + + TQPushButton *defaultButton = new TQPushButton(this); + defaultButton->setText(i18n("Defaults")); + defaultButton->setFixedSize(defaultButton->size()); + connect( defaultButton, SIGNAL(clicked()),this, SLOT(defaults()) ); + defaultButton->move(140,210); + + TQPushButton *cancelButton = new TQPushButton(this); + cancelButton->setText(i18n("Cancel")); + cancelButton->setFixedSize(cancelButton->size()); + connect( cancelButton, SIGNAL(clicked()),this, SLOT(reject()) ); + cancelButton->move(260,210); + + TQFrame *separator = new TQFrame(this); + separator->setFrameStyle( TQFrame::HLine | TQFrame::Sunken ); + separator->setGeometry( 20, 190, 340, 4 ); + + for ( int x = 0; x < 4; x++) { + TQLabel *l = new TQLabel(this); + l->setAlignment(AlignCenter); + labels[x] = l; + } + + labels[0]->setGeometry(120, 20, 140, 20 ); + labels[1]->setGeometry(120,160, 140, 20 ); + labels[2]->setGeometry( 20, 92, 100, 20 ); + labels[3]->setGeometry(265, 92, 100, 20 ); + + TQString pixPath; + + TQPushButton *up = new TQPushButton(this); + pixPath = dirs->findResource("appdata", "pics/up.xpm"); + up->setPixmap( TQPixmap(pixPath)); + up->setFixedSize(up->pixmap()->size()); + connect( up, SIGNAL(clicked()),this, SLOT(butUp()) ); + up->move(180, 50); + + TQPushButton *down = new TQPushButton(this); + pixPath = dirs->findResource("appdata", "pics/down.xpm"); + down->setPixmap( TQPixmap(pixPath)); + down->setFixedSize(down->pixmap()->size()); + connect( down, SIGNAL(clicked()),this, SLOT(butDown()) ); + down->move(180, 130); + + TQPushButton *left = new TQPushButton(this); + pixPath = dirs->findResource("appdata", "pics/left.xpm"); + left->setPixmap( TQPixmap(pixPath)); + left->setFixedSize(left->pixmap()->size()); + connect( left, SIGNAL(clicked()),this, SLOT(butLeft()) ); + left->move(140, 90); + + TQPushButton *right = new TQPushButton(this); + pixPath = dirs->findResource("appdata", "pics/right.xpm"); + right->setPixmap( TQPixmap(pixPath)); + right->setFixedSize(right->pixmap()->size()); + connect( right, SIGNAL(clicked()),this, SLOT(butRight()) ); + right->move(220, 90); + + + setCaption(i18n("Change Direction Keys")); + setFixedSize(380, 260); + lab = 0; + init(); +} + +void PKeys::keyPressEvent( TQKeyEvent *e ) +{ + uint kCode = e->key() & ~(SHIFT | CTRL | ALT); + TQString string = TDEAccel::keyToString(kCode); + + if (lab != 0) { + if ( string.isNull() ) + lab->setText(i18n("Undefined key")); + else + lab->setText(string); + } + else if ( lab == 0 && e->key() == Key_Escape) + reject(); +} + +void PKeys::butUp() +{ + getKey(0); +} + +void PKeys::butDown() +{ + getKey(1); +} + +void PKeys::butLeft() +{ + getKey(2); +} + +void PKeys::butRight() +{ + getKey(3); +} + +void PKeys::getKey(int i) +{ + if ( lab != 0) + focusOut(lab); + + focusIn(labels[i]); +} + +void PKeys::focusOut(TQLabel *l) +{ + l->setFrameStyle( TQFrame::NoFrame ); + l->setBackgroundColor(backgroundColor()); + l->repaint(); +} + +void PKeys::focusIn(TQLabel *l) +{ + lab = l; + lab->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); + lab->setBackgroundColor(white); + lab->repaint(); +} + +void PKeys::defaults() +{ + if ( lab != 0) + focusOut(lab); + + lab = 0; + + labels[0]->setText("Up"); + labels[1]->setText("Down"); + labels[2]->setText("Left"); + labels[3]->setText("Right"); +} + +void PKeys::init() +{ + TQString up("Up"); + up = kapp->config()->readEntry("upKey", up); + labels[0]->setText(up); + + TQString down("Down"); + down = kapp->config()->readEntry("downKey", down); + labels[1]->setText(down); + + TQString left("Left"); + left = kapp->config()->readEntry("leftKey", left); + labels[2]->setText(left); + + TQString right("Right"); + right = kapp->config()->readEntry("rightKey", right); + labels[3]->setText(right); +} + +void PKeys::ok() +{ + kapp->config()->writeEntry("upKey", labels[0]->text() ); + kapp->config()->writeEntry("downKey", labels[1]->text() ); + kapp->config()->writeEntry("leftKey", labels[2]->text() ); + kapp->config()->writeEntry("rightKey", labels[3]->text() ); + kapp->config()->sync(); + + accept(); +} + +#include "keys.moc" diff --git a/tdepacman/keys.h b/tdepacman/keys.h new file mode 100644 index 0000000..f1c822a --- /dev/null +++ b/tdepacman/keys.h @@ -0,0 +1,44 @@ +#ifndef KEYS_H +#define KEYS_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <kapp.h> + +#include <tqdialog.h> +#include <tqlabel.h> +#include <tqstring.h> +#include <tdeaccel.h> + +class PKeys : public TQDialog +{ + Q_OBJECT +public: + PKeys( TQWidget *parent=0, const char *name=0 ); + +private slots: + void butRight(); + void butLeft(); + void butUp(); + void butDown(); + + void getKey(int); + void defaults(); + void focusIn(TQLabel *); + void focusOut(TQLabel *); + + void ok(); + +protected: + void keyPressEvent( TQKeyEvent * ); + +private: + void init(); + + TQLabel *labels[4]; + TQLabel *lab; +}; + +#endif // KEYS_H diff --git a/tdepacman/lo16-app-tdepacman.png b/tdepacman/lo16-app-tdepacman.png Binary files differnew file mode 100644 index 0000000..7dc8172 --- /dev/null +++ b/tdepacman/lo16-app-tdepacman.png diff --git a/tdepacman/lo32-app-tdepacman.png b/tdepacman/lo32-app-tdepacman.png Binary files differnew file mode 100644 index 0000000..2c2d2e6 --- /dev/null +++ b/tdepacman/lo32-app-tdepacman.png diff --git a/tdepacman/main.cpp b/tdepacman/main.cpp new file mode 100644 index 0000000..e80c93e --- /dev/null +++ b/tdepacman/main.cpp @@ -0,0 +1,56 @@ +/*************************************************************************** + main.cpp - description + ------------------- + begin : Sam Jan 19 13:37:57 CET 2002 + copyright : (C) 1998-2003 by Jörg Thönnissen + email : joe@dsite.de + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include <tdecmdlineargs.h> +#include <tdeaboutdata.h> +#include <tdelocale.h> + +#include "tdepacman.h" + +static const char *description = + I18N_NOOP("A pacman game for the TDE Desktop\n\n" + "The program based on the source of ksnake\n" + "by Michel Filippi (mfilippi@sade.rhein-main.de).\n" + "The design was strongly influenced by the pacman\n" + "(c) 1980 MIDWAY MFG.CO.\n\n" + "I like to thank my girlfriend Elke Krueers for\n" + "the last 14 years of her friendship\n" + "and Christine Nickel for the 'K' in my life."); + +static TDECmdLineOptions options[] = +{ + { 0, 0, 0 } + // INSERT YOUR COMMANDLINE OPTIONS HERE +}; + +int main(int argc, char *argv[]) +{ + + TDEAboutData aboutData( "tdepacman", I18N_NOOP("TDEpacman"), + VERSION, description, TDEAboutData::License_GPL, + "(c) 1998-2003, Jörg Thönnissen", 0, 0, "joe@dsite.de"); + aboutData.addAuthor("Jörg Thönnissen",0, "joe@dsite.de"); + TDECmdLineArgs::init( argc, argv, &aboutData ); + TDECmdLineArgs::addCmdLineOptions( options ); // Add our own options. + + TDEApplication app; + + TDEpacmanApp *tdepacman = new TDEpacmanApp(); + tdepacman->show(); + + return app.exec(); +} diff --git a/tdepacman/monster.cpp b/tdepacman/monster.cpp new file mode 100644 index 0000000..2f402b4 --- /dev/null +++ b/tdepacman/monster.cpp @@ -0,0 +1,262 @@ +#include "monster.h" +#include "board.h" + +Monster::Monster(Board *b, int mid) +{ + board = b; + ID = mid; + + setREM(0); + setHarmless(0, 0, 0); + setArrested(0, 0); + setFreedom(board->position(prisonexit)); + if (mid == 0) + setPrison(board->position(prisonentry)); + else + setPrison(board->position(monsterhome, mid)); + + actualPosition = lastPosition = OUT; + feetPosition = 0; + IQ = 0; + maxBodyPixmaps = 0; + maxEyesPixmaps = 0; +} + +void Monster::setMaxPixmaps(int maxBody, int maxEyes) +{ + if (feetPosition >= (maxBody/10)) + feetPosition = 0; + maxBodyPixmaps = maxBody; + maxEyesPixmaps = maxEyes; +} + +void Monster::setArrested(int ticks, int duration) +{ + actualState = dangerous; + pauseDuration = ticks; + pause = 0; + arrestDuration = arrestLeft = duration; + arrestPause = ticks; + harmlessLeft = 0; +} + +void Monster::setDangerous(int ticks, int iq) +{ + actualState = dangerous; + pauseDuration = ticks; + pause = 0; + dangerousPause = ticks; + harmlessLeft = 0; + IQ = iq; +} + +void Monster::setHarmless(int ticks, int hDuration, int wDuration) +{ + actualState = harmless; + pauseDuration = ticks; + pause = 0; + harmlessDuration = harmlessLeft = hDuration; + warningDuration = wDuration; +} + +void Monster::setREM(int ticks) +{ + actualState = rem; + pauseDuration = ticks; + pause = 0; +} + +void Monster::setPosition(int pos) +{ + board->reset(lastPosition, monster, ID); // reset old position on the board + actualPosition = lastPosition = pos; // set position of monster + board->set(actualPosition, monster, ID); + feetPosition = 0; +} + +void Monster::setPrison(int pos) +{ + prisonPosition = pos; +} + +void Monster::setFreedom(int pos) +{ + freedomPosition = pos; +} + +void Monster::setDirection(int dir) +{ + if (dir == X) + lastDirection = actualDirection; + actualDirection = dir; +} + +monsterState Monster::state() +{ + return actualState; +} + +int Monster::position() +{ + return actualPosition; +} + +int Monster::direction() +{ + return actualDirection; +} + +int Monster::id() +{ + return ID; +} + +bool Monster::move() +{ + if (arrestLeft > 1) + arrestLeft--; + + if (harmlessLeft > 0) { + harmlessLeft--; + if (harmlessLeft == 0 && actualState == harmless) { + actualState = dangerous; + pauseDuration = dangerousPause; + } + } + + if (pause-- > 0) + return FALSE; + else + pause = pauseDuration; + + if (actualPosition == OUT) + return FALSE; + + if (actualDirection == X) { + if (++feetPosition >= (maxBodyPixmaps/10)) + feetPosition = 0; + return TRUE; + } + + lastPosition = actualPosition; + int d = actualDirection; + + if (arrestLeft > 1) { // during the arrest, only up and down + if (!board->isWay(actualPosition, d, empty) && + !board->isWay(actualPosition, d, tunnel)) + d = board->turn(actualDirection); + } + + if (arrestLeft == 1) { // going out of the prison + if (((d == W || d == E) && + board->x(actualPosition) == board->x(freedomPosition)) || + ((d == S || d == N) && + board->y(actualPosition) == board->y(freedomPosition)) || + board->isWay(actualPosition, d, brick) || + board->isWay(actualPosition, d, prison)) { + d = board->closeup(actualPosition, d, freedomPosition); + } + while (board->isWay(actualPosition, d, brick) || + board->isWay(actualPosition, d, prison)) { + if (d == actualDirection) + d = rand() % 4; + else + d = actualDirection; + } + if (actualState == dangerous) + pauseDuration = dangerousPause; + + } + + if (arrestLeft == 0) + if (actualState == rem) { // on the way to prison + + d = board->closeup(actualPosition, d, prisonPosition); + + while (board->isWay(actualPosition, d, brick) || + board->isWay(actualPosition, d, prison)) { + if (d != actualDirection) // if new direction is not possible, + d = actualDirection; // try current direction first. + else + d = rand() % 4; + } + + } else { // dangerous or harmless movement + if (rand() % (int) ((190-IQ)/10) == 0) { + d = board->closeup(actualPosition, d, board->position(pacman)); + if (actualState == harmless) + d = board->turn(d); + } else + do // try new direction, but not the opposite + d = rand() % 4; // direction, to prevent hectic movement. + while (d == board->turn(actualDirection)); + + while ((!board->isWay(actualPosition, d, empty) && + !board->isWay(actualPosition, d, tunnel)) || + d == board->turn(actualDirection)) { + if (d != actualDirection) // if new direction is not possible, + d = actualDirection; // try current direction first. + else + d = rand() % 4; + } + } + + actualDirection = d; + actualPosition = board->move(actualPosition, actualDirection); + + if (arrestLeft == 1 && actualPosition == freedomPosition) + arrestLeft = 0; + + if (actualState == rem && actualPosition == prisonPosition) { + actualState = dangerous; + pauseDuration = arrestPause; + arrestLeft = arrestDuration+1; + actualDirection = S; + } + + if (actualPosition != lastPosition) { + board->reset(lastPosition, monster, ID); + board->set(actualPosition, monster, ID); + } + + if (++feetPosition >= (maxBodyPixmaps/10)) + feetPosition = 0; + + return TRUE; +} + +int Monster::body() +{ + if (actualState == rem || actualPosition == OUT) + return -1; + else + if (actualState == harmless) + if (harmlessLeft > warningDuration || + harmlessLeft % (int) (warningDuration/4.5) > (int) (warningDuration/9)) + return ((maxBodyPixmaps/10)*8)+feetPosition; + else + return ((maxBodyPixmaps/10)*9)+feetPosition; + else + return ((maxBodyPixmaps/10)*ID)+feetPosition; +} + +int Monster::eyes() +{ + if (actualState == harmless || actualPosition == OUT) + return -1; + else + switch (actualDirection) { + case N : return 0; + case E : return 1; + case S : return 2; + case W : return 3; + case X : switch (lastDirection) { + case N : return 0; + case E : return 1; + case S : return 2; + default : return 3; + } + default : return -1; + } +} + diff --git a/tdepacman/monster.h b/tdepacman/monster.h new file mode 100644 index 0000000..385c513 --- /dev/null +++ b/tdepacman/monster.h @@ -0,0 +1,62 @@ +#ifndef MONSTER_H +#define MONSTER_H + +#include <stdlib.h> +#include <tqpixmap.h> +#include <tqwidget.h> + +#include "board.h" + +enum monsterState { dangerous, harmless, rem, arrested }; + +class Monster { +public: + Monster(Board *b, int mid = 0); + void setMaxPixmaps(int maxBody, int maxEyes); + void setArrested(int ticks, int duration); + void setDangerous(int ticks, int IQ); + void setHarmless(int ticks, int hDuration, int wDuration); + void setREM(int ticks); + void setPosition(int pos); + void setPrison(int pos); + void setFreedom(int pos); + void setDirection(int dir); + monsterState state(); + int position(); + int direction(); + int id(); + bool move(); + int body(); + int eyes(); +private: + Board *board; + int ID; // ID of monster (0 = 1st, 1 = 2nd ... 7 = last) + int IQ; // Intelligence of movement (0 = dumb..180 = smart) + + monsterState actualState; // The state of the monster + + int pauseDuration; // Number of ticks before movement + int pause; // actual ticks before moevment (0 = move) + int dangerousPause; // pause in dangerous-state + + int harmlessDuration; // Length of harmless-time in ticks + int harmlessLeft; // rest of the time in harmless-state + int warningDuration; // warningtime before monster get dangerous again + + int arrestDuration; // Length of arrest in ticks + int arrestLeft; // time left of arrest + int arrestPause; // pause in arrest-state + + int actualDirection; // actual direction of monster + int lastDirection; // last direction, before no movement (X) + int actualPosition; // actual position on board + int lastPosition; // the last position of the monster + int feetPosition; // left, right, left, right, ... + int maxBodyPixmaps; + int maxEyesPixmaps; + int prisonPosition; // where to go, if arrested + int freedomPosition; // where to go, if released from prison +}; + +#endif // MONSTER_H + diff --git a/tdepacman/pacman.cpp b/tdepacman/pacman.cpp new file mode 100644 index 0000000..40f60a8 --- /dev/null +++ b/tdepacman/pacman.cpp @@ -0,0 +1,147 @@ +#include "pacman.h" +#include "board.h" + +Pacman::Pacman(Board *b) +{ + board = b; + setDemo(FALSE); + setAlive(0); + actualPosition = lastPosition = OUT; + mouthPosition = 0; + lastPix = 0; + maxPixmaps = 0; +} + +void Pacman::setMaxPixmaps(int max) +{ + if (actualDirection == X && lastPix >= 0) { + actualDirection = lastPix / (maxPixmaps/4); + if (max < maxPixmaps) + mouthPosition = 0; + else + mouthPosition = lastPix % (maxPixmaps/4); + maxPixmaps = max; + + lastPix = pix(); + + actualDirection = X; + } else + maxPixmaps = max; +} + +void Pacman::setAlive(int ticks) +{ + actualState = alive; + pauseDuration = ticks; + pause = 0; +} + +void Pacman::setPosition(int pos) +{ + board->reset(lastPosition, pacman); + actualPosition = lastPosition = pos; + board->set(actualPosition, pacman); + mouthPosition = 0; +} + +void Pacman::setDirection(int dir, bool forced) +{ + if (forced || + board->isWay(actualPosition, dir, empty) || + board->isWay(actualPosition, dir, tunnel)) { + if (dir == X) + lastPix = pix(); + actualDirection = dir; + nextDirection = X; + } else + nextDirection = dir; +} + +void Pacman::setDemo(bool yes) +{ + demo = yes; +} + +pacmanState Pacman::state() +{ + return actualState; +} + +int Pacman::position() +{ + return actualPosition; +} + +int Pacman::direction() +{ + return actualDirection; +} + +bool Pacman::move() +{ + if (pause-- > 0) + return FALSE; + else + pause = pauseDuration; + + if (actualDirection == X || actualPosition == OUT) + return FALSE; + + lastPosition = actualPosition; + + if (demo) { + int d = actualDirection; + + do // try new direction, but not the opposite + d = rand() % 4; // direction, to prevent hectic movement. + while (d == board->turn(actualDirection)); + + while (!board->isWay(actualPosition, d, empty) && + !board->isWay(actualPosition, d, tunnel)) { + if (d != actualDirection) // if new actualDirection is not possible, + d = actualDirection; // try current actualDirection first. + else + d = rand() % 4; + } + + actualDirection = d; + actualPosition = board->move(actualPosition, actualDirection); + + } else { + + if (nextDirection != X) + if (board->isWay(actualPosition, nextDirection, empty) || + board->isWay(actualPosition, nextDirection, tunnel)) { + actualDirection = nextDirection; + nextDirection = X; + } + + if (board->isWay(actualPosition, actualDirection, empty) || + board->isWay(actualPosition, actualDirection, tunnel)) + actualPosition = board->move(actualPosition, actualDirection); + } + + if (actualPosition != lastPosition) { + board->reset(lastPosition, pacman); + board->set(actualPosition, pacman); + + if (++mouthPosition >= (maxPixmaps/4)) + mouthPosition = 0; + } + return TRUE; +} + +int Pacman::pix() +{ + if (actualPosition != OUT && maxPixmaps > 0) + switch (actualDirection) { + case N : return ((maxPixmaps/4)*0)+mouthPosition; + case E : return ((maxPixmaps/4)*1)+mouthPosition; + case S : return ((maxPixmaps/4)*2)+mouthPosition; + case W : return ((maxPixmaps/4)*3)+mouthPosition; + case X : return lastPix; + } + + return -1; +} + diff --git a/tdepacman/pacman.h b/tdepacman/pacman.h new file mode 100644 index 0000000..6f1a7c1 --- /dev/null +++ b/tdepacman/pacman.h @@ -0,0 +1,47 @@ +#ifndef PACMAN_H +#define PACMAN_H + +#include <stdlib.h> +#include <tqpixmap.h> +#include <tqwidget.h> + +#include "board.h" + +enum pacmanState { alive }; + +class Pacman { +public: + Pacman(Board *b); + void init(bool Demo = FALSE); + void setMaxPixmaps(int max); + void setAlive(int ticks); + void setPosition(int pos); + void setDirection(int dir, bool forced = FALSE); + void setDemo(bool yes); + pacmanState state(); + int position(); + int direction(); + bool move(); + int pix(); + +private: + Board *board; + + pacmanState actualState; // the state of pacman + bool demo; // real life or just demo + + int pauseDuration; // number of ticks before next movement + int pause; // actual ticks before movement (0=move) + + int actualDirection; // actual direction of pacman + int nextDirection; // where he wants to go + int lastPix; // last Pixmap-index before no movement + int maxPixmaps; // Number of Pixmaps (1..) + int actualPosition; // actual position on board + int lastPosition; // the last position of pacman + int mouthPosition; // eating + +}; + +#endif // PACMAN_H + diff --git a/tdepacman/painter.cpp b/tdepacman/painter.cpp new file mode 100644 index 0000000..4c897c8 --- /dev/null +++ b/tdepacman/painter.cpp @@ -0,0 +1,955 @@ +#include <kapp.h> +#include <kstddirs.h> + +#include <tdeconfig.h> +#include <tqcolor.h> +#include <tqpainter.h> +#include <tqpixmap.h> +#include <tqbitmap.h> +#include <tqrect.h> +#include <tqstring.h> +#include <tqmessagebox.h> +#include <tqfileinfo.h> + +#include "painter.h" +#include "board.h" + +Painter::Painter( Board *b, TQWidget *parent, int Scheme, int Mode, Bitfont *font) +{ + w = parent; + board = b; + + pointPix = NULL; + wallPix = NULL; + prisonPix = NULL; + energizerPix = NULL; + fruitPix = NULL; + pacmanPix = NULL; + dyingPix = NULL; + eyesPix = NULL; + monsterPix = NULL; + fruitScorePix = NULL; + monsterScorePix = NULL; + + lastPointPixmapName = ""; + lastWallPixmapName = ""; + lastPrisonPixmapName = ""; + lastEnergizerPixmapName = ""; + lastFruitPixmapName = ""; + lastPacmanPixmapName = ""; + lastDyingPixmapName = ""; + lastEyesPixmapName = ""; + lastMonsterPixmapName = ""; + lastFruitScorePixmapName = ""; + lastMonsterScorePixmapName = ""; + + bitfont = font; + + scheme = Scheme; + mode = Mode; + level = 0; + + confScheme(); +} + +TQPtrList<TQPixmap> *Painter::loadPixmap(TQWidget *parent, TQString pixmapName, + TQPtrList<TQPixmap> *pixmaps) +{ + if (pixmaps == NULL) { + pixmaps = new TQPtrList<TQPixmap>; + pixmaps->setAutoDelete(TRUE); + } + + if (!pixmaps->isEmpty()) + pixmaps->clear(); + + TQPixmap PIXMAP(pixmapName); + if (PIXMAP.isNull() || PIXMAP.mask() == NULL) { + TQString msg = i18n("The pixmap could not be contructed.\n\n" + "The file '@PIXMAPNAME@' does not exist,\n" + "or is of an unknown format."); + msg.replace(TQRegExp("@PIXMAPNAME@"), pixmapName); + // TQMessageBox::critical(parent, i18n("Initialization Error"), msg); + printf("%s\n", msg.local8Bit().data()); + return 0; + } + + int height = PIXMAP.height(); + int width = (height == 0) ? 0 : PIXMAP.width()/(PIXMAP.width()/height); + + TQBitmap BITMAP; + TQBitmap MASK; + + BITMAP = *PIXMAP.mask(); + MASK.resize(width, height); + + for (int x = 0; x < PIXMAP.width()/width; x++) { + TQPixmap *pixmap = new TQPixmap(width, height); + pixmaps->append(pixmap); + bitBlt(pixmap, 0, 0, &PIXMAP, x*width, 0, width, height, TQPixmap::CopyROP, TRUE); + bitBlt(&MASK, 0, 0, &BITMAP, x*width, 0, width, height, TQPixmap::CopyROP, TRUE); + pixmap->setMask(MASK); + } + + return pixmaps; +} + +TQPtrList<TQPixmap> *Painter::textPixmap(TQStrList &str, TQPtrList<TQPixmap> *pixmaps, + TQColor fg, TQColor bg) +{ + if (pixmaps == NULL) { + pixmaps = new TQPtrList<TQPixmap>; + pixmaps->setAutoDelete(TRUE); + } + + if (!pixmaps->isEmpty()) + pixmaps->clear(); + + for (uint s = 0; s < str.count(); s++) { + TQPixmap *pixmap = new TQPixmap(bitfont->text(str.at(s), fg, bg)); + pixmaps->append(pixmap); + } + + return pixmaps; +} + +TQPtrList<TQPixmap> *Painter::textPixmap(TQString str, TQPtrList<TQPixmap> *pixmaps, + TQColor fg, TQColor bg) +{ + if (pixmaps == NULL) { + pixmaps = new TQPtrList<TQPixmap>; + pixmaps->setAutoDelete(TRUE); + } + + if (!pixmaps->isEmpty()) + pixmaps->clear(); + + TQPixmap *pixmap = new TQPixmap(bitfont->text(str, fg, bg)); + pixmaps->append(pixmap); + + return pixmaps; +} + +/* Return the point of the upperleft pixel of the block representing that position + * on the board. + */ +TQPoint Painter::point(int pos) +{ + return TQPoint((board->x(pos)-1)*BlockWidth, (board->y(pos)-1)*BlockHeight); +} + + +TQRect Painter::rect(int pos, PixMap pix, uint i) +{ + if (pos == OUT) + return TQRect(); + + TQPixmap *PIXMAP = NULL; + switch (pix) { + case PacmanPix : PIXMAP = pacmanPix-> + at(checkRange(i, pacmanPix->count()-1)); + break; + case DyingPix : PIXMAP = dyingPix-> + at(checkRange(i, dyingPix->count()-1)); + break; + case MonsterPix : PIXMAP = monsterPix-> + at(checkRange(i, monsterPix->count()-1)); + break; + case EyesPix : PIXMAP = eyesPix-> + at(checkRange(i, eyesPix->count()-1)); + break; + case FruitPix : PIXMAP = fruitPix-> + at(checkRange(i, fruitPix->count()-1)); + break; + case PointPix : PIXMAP = pointPix-> + at(checkRange(i, pointPix->count()-1)); + break; + case EnergizerPix : PIXMAP = energizerPix-> + at(checkRange(i, energizerPix->count()-1)); + break; + case FruitScorePix : PIXMAP = fruitScorePix-> + at(checkRange(i, fruitScorePix->count()-1)); + break; + case MonsterScorePix : PIXMAP = monsterScorePix-> + at(checkRange(i,monsterScorePix->count()-1)); + break; + default : PIXMAP = wallPix-> + at(checkRange(i, wallPix->count()-1)); + } + if (PIXMAP == NULL) + return TQRect(); + + TQRect rect = PIXMAP->rect(); + TQPoint point = this->point(pos); + rect.moveCenter(TQPoint(point.x()-1, point.y()-1)); + + return rect; +} + +TQRect Painter::rect(int pos, TQString str, int align) +{ + if (pos == OUT) // return an empty rect if the position + return TQRect(); // is invalid + TQPoint point = this->point(pos); + TQRect rect = bitfont->rect(str); + + rect.moveCenter(TQPoint(point.x()-1, point.y()-1)); + + int dx = 0; + int dy = 0; + + if (align & TQLabel::AlignLeft || align & TQLabel::AlignRight) { + dx = (str.length()-1) * (bitfont->width()/2); + if (align & TQLabel::AlignRight) + dx *= -1; + } + + if (align & TQLabel::AlignTop || align & TQLabel::AlignBottom) { + dy = bitfont->height()/2; + if (align & TQLabel::AlignBottom) + dy *= -1; + } + + if (dx != 0 || dy != 0) + rect.moveBy(dx, dy); + + return rect; +} + +TQRect Painter::rect(TQRect r1, TQRect r2) +{ + TQRect rect; + rect.setLeft(r1.left() < r2.left() ? r1.left() : r2.left()); + rect.setTop(r1.top() < r2.top() ? r1.top() : r2.top()); + rect.setRight(r1.right() > r2.right() ? r1.right() : r2.right()); + rect.setBottom(r1.bottom() > r2.bottom() ? r1.bottom() : r2.bottom()); + + return rect; +} + +void Painter::erase(int pos, PixMap pix, uint i) +{ + if (pos == OUT) + return; + TQRect rect = this->rect(pos, pix, i); + bitBlt(&roomPix, rect.x(), rect.y(), &backPix, + rect.x(), rect.y(), rect.width(), rect.height()); +} + +int Painter::maxPixmaps(PixMap pix) +{ + switch (pix) { + case WallPix : return (int) wallPix->count(); + case PrisonPix : return (int) prisonPix->count(); + case PointPix : return (int) pointPix->count(); + case EnergizerPix : return (int) energizerPix->count(); + case FruitPix : return (int) fruitPix->count(); + case PacmanPix : return (int) pacmanPix->count(); + case DyingPix : return (int) dyingPix->count(); + case EyesPix : return (int) eyesPix->count(); + case MonsterPix : return (int) monsterPix->count(); + case FruitScorePix : return (int) fruitScorePix->count(); + case MonsterScorePix : return (int) monsterScorePix->count(); + default : return 0; + } +} + +void Painter::draw(TQPoint point, DrawWidget where, TQPixmap pix) +{ + switch (where) { + case Widget : bitBlt(w, point.x(), point.y(), &pix); + break; + case RoomPix : bitBlt(&roomPix, point.x(), point.y(), &pix); + break; + case BackPix : bitBlt(&backPix, point.x(), point.y(), &pix); + break; + } +} + +void Painter::draw(TQRect rect, DrawWidget where, TQPixmap pix) +{ + draw(TQPoint(rect.x(), rect.y()), where, pix); +} + +void Painter::draw(int pos, DrawWidget where, PixMap pix, uint i) +{ + TQPixmap *PIXMAP = NULL; + switch (pix) { + case PacmanPix : PIXMAP = pacmanPix-> + at(checkRange(i, pacmanPix->count()-1)); + break; + case DyingPix : PIXMAP = dyingPix-> + at(checkRange(i, dyingPix->count()-1)); + break; + case MonsterPix : PIXMAP = monsterPix-> + at(checkRange(i, monsterPix->count()-1)); + break; + case EyesPix : PIXMAP = eyesPix-> + at(checkRange(i, eyesPix->count()-1)); + break; + case FruitPix : PIXMAP = fruitPix-> + at(checkRange(i, fruitPix->count()-1)); + break; + case EnergizerPix : PIXMAP = energizerPix-> + at(checkRange(i, energizerPix->count()-1)); + break; + case FruitScorePix : PIXMAP = fruitScorePix-> + at(checkRange(i, fruitScorePix->count()-1)); + break; + case MonsterScorePix : PIXMAP = monsterScorePix-> + at(checkRange(i,monsterScorePix->count()-1)); + break; + default : ; + } + + if (PIXMAP == NULL) + return; + + TQRect rect = PIXMAP->rect(); + TQPoint point = this->point(pos); + rect.moveCenter(TQPoint(point.x()-1, point.y()-1)); + + switch (where) { + case Widget : bitBlt(w, rect.x(), rect.y(), PIXMAP); + break; + case RoomPix : bitBlt(&roomPix, rect.x(), rect.y(), PIXMAP); + break; + case BackPix : bitBlt(&backPix, rect.x(), rect.y(), PIXMAP); + break; + } +} + +TQPixmap Painter::draw(int pos, DrawWidget where, + TQString str, TQColor fg, TQColor bg, int align) +{ + TQPixmap TEXT = bitfont->text(str, fg, bg); + + TQRect rect = this->rect(pos, str, align); + TQPixmap SAVE = TQPixmap(rect.width(), rect.height()); + + switch (where) { + case Widget : bitBlt(&SAVE, 0, 0, w, rect.x(), rect.y()); + bitBlt(w, rect.x(), rect.y(), &TEXT); + break; + case RoomPix : bitBlt(&SAVE, 0, 0, &roomPix, rect.x(), rect.y()); + bitBlt(&roomPix, rect.x(), rect.y(), &TEXT); + break; + case BackPix : bitBlt(&SAVE, 0, 0, &backPix, rect.x(), rect.y()); + bitBlt(&backPix, rect.x(), rect.y(), &TEXT); + break; + } + + return SAVE; +} + +TQRect Painter::draw(int col, int row, DrawWidget where, + TQString str, TQColor fg, TQColor bg, int align) +{ + TQPixmap TEXT = bitfont->text(str, fg, bg); + + TQRect rect = this->rect(row*BoardWidth+col, str, align); + draw(rect, where, TEXT); + + return rect; +} + +void Painter::initPixmaps() +{ + if (lastPointPixmapName != pointPixmapName.at(level)) { + pointPix = loadPixmap(w, pointPixmapName.at(level), pointPix); + lastPointPixmapName = pointPixmapName.at(level); + } + if (lastPrisonPixmapName != prisonPixmapName.at(level)) { + prisonPix = loadPixmap(w, prisonPixmapName.at(level), prisonPix); + lastPrisonPixmapName = prisonPixmapName.at(level); + } + if (lastEnergizerPixmapName != energizerPixmapName.at(level)) { + energizerPix = loadPixmap(w, energizerPixmapName.at(level), energizerPix); + lastEnergizerPixmapName = energizerPixmapName.at(level); + } + if (lastFruitPixmapName != fruitPixmapName.at(level)) { + fruitPix = loadPixmap(w, fruitPixmapName.at(level), fruitPix); + lastFruitPixmapName = fruitPixmapName.at(level); + } + if (lastPacmanPixmapName != pacmanPixmapName.at(level)) { + pacmanPix = loadPixmap(w, pacmanPixmapName.at(level), pacmanPix); + lastPacmanPixmapName = pacmanPixmapName.at(level); + } + if (lastDyingPixmapName != dyingPixmapName.at(level)) { + dyingPix = loadPixmap(w, dyingPixmapName.at(level), dyingPix); + lastDyingPixmapName = dyingPixmapName.at(level); + } + if (lastEyesPixmapName != eyesPixmapName.at(level)) { + eyesPix = loadPixmap(w, eyesPixmapName.at(level), eyesPix); + lastEyesPixmapName = eyesPixmapName.at(level); + } + if (lastMonsterPixmapName != monsterPixmapName.at(level)) { + monsterPix = loadPixmap(w, monsterPixmapName.at(level), monsterPix); + lastMonsterPixmapName = monsterPixmapName.at(level); + } + + if (lastFruitScorePixmapName != fruitScorePixmapName.at(level) || + *fruitScorePixmapName.at(level) == '\0') { + if (*fruitScorePixmapName.at(level) == '\0') { + fruitScorePix = textPixmap(fruitScoreString, fruitScorePix, PINK); + } else { + fruitScorePix = loadPixmap(w, fruitScorePixmapName.at(level), + fruitScorePix); + lastFruitScorePixmapName = fruitScorePixmapName.at(level); + } + } + + if (lastMonsterScorePixmapName != monsterScorePixmapName.at(level) || + *monsterScorePixmapName.at(level) == '\0') { + if (*monsterScorePixmapName.at(level) == '\0') { + monsterScorePix = textPixmap(monsterScoreString, monsterScorePix, CYAN); + } else { + monsterScorePix = loadPixmap(w, monsterScorePixmapName.at(level), + monsterScorePix); + lastMonsterScorePixmapName = monsterScorePixmapName.at(level); + } + } + + if (lastWallPixmapName != wallPixmapName.at(level)) { + wallPix = loadPixmap(w, wallPixmapName.at(level), wallPix); + if (wallPix->isEmpty()) { + BlockWidth = 0; + BlockHeight = 0; + } else { + BlockWidth = wallPix->at(0)->width(); + BlockHeight = wallPix->at(0)->height(); + } + lastWallPixmapName = wallPixmapName.at(level); + } +} + +void Painter::initbackPixmaps() +{ + backgroundColor = BLACK; + + backPix.resize((BoardWidth-3)*BlockWidth, (BoardHeight-3)*BlockHeight ); + backPix.fill(backgroundColor); +} + +void Painter::initRoomPixmap() +{ + roomPix.resize((BoardWidth-3)*BlockWidth, (BoardHeight-3)*BlockHeight ); + bitBlt(&roomPix,0,0, &backPix); + + for (unsigned int x = 0; x < board->size(); x++) { + if (board->isBrick(x)) + drawBrick(x); + if (board->isPrison(x) || board->isGate(x)) + drawPrison(x); + if (board->isPoint(x)) + drawPoint(x); + } +} + +void Painter::drawBrick(int pos) +{ + int border = 0; + if (board->isBrick(board->move(pos, N ))) border |= (1 << 0); + if (board->isBrick(board->move(pos, NE))) border |= (1 << 1); + if (board->isBrick(board->move(pos, E ))) border |= (1 << 2); + if (board->isBrick(board->move(pos, SE))) border |= (1 << 3); + if (board->isBrick(board->move(pos, S ))) border |= (1 << 4); + if (board->isBrick(board->move(pos, SW))) border |= (1 << 5); + if (board->isBrick(board->move(pos, W ))) border |= (1 << 6); + if (board->isBrick(board->move(pos, NW))) border |= (1 << 7); + + if (board->isOut(board->move(pos, N ))) border |= (1 << 8); + if (board->isOut(board->move(pos, NE))) border |= (1 << 9); + if (board->isOut(board->move(pos, E ))) border |= (1 << 10); + if (board->isOut(board->move(pos, SE))) border |= (1 << 11); + if (board->isOut(board->move(pos, S ))) border |= (1 << 12); + if (board->isOut(board->move(pos, SW))) border |= (1 << 13); + if (board->isOut(board->move(pos, W ))) border |= (1 << 14); + if (board->isOut(board->move(pos, NW))) border |= (1 << 15); + + switch (border & 0xFF) { + case 31 : border = 0; break; + case 159 : border = 0; break; + case 63 : border = 0; break; + case 191 : border = 0; break; + case 241 : border = 1; break; + case 249 : border = 1; break; + case 243 : border = 1; break; + case 251 : border = 1; break; + case 124 : border = 2; break; + case 252 : border = 2; break; + case 126 : border = 2; break; + case 199 : border = 3; break; + case 231 : border = 3; break; + case 207 : border = 3; break; + case 28 : if ((border >> 8) > 0) + border = 24; + else + border = 4; + break; + case 112 : if ((border >> 8) > 0) + border = 27; + else + border = 5; + break; + case 7 : if ((border >> 8) > 0) + border = 25; + else + border = 6; + break; + case 193 : if ((border >> 8) > 0) + border = 26; + else + border = 7; + break; + case 247 : if ((border & (1 << 11)) > 0) + border = 23; + else + border = 8; + break; + case 119 : if ((border & (1 << 15)) > 0) + border = 8; + if ((border & (1 << 11)) > 0) + border = 11; + break; + case 223 : if ((border & (1 << 13)) > 0) + border = 20; + else + border = 9; + break; + case 221 : if ((border & (1 << 13)) > 0) + border = 10; + if ((border & (1 << 9)) > 0) + border = 9; + break; + case 253 : if ((border & (1 << 9)) > 0) + border = 21; + else + border = 10; + break; + case 127 : if ((border & (1 << 15)) > 0) + border = 22; + else + border = 11; + break; + case 30 : border = 12; break; + case 240 : border = 13; break; + case 15 : border = 14; break; + case 225 : border = 15; break; + case 135 : border = 16; break; + case 195 : border = 17; break; + case 60 : border = 18; break; + case 120 : border = 19; break; + case 255 : border = 28; break; + default : border = -1; + } + if (border != -1 && border < (int) wallPix->count()) { + TQRect rect = this->rect(pos, WallPix); + bitBlt(&roomPix, rect.x(), rect.y(), wallPix->at((uint) border)); + } +} + +void Painter::drawPrison(int pos) +{ + int border = 0; + if (board->isPrison(board->move(pos, N ))) border |= (1 << 0); + if (board->isPrison(board->move(pos, NE))) border |= (1 << 1); + if (board->isPrison(board->move(pos, E ))) border |= (1 << 2); + if (board->isPrison(board->move(pos, SE))) border |= (1 << 3); + if (board->isPrison(board->move(pos, S ))) border |= (1 << 4); + if (board->isPrison(board->move(pos, SW))) border |= (1 << 5); + if (board->isPrison(board->move(pos, W ))) border |= (1 << 6); + if (board->isPrison(board->move(pos, NW))) border |= (1 << 7); + + if (board->isGate(board->move(pos, N ))) border |= (1 << 8); + if (board->isGate(board->move(pos, NE))) border |= (1 << 9); + if (board->isGate(board->move(pos, E ))) border |= (1 << 10); + if (board->isGate(board->move(pos, SE))) border |= (1 << 11); + if (board->isGate(board->move(pos, S ))) border |= (1 << 12); + if (board->isGate(board->move(pos, SW))) border |= (1 << 13); + if (board->isGate(board->move(pos, W ))) border |= (1 << 14); + if (board->isGate(board->move(pos, NW))) border |= (1 << 15); + + switch (border & 0xFF) { + case 31 : border = 0; break; + case 159 : border = 0; break; + case 63 : border = 0; break; + case 241 : border = 1; break; + case 249 : border = 1; break; + case 243 : border = 1; break; + case 124 : border = 2; break; + case 252 : border = 2; break; + case 126 : border = 2; break; + case 199 : border = 3; break; + case 231 : border = 3; break; + case 207 : border = 3; break; + case 28 : if ((border >> 8) != 0) + border = 12; + else + border = 4; + break; + case 112 : if ((border >> 8) != 0) + border = 13; + else + border = 5; + break; + case 7 : if ((border >> 8) != 0) + border = 14; + else + border = 6; + break; + case 193 : if ((border >> 8) != 0) + border = 15; + else + border = 7; + break; + case 247 : border = 8; break; + case 223 : border = 9; break; + case 253 : border = 10; break; + case 127 : border = 11; break; + default : border = -1; + } + if (board->isGate(pos)) { + if (board->isGate(board->move(pos, N))) + border = 17; + else + border = 16; + } + + if (border != -1 && border < (int) prisonPix->count()) { + TQRect rect = this->rect(pos, PrisonPix); + bitBlt(&roomPix, rect.x(), rect.y(), prisonPix->at((uint) border)); + } +} + +void Painter::drawPoint(int pos) +{ + if (!pointPix->isEmpty()) { + TQRect rect = this->rect(pos, PointPix); + bitBlt(&roomPix, rect.x(), rect.y(), pointPix->at(0)); + } +} + +TQString Painter::decodeHexOctString(TQString s) +{ + TQString value; + TQString valids; + int pos, xpos = 0, opos = 0; + int v, len, leadin; + const char *ptr; + uchar c; + + while (((xpos = s.find(TQRegExp("\\\\x[0-9a-fA-F]+"), xpos)) != -1) || + ((opos = s.find(TQRegExp("\\\\[0-7]+"), opos)) != -1)) { + if (xpos != -1) { + valids = "0123456789abcdef"; + leadin = 2; + pos = xpos; + } else { + valids = "01234567"; + leadin = 1; + pos = opos; + } + + c = '\0'; + len = 0; + value = s.mid(pos+leadin, 3); + ptr = value.latin1(); + + while (*ptr != '\0' && (v = valids.find(*ptr++, 0, FALSE)) != -1) { + c = (c * valids.length()) + v; + len++; + } + + value.fill(c, 1); + s.replace(pos, len+leadin, value); + } + + return s; +} + +void Painter::fillScoreString(TQStrList &list, TQMemArray<int> &values) +{ + if( !list.isEmpty()) + list.clear(); + + TQString s; + + for (uint i = 0; i < values.size(); i++) { + + if (values[i] < 10 || values[i] > 10000) + s = "?"; + else if (values[i] == 1600) + s = "\x1a\x1b"; + else if (values[i] < 100) { + s = "\x0e"; + s.insert(0, char (values[i] / 10 + 0x10)); + } else if (values[i] < 1000) { + s = "\x0f"; + s.insert(0, char (values[i] / 100 + 0x10)); + } else { + s = "\x0f\x10"; + s.insert(0, char (values[i] / 1000 + 0x10)); + } + + list.append(s.latin1()); + } +} + +void Painter::fillArray(TQMemArray<int> &array, TQString values, int max) +{ + array.resize(max); + int last = 0; + bool ok; + TQString 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 Painter::fillStrList(TQStrList &list, TQString values, int max) +{ + if (!list.isEmpty()) + list.clear(); + + TQString last = ""; + TQString 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 = decodeHexOctString(value); + list.append(last.latin1()); + } +} + +void Painter::fillPixmapName(TQStrList &pixmapName) +{ + TQStrList list = pixmapName; + + if (!pixmapName.isEmpty()) + pixmapName.clear(); + + TQString pixmap; + + TQFileInfo fileInfo; + + for (uint i = 0; i < list.count(); i++) { + pixmap = list.at(i); + + if (pixmap.left(1) != "/" && pixmap.left(1) != "~") + pixmap = TDEGlobal::dirs()->findResource("appdata", pixmapDirectory+pixmap); + + fileInfo.setFile(pixmap); + if (!fileInfo.isReadable() || !fileInfo.isFile()) + pixmap = ""; + + pixmapName.append(pixmap.utf8()); + } +} + +void Painter::confLevels(bool defGroup) +{ + if (defGroup || kapp->config()->hasKey("Levels")) + maxLevel = kapp->config()->readNumEntry("Levels", 13); +} + +void Painter::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("PointPixmapName")) + fillStrList(pointPixmapName, + kapp->config()->readEntry("PointPixmapName", "point.xpm"), maxLevel+1); + if (defGroup || kapp->config()->hasKey("WallPixmapName")) + fillStrList(wallPixmapName, + kapp->config()->readEntry("WallPixmapName", "wall.xpm"), maxLevel+1); + if (defGroup || kapp->config()->hasKey("PrisonPixmapName")) + fillStrList(prisonPixmapName, + kapp->config()->readEntry("PrisonPixmapName", "prison.xpm"), maxLevel+1); + if (defGroup || kapp->config()->hasKey("EnergizerPixmapName")) + fillStrList(energizerPixmapName, + kapp->config()->readEntry("EnergizerPixmapName", "switch.xpm"),maxLevel+1); + if (defGroup || kapp->config()->hasKey("FruitPixmapName")) + fillStrList(fruitPixmapName, + kapp->config()->readEntry("FruitPixmapName", "fruit.xpm"), maxLevel+1); + if (defGroup || kapp->config()->hasKey("PacmanPixmapName")) + fillStrList(pacmanPixmapName, + kapp->config()->readEntry("PacmanPixmapName", "pacman.xpm"), maxLevel+1); + if (defGroup || kapp->config()->hasKey("DyingPixmapName")) + fillStrList(dyingPixmapName, + kapp->config()->readEntry("DyingPixmapName", "dying.xpm"), maxLevel+1); + if (defGroup || kapp->config()->hasKey("EyesPixmapName")) + fillStrList(eyesPixmapName, + kapp->config()->readEntry("EyesPixmapName", "eyes.xpm"), maxLevel+1); + if (defGroup || kapp->config()->hasKey("MonsterPixmapName")) + fillStrList(monsterPixmapName, + kapp->config()->readEntry("MonsterPixmapName", "monster.xpm"), maxLevel+1); + + if (defGroup || kapp->config()->hasKey("FruitScorePixmapName")) + fillStrList(fruitScorePixmapName, + kapp->config()->readEntry("FruitScorePixmapName"), maxLevel+1); + if (defGroup || kapp->config()->hasKey("MonsterScorePixmapName")) + fillStrList(monsterScorePixmapName, + kapp->config()->readEntry("MonsterScorePixmapName"), maxLevel+1); +} + +void Painter::confScoring(bool defGroup) +{ + 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("FruitScoreString")) + fillStrList(fruitScoreString, + kapp->config()->readEntry("FruitScoreString"), maxLevel+1); + if (defGroup || kapp->config()->hasKey("MonsterScoreString")) + fillStrList(monsterScoreString, + kapp->config()->readEntry("MonsterScoreString"), 4); +} + +void Painter::confScheme() +{ + TQString oldgroup = kapp->config()->group(); + TQString 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(); + confScoring(); + + if (mode != -1) { + newgroup.sprintf("Mode %d", mode); + kapp->config()->setGroup(newgroup); + + confMisc(FALSE); + confScoring(FALSE); + } + + if (scheme != -1) { + newgroup.sprintf("Scheme %d", scheme); + kapp->config()->setGroup(newgroup); + + confMisc(FALSE); + confScoring(FALSE); + } + + if (*fruitScoreString.at(0) == '\0') + fillScoreString(fruitScoreString, fruitScore); + if (*monsterScoreString.at(0) == '\0') + fillScoreString(monsterScoreString, monsterScore); + + fillPixmapName(pointPixmapName); + fillPixmapName(wallPixmapName); + fillPixmapName(prisonPixmapName); + fillPixmapName(energizerPixmapName); + fillPixmapName(fruitPixmapName); + fillPixmapName(pacmanPixmapName); + fillPixmapName(dyingPixmapName); + fillPixmapName(eyesPixmapName); + fillPixmapName(monsterPixmapName); + fillPixmapName(fruitScorePixmapName); + fillPixmapName(monsterScorePixmapName); + + initPixmaps(); + initbackPixmaps(); + initRoomPixmap(); + + kapp->config()->setGroup(oldgroup); +} + +void Painter::setScheme(int Scheme, int Mode, Bitfont *font) +{ + bitfont = font; + + mode = Mode; + scheme = Scheme; + + confScheme(); +} + +void Painter::setLevel(int Level) +{ + level = Level; + + initPixmaps(); + initbackPixmaps(); + initRoomPixmap(); +} + +int Painter::checkRange(int value, int max, int min) +{ + if (value < min) { + printf("Painter::checkRange (value = %d, max = %d, min = %d)\n", + value, max, min); + return min; + } else if (value > max) { + printf("Painter::checkRange (value = %d, max = %d, min = %d)\n", + value, max, min); + return max; + } else + return value; +} diff --git a/tdepacman/painter.h b/tdepacman/painter.h new file mode 100644 index 0000000..a15c615 --- /dev/null +++ b/tdepacman/painter.h @@ -0,0 +1,144 @@ +#ifndef PAINTER_H +#define PAINTER_H + +#include <kapp.h> + +#include <tdelocale.h> +#include <tqpixmap.h> +#include <tqbitmap.h> +#include <tqlabel.h> +#include <tqcolor.h> +#include <tqptrlist.h> +#include <tqstrlist.h> +#include <tqregexp.h> + +#include "board.h" +#include "bitfont.h" +#include "colors.h" + +enum PixMap { PacmanPix, DyingPix, MonsterPix, EyesPix, FruitPix, + PointPix, EnergizerPix, WallPix, PrisonPix, + FruitScorePix, MonsterScorePix }; +enum DrawWidget { Widget, RoomPix, BackPix }; + +class Painter +{ +public: + Painter (Board *, TQWidget *parent=0, int scheme=-1, int mode=-1,Bitfont *font=0); + TQPixmap levelPix() { return roomPix; } + + void setScheme(int scheme=-1, int mode=-1, Bitfont *font=0); + void setLevel(int level=0); + + TQRect rect(int pos, PixMap pix, uint i = 0); + TQRect rect(int pos, TQString str, int align = TQLabel::AlignCenter ); + TQRect rect(TQRect r1, TQRect r2); + + void draw(TQPoint point, DrawWidget where, TQPixmap pix); + void draw(TQRect rect, DrawWidget where, TQPixmap pix); + void draw(int pos, DrawWidget where, PixMap pix, uint i = 0); + TQPixmap draw(int pos, DrawWidget where, TQString str, + TQColor fg, TQColor bg = TQColor(), int align = TQLabel::AlignCenter); + TQRect draw(int col, int row, DrawWidget where, TQString str, + TQColor fg, TQColor bg = TQColor(), int align = TQLabel::AlignCenter); + + void drawBrick(int pos); + void drawPrison(int pos); + void drawPoint(int pos); + + void erase(int pos, PixMap pix, uint i = 0); + + int maxPixmaps(PixMap pix); + +protected: + TQString decodeHexOctString(TQString str); + + void fillScoreString(TQStrList &, TQMemArray<int> &); + void fillArray(TQMemArray<int> &, TQString, int); + void fillStrList(TQStrList &, TQString, int); + void fillPixmapName(TQStrList &); + + void confScheme(); + void confLevels(bool defGroup=TRUE); + void confMisc(bool defGroup=TRUE); + void confScoring(bool defGroup=TRUE); + + void initPixmaps(); + void initRoomPixmap(); + void initbackPixmaps(); + +private: + TQWidget *w; + Board *board; + Bitfont *bitfont; + + int BlockWidth; + int BlockHeight; + + TQMemArray<int> fruitScore; + TQStrList fruitScoreString; + TQMemArray<int> monsterScore; + TQStrList monsterScoreString; + + TQString pixmapDirectory; + + TQStrList pointPixmapName; + TQStrList wallPixmapName; + TQStrList prisonPixmapName; + TQStrList energizerPixmapName; + TQStrList fruitPixmapName; + TQStrList pacmanPixmapName; + TQStrList dyingPixmapName; + TQStrList eyesPixmapName; + TQStrList monsterPixmapName; + TQStrList fruitScorePixmapName; + TQStrList monsterScorePixmapName; + + TQString lastPointPixmapName; + TQString lastWallPixmapName; + TQString lastPrisonPixmapName; + TQString lastEnergizerPixmapName; + TQString lastFruitPixmapName; + TQString lastPacmanPixmapName; + TQString lastDyingPixmapName; + TQString lastEyesPixmapName; + TQString lastMonsterPixmapName; + TQString lastFruitScorePixmapName; + TQString lastMonsterScorePixmapName; + + TQPtrList<TQPixmap> *loadPixmap(TQWidget *parent, TQString pixmapName, + TQPtrList<TQPixmap> *pixmaps=0); + TQPtrList<TQPixmap> *textPixmap(TQStrList &, TQPtrList<TQPixmap> *pixmaps=0, + TQColor fg = BLACK, TQColor bg = TQColor()); + TQPtrList<TQPixmap> *textPixmap(TQString str, TQPtrList<TQPixmap> *pixmaps=0, + TQColor fg = BLACK, TQColor bg = TQColor()); + + TQPoint point(int pos); + int checkRange(int value, int max, int min=0); + + TQPtrList<TQPixmap> *wallPix; + TQPtrList<TQPixmap> *prisonPix; + TQPtrList<TQPixmap> *pointPix; + TQPtrList<TQPixmap> *energizerPix; + TQPtrList<TQPixmap> *fruitPix; + TQPtrList<TQPixmap> *pacmanPix; + TQPtrList<TQPixmap> *dyingPix; + TQPtrList<TQPixmap> *eyesPix; + TQPtrList<TQPixmap> *monsterPix; + TQPtrList<TQPixmap> *fruitScorePix; + TQPtrList<TQPixmap> *monsterScorePix; + + TQPixmap roomPix; + TQPixmap backPix; + + bool plainColor; + TQColor backgroundColor; + + int maxLevel; + int level; + + int scheme; + int mode; +}; + +#endif // PAINTER_H diff --git a/tdepacman/referee.cpp b/tdepacman/referee.cpp new file mode 100644 index 0000000..1f4e2bc --- /dev/null +++ b/tdepacman/referee.cpp @@ -0,0 +1,1393 @@ +#include <stdlib.h> + +#include <kapp.h> +#include <kstddirs.h> + +#include <tdeconfig.h> +#include <tqdatetm.h> +#include <tqtimer.h> +#include <tqevent.h> +#include <tqcolor.h> +#include <tqkeycode.h> +#include <tqfileinfo.h> +#include <tdeaccel.h> + +#include "referee.h" +#include "board.h" +#include "pacman.h" +#include "monster.h" +#include "fruit.h" +#include "painter.h" + +Referee::Referee( TQWidget *parent, const char *name, int Scheme, int Mode, Bitfont *font) + : TQWidget( parent, name ) +{ + gameState.resize(12); + gameTimer = 0; + energizerTimer = 0; + + focusedPause = false; + setFocusPolicy(TQWidget::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 TQPtrList<Monster>; + monsters->setAutoDelete(TRUE); + + monsterRect = new TQPtrList<TQRect>; + monsterRect->setAutoDelete(TRUE); + + energizers = new TQPtrList<Energizer>; + energizers->setAutoDelete(TRUE); + + energizerRect = new TQPtrList<TQRect>; + energizerRect->setAutoDelete(TRUE); + + pacmanRect.setRect(0, 0, 0, 0); + fruitRect.setRect(0, 0, 0, 0); + + TQTime midnight( 0, 0, 0 ); + srand( midnight.secsTo(TQTime::currentTime()) ); + + lifes = 0; + points = 0; + + emit setLifes(lifes); + emit setPoints(points); + + intro(); +} + +void Referee::paintEvent( TQPaintEvent *e) +{ + if (gameState.testBit(HallOfFame)) + return; + + TQRect rect = e->rect(); + + if (!rect.isEmpty()) { + TQPixmap 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( TQTimerEvent *e ) +{ + if (gameState.testBit(HallOfFame)) + return; + + TQRect 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() +{ + TQString up("Up"); + up = kapp->config()->readEntry("upKey", up); + UpKey = TDEShortcut(up); + + TQString down("Down"); + down = kapp->config()->readEntry("downKey", down); + DownKey = TDEShortcut(down); + + TQString left("Left"); + left = kapp->config()->readEntry("leftKey", left); + LeftKey = TDEShortcut(left); + + TQString right("Right"); + right = kapp->config()->readEntry("rightKey", right); + RightKey = TDEShortcut(right); +} + +void Referee::fillArray(TQMemArray<int> &array, TQString values, int max) +{ + if (max < 0) + max = values.contains(',')+1; + + array.resize(max); + int last = 0; + bool ok; + TQString 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(TQStrList &list, TQString values, int max) +{ + if (!list.isEmpty()) + list.clear(); + + TQString last = ""; + TQString 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.latin1()); + } +} + +void Referee::fillMapName() +{ + TQStrList list = mapName; + + if (!mapName.isEmpty()) + mapName.clear(); + + TQString map; + + TQFileInfo fileInfo; + + for (uint i = 0; i < list.count(); i++) { + map = list.at(i); + + if (map.left(1) != "/" && map.left(1) != "~") + map = TDEGlobal::dirs()->findResource("appdata", mapDirectory+map); + + fileInfo.setFile(map); + if (!fileInfo.isReadable()) + map = ""; + + mapName.append(map.utf8()); + } +} + +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() +{ + TQString oldgroup = kapp->config()->group(); + TQString 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( TQKeyEvent *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) + TQTimer::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)) + TQTimer::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) +{ + TQString pts; + + switch (t) { + case 0 : repaint(pix->draw(16, 6, RoomPix, i18n("CHARACTER"), WHITE, TQColor(), AlignLeft), FALSE); + repaint(pix->draw(36, 6, RoomPix, i18n("/"), WHITE, TQColor(), AlignLeft), FALSE); + repaint(pix->draw(40, 6, RoomPix, i18n("NICKNAME"), WHITE, TQColor(), AlignLeft), FALSE); + break; + case 1 : introMonster(0); + break; + case 2 : repaint(pix->draw(16, 10, RoomPix, i18n("-SHADOW"), RED, TQColor(), AlignLeft), FALSE); + break; + case 3 : repaint(pix->draw(38, 10, RoomPix, i18n("\"BLINKY\""), RED, TQColor(), AlignLeft), FALSE); + break; + case 4 : introMonster(1); + break; + case 5 : repaint(pix->draw(16, 16, RoomPix, i18n("-SPEEDY"), PINK, TQColor(), AlignLeft), FALSE); + break; + case 6 : repaint(pix->draw(38, 16, RoomPix, i18n("\"PINKY\""), PINK, TQColor(), AlignLeft), FALSE); + break; + case 7 : introMonster(2); + break; + case 8 : repaint(pix->draw(16, 22, RoomPix, i18n("-BASHFUL"), CYAN, TQColor(), AlignLeft), FALSE); + break; + case 9 : repaint(pix->draw(38, 22, RoomPix, i18n("\"INKY\""), CYAN, TQColor(), AlignLeft), FALSE); + break; + case 10 : introMonster(3); + break; + case 11 : repaint(pix->draw(16, 28, RoomPix, i18n("-POKEY"), ORANGE, TQColor(), AlignLeft), FALSE); + break; + case 12 : repaint(pix->draw(38, 28, RoomPix, i18n("\"CLYDE\""), ORANGE, TQColor(), AlignLeft), FALSE); + break; + case 13 : pts.sprintf("%d", pointScore); + repaint(pix->draw(28, 44, RoomPix, pts, WHITE, TQColor(), AlignRight), FALSE); + repaint(pix->draw(31, 44, RoomPix, "\x1C\x1D\x1E", WHITE, TQColor(), AlignLeft), FALSE); + pts.sprintf("%d", energizerScore); + repaint(pix->draw(28, 48, RoomPix, pts, WHITE, TQColor(), AlignRight), FALSE); + repaint(pix->draw(31, 48, RoomPix, "\x1C\x1D\x1E", WHITE, TQColor(), 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)) { + TQTimer::singleShot(afterPauseMS, this, SLOT(introPlay())); + return; + } + + if (!gameState.testBit(Init)) { + if (monstersEaten == 4) { + stop(); + TQTimer::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) + TQTimer::singleShot(introAnimationMS, this, SLOT(introPlay())); +} + +void Referee::demo() +{ + if (gameState.testBit(Ready)) + return; + + if (gameState.testBit(Paused) || gameState.testBit(HallOfFame)) { + TQTimer::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; + TQTimer::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; + TQTimer::singleShot(playerDurMS, this, SLOT(ready())); +} + +void Referee::ready() +{ + if (gameState.testBit(Paused) || gameState.testBit(HallOfFame)) { + TQTimer::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(); + TQTimer::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); + TQTimer::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; + TQTimer::singleShot(levelUpPreAnimationMS, this, SLOT(levelUpPlay())); +} + +void Referee::levelUpPlay() +{ + if (gameState.testBit(Ready)) + return; + + if (gameState.testBit(Paused) || gameState.testBit(HallOfFame)) { + TQTimer::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) { + TQTimer::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)) { + TQTimer::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); + TQTimer::singleShot(dyingPreAnimationMS, this, SLOT(killed())); + } else { + stop(); + if (gameState.testBit(Paused) || gameState.testBit(HallOfFame)) { + TQTimer::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)) { + TQTimer::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) + TQTimer::singleShot(dyingPostAnimationMS, this, SLOT(killedPlay())); + else + TQTimer::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); + TQTimer::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); + TQRect *r = new TQRect(); + 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); + TQRect *r = new TQRect(); + 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(TQFocusEvent *) +{ + if (focusInContinue && focusedPause && + gameState.testBit(Paused) && gameState.testBit(Playing)) { + focusedPause = false; + // this also calls the Referee::pause() function + emit focusedGamePause(); + } +} + +void Referee::focusOutEvent(TQFocusEvent *) +{ + if (focusOutPause && !focusedPause && + !gameState.testBit(Paused) && gameState.testBit(Playing)) { + focusedPause = true; + // this also calls the Referee::pause() function + emit focusedGamePause(); + } +} + +#include "referee.moc" diff --git a/tdepacman/referee.h b/tdepacman/referee.h new file mode 100644 index 0000000..c147d18 --- /dev/null +++ b/tdepacman/referee.h @@ -0,0 +1,191 @@ +#ifndef REFEREE_H +#define REFEREE_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <kapp.h> + +#include <tqwidget.h> +#include <tqptrlist.h> +#include <tqstrlist.h> +#include <tqarray.h> +#include <tqbitarray.h> + +#include "board.h" +#include "pacman.h" +#include "monster.h" +#include "fruit.h" +#include "energizer.h" +#include "bitfont.h" +#include "painter.h" + +enum { Init, Introducing, Playing, Demonstration, Paused, Player, Ready, + Scoring, LevelDone, Dying, GameOver, HallOfFame }; + + +class Referee : public TQWidget +{ + Q_OBJECT +public: + Referee (TQWidget *parent=0, const char *name=0, int scheme=-1, int mode=-1, Bitfont *font=0); + + void setSkill(int); + void setRoom(int); + +public slots: + void setScheme(int scheme, int mode, Bitfont *font=0); + + void levelUp(); + void levelUpPlay(); + + void pause(); + void ready(); + void intro(); + void introPlay(); + void hallOfFame(); + void demo(); + void play(); + void killed(); + void killedPlay(); + void eaten(); + void toggleHallOfFame(); + + void setFocusOutPause(bool focusOutPause); + void setFocusInContinue(bool focusInContinue); + void initKeys(); + + void repaintFigures(); + +private slots: + void start(); + void stop(); + void stopEnergizer(); + +signals: + void setScore(int, int); + void setPoints(int); + void setLevel(int); + void setLifes(int); + + void focusedGamePause(); + void forcedGameHighscores(); + +protected: + void timerEvent(TQTimerEvent *); + void paintEvent(TQPaintEvent *); + void keyPressEvent(TQKeyEvent *); + + void focusOutEvent(TQFocusEvent *); + void focusInEvent(TQFocusEvent *); + + void fillArray(TQMemArray<int> &, TQString, int); + void fillStrList(TQStrList &, TQString, int); + void fillMapName(); + + void confScheme(); + void confLevels(bool defGroup=TRUE); + void confMisc(bool defGroup=TRUE); + void confTiming(bool defGroup=TRUE); + void confScoring(bool defGroup=TRUE); + +private: + TQBitArray gameState; + int timerCount; + int maxLevel; + + int scheme; + int mode; + + TQString pixmapDirectory; + TQString mapDirectory; + TQStrList mapName; + + TQMemArray<int> speed; + TQMemArray<int> monsterIQ; + TQMemArray<int> fruitIQ; + TQMemArray<int> fruitIndex; + TQMemArray<int> pacmanTicks; + TQMemArray<int> remTicks; + TQMemArray<int> dangerousTicks; + TQMemArray<int> harmlessTicks; + TQMemArray<int> harmlessDurTicks; + TQMemArray<int> harmlessWarnTicks; + TQMemArray<int> arrestTicks; + TQMemArray<int> arrestDurTicks; + TQMemArray<int> fruitTicks; + TQMemArray<int> fruitAppearsTicks; + TQMemArray<int> fruitDurTicks; + TQMemArray<int> fruitScoreDurTicks; + + int monsterScoreDurMS; + int playerDurMS; + int readyDurMS; + int gameOverDurMS; + int afterPauseMS; + int dyingPreAnimationMS; + int dyingAnimationMS; + int dyingPostAnimationMS; + int introAnimationMS; + int introPostAnimationMS; + int levelUpPreAnimationMS; + int levelUpAnimationMS; + int energizerAnimationMS; + + int pointScore; + int energizerScore; + TQMemArray<int> fruitScore; + TQMemArray<int> monsterScore; + TQMemArray<int> extraLifeScore; + + int extraLifeScoreIndex; + int nextExtraLifeScore; + + int monstersEaten; + int points; + int lifes; + int level; + + bool focusedPause; + bool focusOutPause; + bool focusInContinue; + + Board *board; + Painter *pix; + Pacman *pacman; + Fruit *fruit; + + TQPtrList<Monster> *monsters; + TQPtrList<TQRect> *monsterRect; + + TQPtrList<Energizer> *energizers; + TQPtrList<TQRect> *energizerRect; + + TQRect pacmanRect; + TQRect fruitRect; + + void introMonster(int id); + void introPaint(int t); + + void initMonsters(); + void initPacman(); + void initFruit(bool fullInitialization=TRUE); + void initEnergizers(); + + void setOnEnergizers(); + + int gameTimer; + int energizerTimer; + void start(int); + void init(bool); + + void score(int); + + uint UpKey; + uint DownKey; + uint RightKey; + uint LeftKey; +}; + +#endif // REFEREE_H diff --git a/tdepacman/score.cpp b/tdepacman/score.cpp new file mode 100644 index 0000000..77c87d8 --- /dev/null +++ b/tdepacman/score.cpp @@ -0,0 +1,628 @@ +#include <stdlib.h> +#include <ctype.h> + +#include <kapp.h> +#include <kstddirs.h> + +#include <tdeaccel.h> +#include <tdeconfig.h> +#include <tdemessagebox.h> +#include <tqpixmap.h> +#include <tqstring.h> +#include <tqdstream.h> +#include <tqkeycode.h> +#include <tqtimer.h> +#include <tqfileinfo.h> + +#include "bitfont.h" +#include "score.h" + +Score::Score(TQWidget *parent, const char *name, int Scheme, int Mode, Bitfont *font) : TQWidget(parent, name) +{ + setFocusPolicy(TQWidget::StrongFocus); + + paused = FALSE; + + lastScore = -1; + lastPlayer = -1; + + cursorBlinkTimer = 0; + cursorBlinkMS = -1; + cursor.x = -1; + cursor.y = -1; + cursor.on = FALSE; + cursor.chr = TQChar('?'); + + initKeys(); + + scheme = Scheme; + mode = Mode; + confScheme(); + + bitfont = font; + + highscoreFile.setName(locateHighscoreFilePath().filePath()); + read(); + + for (int p = 0; p < maxPlayer; p++) { + playerScore[p] = 0; + playerName[p] = getenv("LOGNAME"); + if (playerName[p].length() < minPlayerNameLength) + playerName[p].setExpand(minPlayerNameLength-1, ' '); + + for (uint i = 0; i < playerName[p].length(); i++) + if (playerName[p].at(i) < bitfont->firstChar() || + playerName[p].at(i) > bitfont->lastChar()) + playerName[p].at(i) = playerName[p].at(i).upper(); + } +} + +Score::~Score() +{ + // write(); +} + +void Score::paintEvent( TQPaintEvent *e) +{ + if (rect(1, 0, i18n(" 1UP ")).intersects(e->rect())) { + TQPixmap pix; + TQColor fg = BLACK; + if (cursor.on || paused || lastPlayer != 0) + fg = WHITE; + pix = bitfont->text(i18n(" 1UP "), fg, BLACK); + bitBlt(this, x(1), y(0), &pix); + } + + if (rect(8, 0, i18n(" HIGH SCORE ")).intersects(e->rect())) { + TQPixmap pix = bitfont->text(i18n(" HIGH SCORE "), WHITE, BLACK); + bitBlt(this, x(8), y(0), &pix); + } + + if (maxPlayer > 1 && rect(21, 0, i18n(" 2UP ")).intersects(e->rect())) { + TQPixmap pix; + TQColor fg = BLACK; + if (cursor.on || paused || lastPlayer != 1) + fg = WHITE; + pix = bitfont->text(i18n(" 2UP "), fg, BLACK); + bitBlt(this, x(21), y(0), &pix); + } + + TQString s; + + s.sprintf("%6d0", playerScore[0]/10); + if (rect(0, 1, s).intersects(e->rect())) { + TQPixmap pix = bitfont->text(s, WHITE, BLACK); + bitBlt(this, x(0), y(1), &pix); + } + + s.sprintf("%8d0", HighScore/10); + if (rect(8, 1, s).intersects(e->rect())) { + TQPixmap pix = bitfont->text(s, WHITE, BLACK); + bitBlt(this, x(8), y(1), &pix); + } + + if (lastScore >= 0) { + if (rect(1, 4*1.25, i18n(" CONGRATULATIONS ")).intersects(e->rect())) { + TQPixmap pix = bitfont->text(i18n(" CONGRATULATIONS "), YELLOW, BLACK); + bitBlt(this, x(1), y(4*1.25), &pix); + } + if (rect(1, 6*1.25, i18n(" YOU HAVE ARCHIEVED ")).intersects(e->rect())) { + TQPixmap pix = bitfont->text(i18n(" YOU HAVE ARCHIEVED "), CYAN, BLACK); + bitBlt(this, x(1), y(6*1.25), &pix); + } + if (rect(1, 7*1.25, i18n(" A SCORE IN THE TOP 10. ")).intersects(e->rect())) { + TQPixmap pix = bitfont->text(i18n(" A SCORE IN THE TOP 10. "), CYAN, BLACK); + bitBlt(this, x(1), y(7*1.25), &pix); + } + if (rect(1, 8*1.25, i18n(" ")).intersects(e->rect())) { + TQPixmap pix = bitfont->text(i18n(" "), CYAN, BLACK); + bitBlt(this, x(1), y(8*1.25), &pix); + } + } + + if (rect(1, 9.5*1.25, i18n("RNK SCORE NAME DATE")).intersects(e->rect())) { + TQPixmap pix = bitfont->text(i18n("RNK SCORE NAME DATE"), WHITE, BLACK); + bitBlt(this, x(1), y(9.5*1.25), &pix); + } + + for (int i = 0; i < 10; i++) { + s.sprintf("%2d%9d %-3.3s %-8.8s", + i+1, hallOfFame[i].points, hallOfFame[i].name.utf8().data(), + formatDate(hallOfFame[i].moment.date()).utf8().data()); + if (rect(1, (11+i)*1.25, s).intersects(e->rect())) { + TQPixmap pix = bitfont->text(s, (i == lastScore) ? YELLOW : WHITE, BLACK); + bitBlt(this, x(1), y((11+i)*1.25), &pix); + } + } + + if (cursor.x != -1 && cursor.y != -1 && cursor.on) { + if (rect(cursor.x, (cursor.y*1.25), cursor.chr).intersects(e->rect())) { + TQPixmap pix = bitfont->text(cursor.chr, BLACK, YELLOW); + bitBlt(this, x(cursor.x), y(cursor.y*1.25), &pix); + } + } + + if (paused) { + + TQPixmap pix = bitfont->text(i18n("PAUSED"), RED, BLACK); + TQRect r = bitfont->rect(i18n("PAUSED")); + r.moveCenter(TQPoint(this->width()/2, this->height()/2)); + + bitBlt(this, r.x(), r.y(), &pix); + } +} + +void Score::timerEvent(TQTimerEvent *e) +{ + cursor.on = !cursor.on; + + if (paused) + return; + + if (cursor.x != -1 && cursor.y != -1) + repaint(rect(cursor.x, cursor.y*1.25, cursor.chr), FALSE); + scrollRepeat = FALSE; + + if (lastPlayer == 0) + repaint(rect(1, 0, i18n(" 1UP ")), FALSE); + + if (lastPlayer == 1) + repaint(rect(21, 0, i18n(" 2UP ")), FALSE); +} + +void Score::keyPressEvent(TQKeyEvent *k) +{ + if (lastScore < 0 || lastPlayer < 0 || lastPlayer >= maxPlayer || paused) { + k->ignore(); + return; + } + + int x = cursor.x; + int y = cursor.y; + + uint key = k->key(); + + if (scrollRepeat && (key == UpKey || key == Key_Up || key == DownKey || key == Key_Down)) { + k->ignore(); + return; + } + + if (key != Key_Return) { + if (key == RightKey || key == Key_Right) + if (++cursor.x > 16) + cursor.x = 14; + if (key == LeftKey || key == Key_Left) + if (--cursor.x < 14) + cursor.x = 16; + if (key == UpKey || key == Key_Up) + if (cursor.chr.unicode() < bitfont->lastChar()) + cursor.chr = cursor.chr.unicode()+1; + else + cursor.chr = bitfont->firstChar(); + if (key == DownKey || key == Key_Down) + if (cursor.chr.unicode() > bitfont->firstChar()) + cursor.chr = cursor.chr.unicode()-1; + else + cursor.chr = bitfont->lastChar(); + + if (cursor.x == x && cursor.y == y && + cursor.chr == hallOfFame[lastScore].name.at(cursor.x-14)) { + uint ascii = k->ascii(); + + if (ascii < bitfont->firstChar() || ascii > bitfont->lastChar()) + ascii = toupper(ascii); + + if (ascii >= bitfont->firstChar() && ascii <= bitfont->lastChar()) { + cursor.chr = ascii; + hallOfFame[lastScore].name.at(cursor.x-14) = cursor.chr; + if (++cursor.x > 16) + cursor.x = 14; + } + } + } + + if (key == Key_Return) { + playerName[lastPlayer] = hallOfFame[lastScore].name; + write(); + read(); + lastScore = -1; + lastPlayer = -1; + cursor.x = -1; + cursor.y = -1; + emit gameFinished(); + end(); + } + + if (x != cursor.x || y != cursor.y) { + if (cursor.x != -1) + cursor.chr = hallOfFame[lastScore].name.at(cursor.x-14); + scrollRepeat = FALSE; + repaint(rect(x, y*1.25, cursor.chr), FALSE); + } else + hallOfFame[lastScore].name.at(cursor.x-14) = cursor.chr; + + if (key == UpKey || key == Key_Up || key == DownKey || key == Key_Down) + scrollRepeat = TRUE; + else + repaint(rect(cursor.x, cursor.y*1.25, cursor.chr), FALSE); +} + +void Score::initKeys() +{ + TQString up("Up"); + up = kapp->config()->readEntry("upKey", up); + UpKey = TDEShortcut(up); + + TQString down("Down"); + down = kapp->config()->readEntry("downKey", down); + DownKey = TDEShortcut(down); + + TQString left("Left"); + left = kapp->config()->readEntry("leftKey", left); + LeftKey = TDEShortcut(left); + + TQString right("Right"); + right = kapp->config()->readEntry("rightKey", right); + RightKey = TDEShortcut(right); +} + +void Score::confTiming(bool defGroup) +{ + if (defGroup || kapp->config()->hasKey("CursorBlinkMS")) + cursorBlinkMS = kapp->config()->readNumEntry("CursorBlinkMS", 250); + if (defGroup || kapp->config()->hasKey("HallOfFameMS")) + hallOfFameMS = kapp->config()->readNumEntry("HallOfFameMS", 7000); + if (defGroup || kapp->config()->hasKey("AfterPauseMS")) + afterPauseMS = kapp->config()->readNumEntry("AfterPauseMS", 1000); +} + +void Score::confScheme() +{ + TQString oldgroup = kapp->config()->group(); + TQString 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); + } + } + + int oldCursorBlinkMS = cursorBlinkMS; + + confTiming(); + + if (mode != -1) { + newgroup.sprintf("Mode %d", mode); + kapp->config()->setGroup(newgroup); + + confTiming(FALSE); + } + + if (scheme != -1) { + newgroup.sprintf("Scheme %d", scheme); + kapp->config()->setGroup(newgroup); + + confTiming(FALSE); + } + + if (cursorBlinkMS != oldCursorBlinkMS) { + if (cursorBlinkTimer) + killTimer(cursorBlinkTimer); + cursorBlinkTimer = startTimer(cursorBlinkMS); + } + + kapp->config()->setGroup(oldgroup); +} + +void Score::setScheme(int Scheme, int Mode, Bitfont *font) +{ + mode = Mode; + scheme = Scheme; + + confScheme(); + + bitfont = font; + + for (int p = 0; p < maxPlayer; p++) + for (uint i = 0; i < playerName[p].length(); i++) + if (playerName[p].at(i) < bitfont->firstChar() || + playerName[p].at(i) > bitfont->lastChar()) + playerName[p].at(i) = playerName[p].at(i).upper(); + + for (int i = 0; i < 10; i++) + for (uint j = 0; j < hallOfFame[i].name.length(); j++) + if (hallOfFame[i].name.at(j) < bitfont->firstChar() || + hallOfFame[i].name.at(j) > bitfont->lastChar()) + hallOfFame[i].name.at(j) = hallOfFame[i].name.at(j).upper(); + + if (cursor.chr.unicode() < bitfont->firstChar() || + cursor.chr.unicode() > bitfont->lastChar()) + cursor.chr = cursor.chr.upper(); +} + +void Score::set(int score) +{ + set(score, 0); +} + +void Score::set(int score, int player) +{ + if (player < 0 || player >= maxPlayer) + return; + + lastPlayer = player; + playerScore[lastPlayer] = score; + + TQString s; + + s.sprintf("%6d0", playerScore[lastPlayer]/10); + repaint(rect(0, 1, s), FALSE); + + if (score > HighScore) { + HighScore = score; + s.sprintf("%8d0", HighScore/10); + repaint(rect(8, 1, s), FALSE); + } +} + +/* + * Set the score for player after the game if over. If the score is in the + * high scores then the hall of fame is updated (shifted) and the scoreboard + * is shown. + */ + +void Score::setScore(int level, int player) +{ + // pointer to the array-position of a new archived top score + lastScore = -1; + + // was it a real game or just a demo (level == 0) + if (player >= 0 && player < maxPlayer && level != 0) { + + lastPlayer = player; + + for (int i = 0; i < 10; i++) + if ( playerScore[lastPlayer] > hallOfFame[i].points) { + lastScore = i; + break; + } + } + + // no new highscore archived, finish after specified time + if (lastScore < 0) { + // enable gameNew directly for an immediate next try + emit gameFinished(); + lastPlayer = -1; + TQTimer::singleShot(hallOfFameMS, this, SLOT(end())); + return; + } + + // shift old (lower) scores to make place for the new one + for (int i = 9; i > lastScore && i > 0; i--) + hallOfFame[i] = hallOfFame[i-1]; + + hallOfFame[lastScore].points = playerScore[lastPlayer]; + hallOfFame[lastScore].levels = level; + hallOfFame[lastScore].moment = TQDateTime::currentDateTime(); + hallOfFame[lastScore].name = playerName[lastPlayer]; + + cursor.x = 14; + cursor.y = 11+lastScore; + cursor.chr = hallOfFame[lastScore].name.at(cursor.x-14); + +// startTimer(cursorBlinkMS); + setFocus(); +} + +/* + * Read the highscores, if no file or a file shorter than 4 bytes (versions before 0.2.4 stores only + * the points of one highscore) exists - the highscores were initialized with default values. + */ +void Score::read() +{ + if (highscoreFile.exists() && highscoreFile.size() > 4) { + if (highscoreFile.open(IO_ReadOnly)) { + TQDataStream s(&highscoreFile); + char *name; + for (int i = 0; i < 10; i++) { + s >> hallOfFame[i].points >> hallOfFame[i].levels >> hallOfFame[i].duration >> + hallOfFame[i].moment >> name; + hallOfFame[i].name = TQString::fromLatin1(name); + delete(name); + } + highscoreFile.close(); + } + } else { + for (int i = 0; i < 10; i++) { + hallOfFame[i].points = 5000; + hallOfFame[i].levels = 0; + hallOfFame[i].duration = TQTime(); + hallOfFame[i].moment = TQDateTime(); + hallOfFame[i].name = "???"; + } + // write(); + } + + for (int i = 0; i < 10; i++) + for (uint j = 0; j < hallOfFame[i].name.length(); j++) + if (hallOfFame[i].name.at(j) < bitfont->firstChar() || + hallOfFame[i].name.at(j) > bitfont->lastChar()) + hallOfFame[i].name.at(j) = hallOfFame[i].name.at(j).upper(); + + HighScore = hallOfFame[0].points; +} + +void Score::write() +{ + if (!highscoreFile.exists() && highscoreFile.name() == systemHighscoreFileInfo.filePath()) + KMessageBox::information(0, + i18n("You're going to create the highscore-file\n" + "'%1'\n" + "for your maschine, that should be used systemwide.\n" + "\n" + "To grant access to the other users, set the appropriate rights (a+w)\n" + "on that file or ask your systemadministator for that favor.\n" + "\n" + "To use a different directory or filename for the highscores," + "specify them in the configfile (tdepacmanrc:highscoreFilePath)." + ).arg(systemHighscoreFileInfo.filePath())); + + if (highscoreFile.name() == privateHighscoreFileInfo.filePath()) + KMessageBox::information(0, + i18n("You're using a private highscore-file, that's mostly because of\n" + "missing write-access to the systemwide file\n" + "'%1' .\n" + "\n" + "Ask your systemadministrator for granting you access to that file,\n" + "by setting the appropriate rights (a+w) on it.\n" + "\n" + "To use a different directory or filename for the highscores," + "specify them in the configfile (tdepacmanrc:highscoreFilePath)." + ).arg(systemHighscoreFileInfo.filePath()), + TQString::null, "PrivateHighscore"); + + if (highscoreFile.open(IO_WriteOnly)) { + TQDataStream s(&highscoreFile); + for (int i = 0; i < 10; i++) + s << hallOfFame[i].points << hallOfFame[i].levels << hallOfFame[i].duration << + hallOfFame[i].moment << hallOfFame[i].name.latin1(); + highscoreFile.close(); + } +} + +void Score::setPause(bool Paused) +{ + paused = Paused; + + TQRect r = bitfont->rect(i18n("PAUSED")); + r.moveCenter(TQPoint(this->width()/2, this->height()/2)); + repaint(r, TRUE); + + // repaint 1UP or 2UP + repaint(FALSE); +} + +void Score::end() +{ + if (paused) { + TQTimer::singleShot(afterPauseMS, this, SLOT(end())); + return; + } + + // repaint 1UP or 2UP + repaint(FALSE); + + // if lastPlayer != -1 we're already in playing mode + if (lastPlayer == -1) + emit gameHighscores(); +} + +/* + * Return the date in a formatted TQString. The format can be changed using internationalization + * of the string "YY/MM/DD". Invalid TQDate's where returned as "00/00/00". + */ +TQString Score::formatDate(TQDate date) +{ + TQString s = i18n("@YY@/@MM@/@DD@"); + + TQString dd; + dd.sprintf("%02d", date.isValid() ? date.year() % 100 : 0); + s.replace(TQRegExp("@YY@"), dd); + dd.sprintf("%02d", date.isValid() ? date.month() : 0); + s.replace(TQRegExp("@MM@"), dd); + dd.sprintf("%02d", date.isValid() ? date.day() : 0); + s.replace(TQRegExp("@DD@"), dd); + + return s; +} + +TQRect Score::rect(int col, float row, TQString str, int align) +{ + TQRect r = bitfont->rect(str); + r.moveBy(x(col), y(row)); + + int dx = 0; + int dy = 0; + + if (align & AlignLeft || align & AlignRight) { + dx = (str.length()-1) * (bitfont->width()/2); + if (align & AlignRight) + dx *= -1; + } + + if (align & AlignTop || align & AlignBottom) { + dy = bitfont->height()/2; + if (align & AlignBottom) + dy *= -1; + } + + if (dx != 0 || dy != 0) + r.moveBy(dx, dy); + + return r; +} + +int Score::x(int col) +{ + return col*bitfont->width(); +} + +int Score::y(float row) +{ + return (int) (row*(bitfont->height()+bitfont->height()/4)); +} + +/** + * Ermittelt die zu benutzende "highscore"-Datei, in die auch geschrieben werden kann. + * Über den "highscoreFilePath"-TDEConfig-Eintrag, kann abweichend von der Standardlokation + * der Standort der "highscore"-Datei spezifiziert werden. + * Wenn die systemweite "highscore"-Datei nicht beschrieben werden kann, wird mit einer + * privaten Datei gearbeitet. + */ +TQFileInfo Score::locateHighscoreFilePath() +{ + TQFileInfo systemHighscoreDirPath; + TQStringList systemHighscoreDirs; + + // Schreibfähige "private" highscore-Datei ermitteln für den fallback. + privateHighscoreFileInfo.setFile(TDEGlobal::dirs()->saveLocation("appdata")+highscoreName); + + // FilePath aus der Konfigurationsdatei benutzen + systemHighscoreFileInfo.setFile(kapp->config()->readEntry("HighscoreFilePath")); + + // Kein Wert aus der Konfiguration erhalten, dann die "system"-Datei suchen. + if (systemHighscoreFileInfo.filePath().isEmpty()) + systemHighscoreDirs = TDEGlobal::dirs()->resourceDirs("appdata"); + else + systemHighscoreDirs = TQStringList(systemHighscoreFileInfo.filePath()); + + for (TQStringList::Iterator i = systemHighscoreDirs.begin(); i != systemHighscoreDirs.end(); ++i) { + + systemHighscoreFileInfo.setFile(*i); + if (systemHighscoreFileInfo.fileName().isEmpty()) + systemHighscoreFileInfo.setFile(systemHighscoreFileInfo.dirPath()+"/"+highscoreName); + + // privateHighscoreFileInfo für die "system" Suche ignorieren + if (systemHighscoreFileInfo.filePath() != privateHighscoreFileInfo.filePath()) + if (!systemHighscoreFileInfo.exists()) { + systemHighscoreDirPath.setFile(systemHighscoreFileInfo.dirPath()); + if (systemHighscoreDirPath.exists() && systemHighscoreDirPath.isWritable()) + return systemHighscoreFileInfo; + } else + if (systemHighscoreFileInfo.isWritable()) + return systemHighscoreFileInfo; + } + + return privateHighscoreFileInfo; +} + +#include "score.moc" diff --git a/tdepacman/score.h b/tdepacman/score.h new file mode 100644 index 0000000..fc0da45 --- /dev/null +++ b/tdepacman/score.h @@ -0,0 +1,124 @@ +#ifndef SCORE_H +#define SCORE_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <kapp.h> + +#include <tqwidget.h> +#include <tqstring.h> +#include <tqpoint.h> +#include <tqrect.h> +#include <tqfile.h> +#include <tqfileinfo.h> +#include <tqdatetime.h> + +#include "painter.h" +#include "bitfont.h" + +#define maxPlayer 1 +#define minPlayerNameLength 3 +#define highscoreName "highscore" + +class Score : public TQWidget +{ + Q_OBJECT +public: + Score (TQWidget *parent=0, const char *name=0, int scheme=-1, int mode=-1, Bitfont *font=0); + ~Score(); + +public slots: + void setScheme(int scheme, int mode, Bitfont *font=0); + + void set(int score); + void set(int score, int player); + void setScore(int level, int player); + void setPause(bool paused); + + void initKeys(); + +private slots: + void read(); + void write(); + void end(); + +signals: + void gameFinished(); + void gameHighscores(); + +protected: + void timerEvent(TQTimerEvent *); + void paintEvent(TQPaintEvent *); + void keyPressEvent(TQKeyEvent *); + + void focusInEvent(TQFocusEvent *) { ; } + void focusOutEvent(TQFocusEvent *) { ; } + + void confScheme(); + void confTiming(bool defGroup=TRUE); + +private: + Bitfont *bitfont; + + TQRect rect(int col, float row, TQString str, int align = AlignCenter); + int x(int col); + int y(float row); + + TQString formatDate(TQDate date); + + /** + * Ermittelt die zu benutzende "highscore"-Datei, in die auch geschrieben werden kann. + * Über den "highscoreFilePath"-TDEConfig-Eintrag, kann abweichend von der Standardlokation + * der Standort der "highscore"-Datei spezifiziert werden. + * Wenn die systemweite "globale" Datei nicht beschrieben werden kann, wird mit einer + * privaten Datei gearbeitet. + */ + TQFileInfo locateHighscoreFilePath(); + + int cursorBlinkMS; + int hallOfFameMS; + int afterPauseMS; + + bool paused; + + uint UpKey; + uint DownKey; + uint RightKey; + uint LeftKey; + + int lastScore; + int lastPlayer; + int HighScore; + int playerScore[maxPlayer]; + TQString playerName[maxPlayer]; + + struct { + int x; + int y; + TQChar chr; + bool on; + } cursor; + + int cursorBlinkTimer; + bool scrollRepeat; + + struct { + int points; + int levels; + TQTime duration; + TQDateTime moment; + TQString name; + } hallOfFame[10]; + + TQFileInfo systemHighscoreFileInfo; + TQFileInfo privateHighscoreFileInfo; + + TQFile highscoreFile; + + int scheme; + int mode; +}; + +#endif // SCORE_H diff --git a/tdepacman/status.cpp b/tdepacman/status.cpp new file mode 100644 index 0000000..12f01b7 --- /dev/null +++ b/tdepacman/status.cpp @@ -0,0 +1,353 @@ +#include <kapp.h> +#include <kstddirs.h> + +#include <tdelocale.h> +#include <tqbitmap.h> +#include <tqstring.h> +#include <tqmsgbox.h> +#include <tqfileinfo.h> + +#include "status.h" + +Status::Status( TQWidget *parent, const char *name, int Scheme, int Mode ) : + TQWidget( parent, name ) +{ + actualLifes = 0; + actualLevel = 0; + + lifesPix = NULL; + levelPix = NULL; + + scheme = Scheme; + mode = Mode; + level = 0; + + confScheme(); +} + +TQPtrList<TQPixmap> *Status::loadPixmap(TQWidget *parent, TQString pixmapName, + TQPtrList<TQPixmap> *pixmaps) +{ + if (pixmaps == NULL) { + pixmaps = new TQPtrList<TQPixmap>; + pixmaps->setAutoDelete(TRUE); + } + + if (!pixmaps->isEmpty()) + pixmaps->clear(); + + TQPixmap PIXMAP(pixmapName); + if (PIXMAP.isNull() || PIXMAP.mask() == NULL) { + TQString msg = i18n("The pixmap could not be contructed.\n\n" + "The file '@PIXMAPNAME@' does not exist,\n" + "or is of an unknown format."); + msg.replace(TQRegExp("@PIXMAPNAME@"), pixmapName); + TQMessageBox::information(parent, i18n("Initialization Error"), msg); + return 0; + } + + int height = PIXMAP.height(); + int width = (height == 0) ? 0 : PIXMAP.width()/(PIXMAP.width()/height); + + TQBitmap BITMAP; + TQBitmap MASK; + + BITMAP = *PIXMAP.mask(); + MASK.resize(width, height); + + for (int x = 0; x < PIXMAP.width()/width; x++) { + TQPixmap *pixmap = new TQPixmap(width, height); + pixmaps->append(pixmap); + bitBlt(pixmap, 0, 0, &PIXMAP, x*width, 0, width, height, CopyROP, TRUE); + bitBlt(&MASK, 0, 0, &BITMAP, x*width, 0, width, height, CopyROP, TRUE); + pixmap->setMask(MASK); + } + + return pixmaps; +} + +void Status::paintEvent( TQPaintEvent *) +{ + for (int x = 0; x < actualLifes && !lifesPix->isEmpty(); x++) + bitBlt(this, lifesPix->at(0)->width()+(lifesPix->at(0)->width()*x), + (height()-lifesPix->at(0)->height())/2, + lifesPix->at(0), 0, 0, + lifesPix->at(0)->width(), lifesPix->at(0)->height()); + + for (int x = 0; x < actualLevel && !levelPix->isEmpty(); x++) { + erase((width()-levelPix->at(x)->width()*2)-(levelPix->at(x)->width()*levelPos[x]), + (height()-levelPix->at(x)->height())/2, + levelPix->at(x)->width(), levelPix->at(x)->height()); + bitBlt(this, (width()-levelPix->at(x)->width()*2)-(levelPix->at(x)->width()*levelPos[x]), + (height()-levelPix->at(x)->height())/2, + levelPix->at(x), 0, 0, + levelPix->at(x)->width(), levelPix->at(x)->height()); + } +} + +void Status::initPixmaps() +{ + if (lastLifesPixmapName != lifesPixmapName.at(level)) { + lifesPix = loadPixmap(this, lifesPixmapName.at(level), lifesPix); + lastLifesPixmapName = lifesPixmapName.at(level); + } + if (lastLevelPixmapName != levelPixmapName.at(level)) { + levelPix = loadPixmap(this, levelPixmapName.at(level), levelPix); + lastLevelPixmapName = levelPixmapName.at(level); + } +} + +TQString Status::decodeHexOctString(TQString s) +{ + TQString value; + TQString valids; + int pos, xpos = 0, opos = 0; + int v, len, leadin; + const char *ptr; + uchar c; + + while (((xpos = s.find(TQRegExp("\\\\x[0-9a-fA-F]+"), xpos)) != -1) || + ((opos = s.find(TQRegExp("\\\\[0-7]+"), opos)) != -1)) { + if (xpos != -1) { + valids = "0123456789abcdef"; + leadin = 2; + pos = xpos; + } else { + valids = "01234567"; + leadin = 1; + pos = opos; + } + + c = '\0'; + len = 0; + value = s.mid(pos+leadin, 3); + ptr = value.latin1(); + + while (*ptr != '\0' && (v = valids.find(*ptr++, 0, FALSE)) != -1) { + c = (c * valids.length()) + v; + len++; + } + + value.fill(c, 1); + s.replace(pos, len+leadin, value); + } + + return s; +} + +void Status::fillArray(TQMemArray<int> &array, TQString values, int max) +{ + array.resize(max); + int last = 0; + bool ok; + TQString 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 Status::fillStrList(TQStrList &list, TQString values, int max) +{ + if (!list.isEmpty()) + list.clear(); + + TQString last = ""; + TQString 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 = decodeHexOctString(value); + list.append(last.latin1()); + } +} + +void Status::fillPixmapName(TQStrList &pixmapName) +{ + TQStrList list = pixmapName; + + if (!pixmapName.isEmpty()) + pixmapName.clear(); + + TQString pixmap; + + TQFileInfo fileInfo; + + for (uint i = 0; i < list.count(); i++) { + pixmap = list.at(i); + + if (pixmap.left(1) != "/" && pixmap.left(1) != "~") + pixmap = TDEGlobal::dirs()->findResource("appdata", pixmapDirectory+pixmap); + + fileInfo.setFile(pixmap); + if (!fileInfo.isReadable() || !fileInfo.isFile()) + pixmap = ""; + + pixmapName.append(pixmap.utf8()); + } +} + +void Status::confLevels(bool defGroup) +{ + if (defGroup || kapp->config()->hasKey("Levels")) + maxLevel = kapp->config()->readNumEntry("Levels", 13); +} + +void Status::confMisc(bool defGroup) +{ + if (defGroup || kapp->config()->hasKey("LevelPosition")) + fillArray(levelPos, kapp->config()->readEntry("LevelPosition", "0,1,2,3,,4,,5,,6,,7"), maxLevel); + + 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("LifesPixmapName")) + fillStrList(lifesPixmapName, + kapp->config()->readEntry("LifesPixmapName", "lifes.xpm"), maxLevel+1); + if (defGroup || kapp->config()->hasKey("LevelPixmapName")) + fillStrList(levelPixmapName, + kapp->config()->readEntry("LevelPixmapName", "level.xpm"), maxLevel+1); + +} + +void Status::confScheme() +{ + TQString oldgroup = kapp->config()->group(); + TQString 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(); + + if (mode != -1) { + newgroup.sprintf("Mode %d", mode); + kapp->config()->setGroup(newgroup); + + confMisc(FALSE); + } + + if (scheme != -1) { + newgroup.sprintf("Scheme %d", scheme); + kapp->config()->setGroup(newgroup); + + confMisc(FALSE); + } + + fillPixmapName(lifesPixmapName); + fillPixmapName(levelPixmapName); + + initPixmaps(); + + setFixedHeight(minHeight()); + + kapp->config()->setGroup(oldgroup); +} + +void Status::setScheme(int Scheme, int Mode) +{ + mode = Mode; + scheme = Scheme; + + confScheme(); + + repaint(); +} + +int Status::minHeight() +{ + if (lifesPix->isEmpty() && levelPix->isEmpty()) + return 0; + if (levelPix->isEmpty()) + return lifesPix->at(0)->height(); + if (lifesPix->isEmpty()) + return levelPix->at(0)->height(); + return (lifesPix->at(0)->height() > levelPix->at(0)->height()) ? + lifesPix->at(0)->height() : levelPix->at(0)->height(); +} + +int Status::minWidth() +{ + if (lifesPix->isEmpty() && levelPix->isEmpty()) + return 0; + if (levelPix->isEmpty()) + return lifesPix->at(0)->width(); + if (lifesPix->isEmpty()) + return levelPix->at(0)->width(); + return (lifesPix->at(0)->width() > levelPix->at(0)->width()) ? + lifesPix->at(0)->width() : levelPix->at(0)->width(); +} + +void Status::setLifes(int lifes) +{ + actualLifes = lifes; + repaint(); +} + +void Status::setLevel(int Level) +{ + level = Level; + + initPixmaps(); + + actualLevel = (level > (int) levelPix->count()) ? (int) levelPix->count() : level; + repaint(); +} + +#include "status.moc" diff --git a/tdepacman/status.h b/tdepacman/status.h new file mode 100644 index 0000000..6cbf759 --- /dev/null +++ b/tdepacman/status.h @@ -0,0 +1,74 @@ +#ifndef STATUS_H +#define STATUS_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <kapp.h> + +#include <tdeconfig.h> +#include <tqwidget.h> +#include <tqpixmap.h> +#include <tqstring.h> +#include <tqmemarray.h> +#include <tqptrlist.h> +#include <tqstrlist.h> +#include <tqregexp.h> + +class Status : public TQWidget +{ + Q_OBJECT +public: + Status(TQWidget *parent=0, const char *name=0, int scheme=-1, int mode=-1); + ~Status() {}; + +public slots: + void setScheme(int scheme, int mode); + void setLevel(int level); + void setLifes(int lifes); + +protected: + void paintEvent(TQPaintEvent *); + int minHeight(); + int minWidth(); + + TQString decodeHexOctString(TQString str); + + void fillArray(TQMemArray<int> &, TQString, int); + void fillStrList(TQStrList &, TQString, int); + void fillPixmapName(TQStrList &); + + void confScheme(); + void confLevels(bool defGroup=TRUE); + void confMisc(bool defGroup=TRUE); + + void initPixmaps(); + +private: + TQMemArray<int> levelPos; + int actualLifes; + int actualLevel; + + TQString pixmapDirectory; + + TQStrList lifesPixmapName; + TQStrList levelPixmapName; + + TQString lastLifesPixmapName; + TQString lastLevelPixmapName; + + TQPtrList<TQPixmap> *loadPixmap(TQWidget *parent, TQString pixmapName, + TQPtrList<TQPixmap> *pixmaps=0); + + TQPtrList<TQPixmap> *lifesPix; + TQPtrList<TQPixmap> *levelPix; + + int maxLevel; + int level; + + int scheme; + int mode; +}; + +#endif // STATUS_H diff --git a/tdepacman/tdepacman.cpp b/tdepacman/tdepacman.cpp new file mode 100644 index 0000000..351d56f --- /dev/null +++ b/tdepacman/tdepacman.cpp @@ -0,0 +1,476 @@ +/*************************************************************************** + tdepacman.cpp - description + ------------------- + begin : Sam Jan 19 13:37:57 CET 2002 + copyright : (C) 1998-2003 by Jörg Thönnissen + email : joe@dsite.de + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +// include files for TQt +#include <tqkeycode.h> +#include <tqcolor.h> +#include <tqstring.h> +#include <tqmsgbox.h> + +// include files for TDE +#include <kcolordlg.h> +#include <kstatusbar.h> +#include <kstdaction.h> +#include <kstdgameaction.h> + +// application specific includes +#include "tdepacman.h" + +#define ID_STATUS_MSG 1 + +TDEpacmanApp::TDEpacmanApp(TQWidget *, const char *name) : TDEMainWindow(0, name) +{ + config=kapp->config(); + + /////////////////////////////////////////////////////////////////// + // call inits to invoke all other construction parts + initStatusBar(); + initActions(); + initView(); + + readOptions(); + + highscoresChecked = false; + focusedPause = false; + + connect(view->referee, SIGNAL(setScore(int, int)), view->score, SLOT(setScore(int, int))); + connect(view->referee, SIGNAL(setPoints(int)), view->score, SLOT(set(int))); + connect(view->referee, SIGNAL(setLifes(int)), view->status, SLOT(setLifes(int))); + connect(view->referee, SIGNAL(setLevel(int)), view->status, SLOT(setLevel(int))); + + connect(view->referee, SIGNAL(focusedGamePause()), this, SLOT(slotFocusedGamePause())); + connect(view->referee, SIGNAL(forcedGameHighscores()), this, SLOT(slotForcedGameHighscores())); + + connect(view->score, SIGNAL(gameHighscores()), this, SLOT(slotGameHighscores())); + connect(view->score, SIGNAL(gameFinished()), this, SLOT(slotGameFinished())); +} + +TDEpacmanApp::~TDEpacmanApp() +{ + +} + + +void TDEpacmanApp::initActions() +{ + gameNew = KStdGameAction::gameNew(this, SLOT(slotGameNew()), actionCollection()); + gamePause = KStdGameAction::pause(this, SLOT(slotGamePause()), actionCollection()); + gamePause->setAccel(Key_F3); + gameQuit = KStdGameAction::quit(this, SLOT(slotGameQuit()), actionCollection()); + gameHighscores = KStdGameAction::highscores(this, SLOT(slotGameHighscores()), actionCollection()); + showMenuBar = KStdAction::showMenubar(this, SLOT(slotShowMenuBar()), actionCollection()); + showToolBar = KStdAction::showToolbar(this, SLOT(slotShowToolBar()), actionCollection()); + showStatusBar = KStdAction::showStatusbar(this, SLOT(slotShowStatusBar()), actionCollection()); + showMouseCursor = new TDEToggleAction(i18n("Show Mouse&cursor"), 0, + this, SLOT(slotShowMouseCursor()), actionCollection(), + "options_show_mousecursor"); + selectGraphicScheme = new TDEActionMenu(i18n("&Select graphic scheme"), actionCollection(), + "options_select_graphic_scheme"); + KStdAction::keyBindings(this, SLOT(slotKeyBindings()), actionCollection()); + focusOutPause = new TDEToggleAction(i18n("Pause in &Background"), 0, + this, SLOT(slotFocusOutPause()), actionCollection(), + "options_focus_out_pause"); + focusInContinue = new TDEToggleAction(i18n("Continue in &Foreground"), 0, + this, SLOT(slotFocusInContinue()), actionCollection(), + "options_focus_in_continue"); + + showMenuBar->setStatusText(i18n("Enables/disables the menubar")); + showToolBar->setStatusText(i18n("Enables/disables the toolbar")); + showStatusBar->setStatusText(i18n("Enables/disables the statusbar")); + showMouseCursor->setStatusText(i18n("Enable/disables the mousecursor")); + + // use the absolute path to your tdepacmanui.rc file for testing purpose in createGUI(); + createGUI(); +} + + +void TDEpacmanApp::initStatusBar() +{ + /////////////////////////////////////////////////////////////////// + // STATUSBAR + // TODO: add your own items you need for displaying current application status. + statusBar()->insertItem(i18n("Ready."), ID_STATUS_MSG); +} + +void TDEpacmanApp::initView() +{ + //////////////////////////////////////////////////////////////////// + // create the main widget here that is managed by TDEMainWindow's view-region and + // connect the widget. + + view = new TDEpacmanView(this); + setCentralWidget(view); + + setFixedSize(view->width(), view->height()); + view->referee->setFocus(); +} + +void TDEpacmanApp::saveOptions() +{ + // config->setGroup("General Options"); + config->writeEntry("Geometry", size()); + config->writeEntry("ShowMenubar", showMenuBar->isChecked()); + config->writeEntry("ShowToolbar", showToolBar->isChecked()); + config->writeEntry("ShowStatusbar", showStatusBar->isChecked()); + config->writeEntry("ShowMousecursor", showMouseCursor->isChecked()); + config->writeEntry("FocusOutPause", focusOutPause->isChecked()); + config->writeEntry("FocusInContinue", focusInContinue->isChecked()); + config->writeEntry("ToolBarPos", (int) toolBar("mainToolBar")->barPos()); + config->writeEntry("Scheme", scheme); + config->writeEntry("Mode", mode); +} + +void TDEpacmanApp::readOptions() +{ + + // config->setGroup("General Options"); + + // bar status settings + bool bShowMenubar = config->readBoolEntry("ShowMenubar", true); + showMenuBar->setChecked(bShowMenubar); + slotShowMenuBar(); + + bool bShowToolbar = config->readBoolEntry("ShowToolbar", true); + showToolBar->setChecked(bShowToolbar); + slotShowToolBar(); + + bool bShowStatusbar = config->readBoolEntry("ShowStatusbar", false); + showStatusBar->setChecked(bShowStatusbar); + slotShowStatusBar(); + + // cursor status settings + bool bShowMousecursor = config->readBoolEntry("ShowMousecursor", false); + showMouseCursor->setChecked(bShowMousecursor); + slotShowMouseCursor(); + + // focus status settings + bool bFocusOutPause = config->readBoolEntry("FocusOutPause", false); + focusOutPause->setChecked(bFocusOutPause); + slotFocusOutPause(); + + bool bFocusInContinue = config->readBoolEntry("FocusInContinue", false); + focusInContinue->setChecked(bFocusInContinue); + slotFocusInContinue(); + + // bar position settings + TDEToolBar::BarPosition toolBarPos; + toolBarPos = (TDEToolBar::BarPosition) config->readNumEntry("ToolBarPos", TDEToolBar::Top); + toolBar("mainToolBar")->setBarPos(toolBarPos); + + TQSize size = config->readSizeEntry("Geometry"); + if (!size.isEmpty()) + { + resize(size); + } + + // scheme and mode + scheme = config->readNumEntry("Scheme", -1); + mode = config->readNumEntry("Mode", -1); + readSchemes(); +} + +void TDEpacmanApp::readSchemes() +{ + TQString saveGroup = config->group(); + TQString group; + TQString description; + + int modeCount = config->readNumEntry("ModeCount", -1); + int schemeCount = config->readNumEntry("SchemeCount"); + + modeID.resize(modeCount > 0 ? modeCount : 0); + schemeID.resize(schemeCount); + schemeMode.resize(schemeCount); + + schemesPopup = new TQPtrList<TDEPopupMenu>; + schemesPopup->setAutoDelete(true); + + modesPopup = selectGraphicScheme->popupMenu(); + connect(modesPopup, SIGNAL(activated(int)), this, SLOT(slotSchemeActivated(int))); + + if (schemeCount == 0 || scheme == -1) { + TQMessageBox::warning(this, i18n("Configuration Error"), + i18n("There are no schemes defined,\n" + "or no scheme is selected.")); + return; + } + + // create submenus (TQPopupMenu) for graphic-modes + for (int m = 0; m < modeCount; m++) { + group.sprintf("Mode %d", m); + config->setGroup(group); + + description = config->readEntry("Description", group); + + TDEPopupMenu *p = new TDEPopupMenu; + p->setCheckable(true); + connect(p, SIGNAL(activated(int)), this, SLOT(slotSchemeActivated(int))); + schemesPopup->append(p); + + modeID[m] = modesPopup->insertItem(description, schemesPopup->at(m)); + modesPopup->setItemEnabled(modeID[m], false); + modesPopup->setItemChecked(modeID[m], m == mode); + } + + // create menuitems (insertItem) for graphic-schemes + for (int i = 0; i < schemeCount; i++) { + group.sprintf("Scheme %d", i); + config->setGroup(group); + + description = config->readEntry("Description", group); + schemeMode[i] = config->readNumEntry("Mode", -1); + + if (schemeMode[i] == -1) { + schemeID[i] = modesPopup->insertItem(description); + modesPopup->setItemChecked(schemeID[i], i == scheme); + } else { + schemeID[i] = schemesPopup->at(schemeMode[i])->insertItem(description); + schemesPopup->at(schemeMode[i])->setItemChecked(schemeID[i], i == scheme); + modesPopup->setItemEnabled(modeID[schemeMode[i]], true); + } + } + + config->setGroup(saveGroup); +} + +bool TDEpacmanApp::queryExit() +{ + saveOptions(); + return true; +} + + +///////////////////////////////////////////////////////////////////// +// SLOT IMPLEMENTATION +///////////////////////////////////////////////////////////////////// + +void TDEpacmanApp::slotGameNew() +{ + // enable the gameHighscores action, if disabled by forced highscores mode + if (!gameHighscores->isEnabled()) + gameHighscores->setEnabled(true); + + // hide highscores and show board again, if in highscores mode + if (highscoresChecked) + slotGameHighscores(); + + // deactivate pause and uncheck the menuitem, if in pause state + if (gamePause->isChecked()) { + gamePause->setChecked(false); + slotGamePause(); + } + // disable menuitem to prevent interruption of the game + gameNew->setEnabled(false); + + view->referee->play(); +} + +void TDEpacmanApp::slotGamePause() +{ + view->referee->pause(); + view->score->setPause(gamePause->isChecked()); +} + +void TDEpacmanApp::slotFocusedGamePause() +{ + // if an focus-event triggers the pause, toggle the gamePause checked + gamePause->setChecked(!gamePause->isChecked()); + focusedPause = !focusedPause; + + slotGamePause(); +} + +void TDEpacmanApp::slotGameHighscores() +{ + // toggle highscores mode flag + highscoresChecked = !highscoresChecked; + + view->referee->toggleHallOfFame(); + + // show highscore (by lowering referee and status) or return to play (by raising them again) + if (highscoresChecked) { + view->referee->lower(); + view->status->lower(); + } else { + view->status->raise(); + view->referee->raise(); + view->referee->setFocus(); + + // after forced highscores comes the intro again + if (!gameHighscores->isEnabled()) { + gameHighscores->setEnabled(true); + view->referee->intro(); + } + } +} + +void TDEpacmanApp::slotForcedGameHighscores() +{ + // disable menuitem to prevent closing highscores display + gameHighscores->setEnabled(false); + + slotGameHighscores(); +} + +void TDEpacmanApp::slotGameQuit() +{ + slotStatusMsg(i18n("Exiting...")); + saveOptions(); + kapp->quit(); +} + +void TDEpacmanApp::slotShowMenuBar() +{ + slotStatusMsg(i18n("Toggling menubar...")); + /////////////////////////////////////////////////////////////////// + // turn Menubar on or off + if(!showMenuBar->isChecked()) { + menuBar()->hide(); + setFixedSize(view->width(), view->height()); + } else { + menuBar()->show(); + } + + slotStatusMsg(i18n("Ready.")); +} + +void TDEpacmanApp::slotShowToolBar() +{ + slotStatusMsg(i18n("Toggling toolbar...")); + /////////////////////////////////////////////////////////////////// + // turn Toolbar on or off + if(!showToolBar->isChecked()) { + toolBar("mainToolBar")->hide(); + setFixedSize(view->width(), view->height()); + } else { + toolBar("mainToolBar")->show(); + } + + slotStatusMsg(i18n("Ready.")); +} + +void TDEpacmanApp::slotShowStatusBar() +{ + slotStatusMsg(i18n("Toggle the statusbar...")); + /////////////////////////////////////////////////////////////////// + // turn Statusbar on or off + if(!showStatusBar->isChecked()) { + statusBar()->hide(); + setFixedSize(view->width(), view->height()); + } else { + statusBar()->show(); + } + + slotStatusMsg(i18n("Ready.")); +} + +void TDEpacmanApp::slotShowMouseCursor() +{ + slotStatusMsg(i18n("Toggle the mousecursor...")); + /////////////////////////////////////////////////////////////////// + // turn Mousecursor on or off + if(!showMouseCursor->isChecked()) { + view->setCursor(blankCursor); + } else { + view->setCursor(arrowCursor); + } + + slotStatusMsg(i18n("Ready.")); +} + +void TDEpacmanApp::slotSchemeActivated(int id) +{ + slotStatusMsg(i18n("Graphic scheme selected...")); + /////////////////////////////////////////////////////////////////// + // select activated scheme/mode + + mode = -1; + scheme = -1; + + for (uint s = 0; s < schemeID.size(); s++) { + if (schemeID[s] == id) { + scheme = s; + mode = schemeMode[s]; + } + if (schemeMode[s] == -1) { + modesPopup->setItemChecked(schemeID[s], schemeID[s] == id); + } else { + modesPopup->setItemChecked(modeID[schemeMode[s]], schemeMode[s] == mode); + schemesPopup->at(schemeMode[s])->setItemChecked(schemeID[s], schemeID[s] == id); + } + } + + view->setScheme(scheme, mode); + setFixedSize(view->width(), view->height()); + + slotStatusMsg(i18n("Ready.")); +} + +void TDEpacmanApp::slotFocusOutPause() +{ + slotStatusMsg(i18n("Toggle focusOutPause...")); + /////////////////////////////////////////////////////////////////// + // turn focusOutPause on or off + view->referee->setFocusOutPause(focusOutPause->isChecked()); + + slotStatusMsg(i18n("Ready.")); +} + +void TDEpacmanApp::slotFocusInContinue() +{ + slotStatusMsg(i18n("Toggle focusInContinue...")); + /////////////////////////////////////////////////////////////////// + // turn focusInContinue on or off + view->referee->setFocusInContinue(focusInContinue->isChecked()); + + slotStatusMsg(i18n("Ready.")); +} + +void TDEpacmanApp::slotKeyBindings() +{ + slotStatusMsg(i18n("Configure key bindings...")); + /////////////////////////////////////////////////////////////////// + // configure key bindings + PKeys *keys = new PKeys(); + if (keys->exec() == TQDialog::Accepted) { + view->referee->initKeys(); + view->score->initKeys(); + } + delete keys; + + slotStatusMsg(i18n("Ready.")); +} + +void TDEpacmanApp::slotGameFinished() +{ + slotStatusMsg(i18n("Game finished...")); + /////////////////////////////////////////////////////////////////// + // enable/disable the menuitem + gameNew->setEnabled(true); + + slotStatusMsg(i18n("Ready.")); +} + +void TDEpacmanApp::slotStatusMsg(const TQString &text) +{ + /////////////////////////////////////////////////////////////////// + // change status message permanently + statusBar()->clear(); + statusBar()->changeItem(text, ID_STATUS_MSG); +} + +#include "tdepacman.moc" diff --git a/tdepacman/tdepacman.desktop b/tdepacman/tdepacman.desktop new file mode 100644 index 0000000..8d69824 --- /dev/null +++ b/tdepacman/tdepacman.desktop @@ -0,0 +1,16 @@ +[Desktop Entry] +Name=TDEpacman + +GenericName=Arcade Game + +Comment=A simple clone of the classic arcade game Pac-Man + +Keywords=arcade;pacman;dots;ghosts;level; + +Type=Application +Exec=tdepacman -caption "%c" %i %m +Icon=tdepacman.png +MiniIcon=tdepacman.png +Terminal=false +X-DocPath=tdepacman/index.html +Categories=Qt;TDE;Game;ArcadeGame; diff --git a/tdepacman/tdepacman.h b/tdepacman/tdepacman.h new file mode 100644 index 0000000..65740ed --- /dev/null +++ b/tdepacman/tdepacman.h @@ -0,0 +1,185 @@ +/*************************************************************************** + tdepacman.h - description + ------------------- + begin : Sam Jan 19 13:37:57 CET 2002 + copyright : (C) 1998-2003 by Jörg Thönnissen + email : joe@dsite.de + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef TDEPACMAN_H +#define TDEPACMAN_H + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +// include files for TQt +#include <tqptrlist.h> +#include <tqfileinf.h> +#include <tqregexp.h> + +//include files for TDE +#include <kapp.h> +#include <tdemainwindow.h> +#include <tdepopupmenu.h> +#include <tdeaction.h> +#include <tdelocale.h> +#include <tdemenubar.h> + +// application specific includes +#include "tdepacmanview.h" +#include "referee.h" +#include "status.h" +#include "score.h" +#include "keys.h" + +// forward declaration of the TDEpacman classes +class TDEpacmanView; + +/** + * The base class for TDEpacman application. + */ +class TDEpacmanApp : public TDEMainWindow +{ + Q_OBJECT + + friend class TDEpacmanView; + + public: + /** constructor of TDEpacmanApp, calls all init functions to create the application. + */ + TDEpacmanApp(TQWidget *parent = 0, const char *name = 0); + virtual ~TDEpacmanApp(); + + protected: + /** save general Options like all bar positions and status as well as the application specific + * Options to the configuration file + */ + void saveOptions(); + /** read general Options again and initialize all variables + */ + void readOptions(); + /** read graphic schemes and build menu items for selection + */ + void readSchemes(); + /** initializes the TDEActions of the application */ + void initActions(); + /** sets up the statusbar for the main window by initialzing a statuslabel. + */ + void initStatusBar(); + /** creates the centerwidget of the KTMainWindow instance and sets it as the view + */ + void initView(); + /** queryExit is called by KTMainWindow when the last window of the application is going to be closed + * during the closeEvent(). + * Against the default implementation that just returns true, this calls saveOptions() to save the + * settings of the window's properties. + * @see KTMainWindow#queryExit + * @see KTMainWindow#closeEvent + */ + virtual bool queryExit(); + + + public slots: + /** play new game + */ + void slotGameNew(); + /** pause (continue) game + */ + void slotGamePause(); + /** pause (continue) game triggered by focus events + */ + void slotFocusedGamePause(); + /** toggle the highscores + */ + void slotGameHighscores(); + /** toggle the highscores, forced by the referee + */ + void slotForcedGameHighscores(); + /** save the options, then quits the application. + */ + void slotGameQuit(); + /** toggles the menubar + */ + void slotShowMenuBar(); + /** toggles the toolbar + */ + void slotShowToolBar(); + /** toggles the statusbar + */ + void slotShowStatusBar(); + /** toggles the mousecursor + */ + void slotShowMouseCursor(); + /** graphic scheme activated + * @param id the id of the activated/selected menuitem + */ + void slotSchemeActivated(int id); + /** toggles the focus out pause + */ + void slotFocusOutPause(); + /** toggles the focus in continue + */ + void slotFocusInContinue(); + /** changes the statusbar contents for the standard label permanently, used to indicate current actions. + * @param text the text that is displayed in the statusbar + */ + void slotStatusMsg(const TQString &text); + /** configure keysbindings dialog + */ + void slotKeyBindings(); + /** game (including highscores displayed) has been finished + */ + void slotGameFinished(); + + private: + /** the configuration object of the application */ + TDEConfig *config; + /** view is the main widget which represents your working area. The View + * class should handle all events of the view widget. It is kept empty so + * you can create your view according to your application's needs by + * changing the view class. + */ + TDEpacmanView *view; + + // TDEAction pointers to enable/disable actions + TDEAction* gameNew; + TDEToggleAction* gamePause; + TDEAction* gameHighscores; + TDEAction* gameQuit; + TDEToggleAction* showMenuBar; + TDEToggleAction* showToolBar; + TDEToggleAction* showStatusBar; + TDEToggleAction* showMouseCursor; + TDEToggleAction* focusOutPause; + TDEToggleAction* focusInContinue; + TDEActionMenu* selectGraphicScheme; + + // active scheme/mode + int scheme; + int mode; + + TDEPopupMenu *modesPopup; // TDEAction main scheme selection menu + TQPtrList<TDEPopupMenu> *schemesPopup; // submenus for selecting scheme + + // ID's of the menuitem(s) for finding/selecting scheme by id + TQMemArray<int> modeID; + TQMemArray<int> schemeID; + + TQMemArray<int> schemeMode; // mode(group) of the schemes, -1 if no group + + bool highscoresChecked; // highscores display active + bool focusedPause; // Pause caused by focusEvents +}; + +#endif // TDEPACMAN_H diff --git a/tdepacman/tdepacmanrc b/tdepacman/tdepacmanrc new file mode 100644 index 0000000..156c455 --- /dev/null +++ b/tdepacman/tdepacmanrc @@ -0,0 +1,70 @@ +FocusInContinue=true +FocusOutPause=true +HideMouseCursor=false +LevelPixmapName=fruit.xpm +Mode=0 +ModeCount=2 +Scheme=0 +SchemeCount=5 +downKey=Down +leftKey=Left +rightKey=Right +upKey=Up + +[Mode 0] +Description=&Pacman + +[Mode 1] +Description=&Ms.Pacman +DyingAnimationMS=150 +EnergizerPixmapName=switch.xpm,,,switch02.xpm,,,switch03.xpm,,,,switch.xpm,,,,,,,,,,,,switch03.xpm,,,,switch.xpm +ExtraLifeScore=-10000,-30000,-50000,30000 +FruitScore=100,200,500,700,1000,2000,5000 +FruitScorePixmapName=fruitscore.xpm +LevelPosition=0,1,2,3,4,5,6 +Levels=29 +MapDirectory=mspacman +MapName=map01,,,map02,,,map03,,,,map04,,,,map03,,,,map04,,,,map03,,,,map04 +PointPixmapName=point.xpm,,,point02.xpm,,,point03.xpm,,,,point.xpm,,,,,,,,,,,,point03.xpm,,,,point.xpm +PrisonPixmapName=prison.xpm,,,prison02.xpm,,,prison03.xpm,,,,prison04.xpm,,,,prison05.xpm,,,,prison06.xpm,,,,prison03.xpm,,,,prison04.xpm +WallPixmapName=wall.xpm,,,wall02.xpm,,,wall03.xpm,,,,wall04.xpm,,,,wall05.xpm,,,,wall06.xpm,,,,wall03.xpm,,,,wall04.xpm + +[Scheme 0] +Description=&MIDWAY MFG.CO. +Description[de]=&MIDWAY MFG.CO. +Font=font-smooth.pbm +Mode=0 +PixmapDirectory= + +[Scheme 1] +Description=MIDWAY MFG.CO. (&tiny) +Description[de]=MIDWAY MFG.CO. (&klein) +Font=font-small.pbm +Mode=0 +PixmapDirectory=tiny + +[Scheme 2] +Description=K&Zacman (incomplete) +Description[de]=K&Zacman (unvollständig) +Font=font-smooth.pbm +FruitPixmapName=../fruit.xpm +LevelPixmapName=../fruit.xpm +PixmapDirectory=zacman +PrisonPixmapName=../prison.xpm + +[Scheme 3] +Description=&MIDWAY MFG.CO. +EyesPixmapName=../eyes.xpm +Font=font-smooth.pbm +Mode=1 +MonsterPixmapName=../monster.xpm +PixmapDirectory=mspacman + +[Scheme 4] +Description=MIDWAY MFG.CO. (&tiny) +Description[de]=MIDWAY MFG.CO. (&klein) +EyesPixmapName=../tiny/eyes.xpm +Font=font-small.pbm +Mode=1 +MonsterPixmapName=../tiny/monster.xpm +PixmapDirectory=mspacman-tiny diff --git a/tdepacman/tdepacmanui.rc b/tdepacman/tdepacmanui.rc new file mode 100644 index 0000000..9228ab9 --- /dev/null +++ b/tdepacman/tdepacmanui.rc @@ -0,0 +1,18 @@ +<!DOCTYPE kpartgui> +<kpartgui name="tdepacman" version="0.3.2"> +<MenuBar> + <Menu name="game"><text>&Game</text> + </Menu> + <Menu name="settings"><text>&Settings</text> + <Action name="options_show_mousecursor" append="show_merge"/> + <Action name="options_select_graphic_scheme" append="configure_merge"/> + <Action name="options_focus_out_pause" append="configure_merge"/> + <Action name="options_focus_in_continue" append="configure_merge"/> + </Menu> +</MenuBar> + +<ToolBar noMerge="1" name="mainToolBar"><text>Main Toolbar</text> + <Action name="game_new"/> + <Action name="game_pause"/> +</ToolBar> +</kpartgui> diff --git a/tdepacman/tdepacmanview.cpp b/tdepacman/tdepacmanview.cpp new file mode 100644 index 0000000..1a9d3e4 --- /dev/null +++ b/tdepacman/tdepacmanview.cpp @@ -0,0 +1,163 @@ +/*************************************************************************** + tdepacmanview.cpp - description + ------------------- + begin : Sam Jan 19 13:37:57 CET 2002 + copyright : (C) 1998-2003 by Jörg Thönnissen + email : joe@dsite.de + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +// include files for TQt +#include <tqmessagebox.h> + +// include files for TDE +#include <kapp.h> +#include <tdeconfig.h> +#include <kstddirs.h> + +// application specific includes +#include "tdepacmanview.h" +#include "bitfont.h" +#include "score.h" +#include "referee.h" +#include "status.h" + +TDEpacmanView::TDEpacmanView( TQWidget *parent, const char *name) : TQWidget( parent, name ) +{ + bitfont = NULL; + fontName = ""; + + scheme = mode = -1; + confScheme(); + + score = new Score(this, name, scheme, mode, bitfont); + referee = new Referee( this, name, scheme, mode, bitfont); + status = new Status(this, name, scheme, mode); + + setFixedSize(referee->width(), bitfont->height()*3 + referee->height() + status->height()); +} + +TDEpacmanView::~TDEpacmanView() +{ +} + +void TDEpacmanView::confMisc(bool defGroup) +{ + TDEStandardDirs *dirs = TDEGlobal::dirs(); + TQString findPath; + + if (defGroup || kapp->config()->hasKey("Font")) { + fontName = kapp->config()->readEntry("Font"); + + if (fontName.left(1) != "/" && fontName.left(1) != "~") + fontName.insert(0, "fonts/"); + if (fontName.right(1) == "/") + fontName.append("font.xbm"); + + findPath = dirs->findResource("appdata", fontName); + if (!findPath.isEmpty()) + fontName = findPath; + + bitfontFirstChar = kapp->config()->readNumEntry("FontFirstChar", 0x0e); + bitfontLastChar = kapp->config()->readNumEntry("FontLastChar", 0x5f); + } +} + +void TDEpacmanView::confScheme() +{ + TQString lastFontName = fontName; + TQString oldgroup = kapp->config()->group(); + TQString 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); + } + } + + confMisc(); + + if (mode != -1) { + newgroup.sprintf("Mode %d", mode); + kapp->config()->setGroup(newgroup); + + confMisc(FALSE); + } + + if (scheme != -1) { + newgroup.sprintf("Scheme %d", scheme); + kapp->config()->setGroup(newgroup); + + confMisc(FALSE); + } + + if (lastFontName != fontName) { + + if (bitfont != 0) + delete bitfont; + + bitfont = new Bitfont(fontName, bitfontFirstChar, bitfontLastChar); + if (bitfont->width() == 0 || bitfont->height() == 0) { + TQString msg = i18n("The bitfont could not be contructed.\n\n" + "The file '@FONTNAME@' does not exist,\n" + "or is of an unknown format."); + msg.replace(TQRegExp("@FONTNAME@"), fontName); + // TQMessageBox::critical(this, i18n("Initialization Error"), msg); + printf("%s\n", msg.local8Bit().data()); + } + } + + kapp->config()->setGroup(oldgroup); +} + +void TDEpacmanView::setScheme(int Scheme, int Mode) +{ + mode = Mode; + scheme = Scheme; + + confScheme(); + + score->setScheme(Scheme, Mode, bitfont); + referee->setScheme(Scheme, Mode, bitfont); + status->setScheme(Scheme, Mode); + + setFixedSize(referee->width(), + bitfont->height()*3 + referee->height() + status->height()); + updateGeometry(); + + score->repaint(FALSE); + referee->repaint(FALSE); + status->repaint(FALSE); +} + +void TDEpacmanView::resizeEvent( TQResizeEvent * ) +{ + referee->setGeometry(0, bitfont->height()*3, referee->width(), referee->height()); + referee->setBackgroundColor(BLACK); + + status->setGeometry(0, bitfont->height()*3+referee->height(), referee->width(), + status->height()); + status->setBackgroundColor(BLACK); + + score->setGeometry(0, 0, referee->width(), bitfont->height()*3+referee->height()+status->height()); + score->setBackgroundColor(BLACK); +} + +#include "tdepacmanview.moc" diff --git a/tdepacman/tdepacmanview.h b/tdepacman/tdepacmanview.h new file mode 100644 index 0000000..a7792df --- /dev/null +++ b/tdepacman/tdepacmanview.h @@ -0,0 +1,68 @@ +/*************************************************************************** + tdepacmanview.h - description + ------------------- + begin : Sam Jan 19 13:37:57 CET 2002 + copyright : (C) 1998-2003 by Jörg Thönnissen + email : joe@dsite.de + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef TDEPACMANVIEW_H +#define TDEPACMANVIEW_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +//include files for TQt +#include <tqwidget.h> +#include <tqregexp.h> + +// application specific includes +#include "score.h" +#include "referee.h" +#include "status.h" +#include "painter.h" + +/** The TDEpacmanView class provides the view widget for the TDEpacmanApp instance. + * The View instance inherits TQWidget as a base class and represents the view object of a KTMainWindow. + */ +class TDEpacmanView : public TQWidget +{ + Q_OBJECT +public: + /** Constructor for the main view */ + TDEpacmanView ( TQWidget *parent = 0, const char *name = 0); + /** Destructor for the main view */ + virtual ~TDEpacmanView(); + + void setScheme(int scheme=-1, int mode=-1); + Score *score; + Referee *referee; + Status *status; + +protected: + void confScheme(); + void confMisc(bool defGroup=TRUE); + void resizeEvent( TQResizeEvent * ); + +private: + Bitfont *bitfont; + uchar bitfontFirstChar; + uchar bitfontLastChar; + + TQString fontName; + + int scheme; + int mode; +}; + +#endif // TDEPACMANVIEW_H |