diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | c90c389a8a8d9d8661e9772ec4144c5cf2039f23 (patch) | |
tree | 6d8391395bce9eaea4ad78958617edb20c6a7573 /ksnake/rattler.cpp | |
download | tdegames-c90c389a8a8d9d8661e9772ec4144c5cf2039f23.tar.gz tdegames-c90c389a8a8d9d8661e9772ec4144c5cf2039f23.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegames@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'ksnake/rattler.cpp')
-rw-r--r-- | ksnake/rattler.cpp | 692 |
1 files changed, 692 insertions, 0 deletions
diff --git a/ksnake/rattler.cpp b/ksnake/rattler.cpp new file mode 100644 index 00000000..8bea1c0c --- /dev/null +++ b/ksnake/rattler.cpp @@ -0,0 +1,692 @@ +/** + * Copyright Michel Filippi <[email protected]> + * Robert Williams + * Andrew Chant <[email protected]> + * André Luiz dos Santos <[email protected]> + * Benjamin Meyer <[email protected]> + * + * This file is part of the ksnake package + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "rattler.h" + +#include <qtimer.h> +#include <qlabel.h> +#include <kapplication.h> +#include <kstdgameaction.h> +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <qbitarray.h> +#include <kstandarddirs.h> + +#include "level.h" +#include "basket.h" +#include "settings.h" + +QBitArray gameState(5); +QLabel *label = 0; +int speed[4] = { 130, 95, 55, 40 }; + +Rattler::Rattler( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + setFocusPolicy(QWidget::StrongFocus); + + numBalls = Settings::balls(); + ballsAI = Settings::ballsAI(); + numSnakes = Settings::computerSnakes(); + snakesAI = Settings::snakesAI(); + skill = Settings::skill(); + room = Settings::startingRoom(); + + board = new Board(35*35); + level = new Level(board); + pix = new PixServer(board); + basket = new Basket(board, pix); + samy = new SamySnake(board, pix); + + computerSnakes = new QPtrList<CompuSnake>; + computerSnakes->setAutoDelete( true ); + + balls = new QPtrList<Ball>; + balls->setAutoDelete( true ); + + connect( samy, SIGNAL(closeGate(int)), this, SLOT(closeGate(int))); + connect( samy, SIGNAL(score(bool, int)), this, SLOT(scoring(bool,int))); + connect( samy, SIGNAL(goingOut()), this, SLOT(speedUp())); + connect( basket, SIGNAL(openGate()), this, SLOT(openGate())); + + gameState.fill(false); + gameState.setBit(Demo); + + timerCount = 0; + QTimer::singleShot( 2000, this, SLOT(demo()) ); // Why wait? + + backgroundPixmaps = + KGlobal::dirs()->findAllResources("appdata", "backgrounds/*.png"); +} + +Rattler::~Rattler() +{ + delete level; + delete balls; + delete computerSnakes; + delete basket; + delete samy; + delete pix; + delete board; +} + +/** + * One of the settings changed, load our settings + */ +void Rattler::loadSettings(){ + setBalls(Settings::balls()); + setBallsAI(Settings::ballsAI()); + setCompuSnakes(Settings::computerSnakes()); + setSnakesAI(Settings::snakesAI()); + setSkill(Settings::skill()); + setRoom(Settings::startingRoom()); + reloadRoomPixmap(); +} + +void Rattler::paintEvent( QPaintEvent *e) +{ + QRect rect = e->rect(); + + if (rect.isEmpty()) + return; + QPixmap levelPix = pix->levelPix(); + + basket->repaint(true); + + bitBlt(this, rect.x(), rect.y(), + &levelPix, rect.x(), rect.y(), rect.width(), rect.height()); +} + +void Rattler::timerEvent( QTimerEvent * ) +{ + timerCount++; + + if ( !leaving ) // advance progressBar unless Samy + emit advance(); // is going out + + for (CompuSnake *c = computerSnakes->first(); c != 0; c = computerSnakes->next()){ + if(c) { + c->nextMove(); + c->repaint(false); + } + } + + for (Ball *b = balls->first(); b != 0; b = balls->next()){ + if (b) { + b->nextMove(); + b->repaint(); + } + } + + + samyState state = ok; + + if(!gameState.testBit(Demo)) + { + state = samy->nextMove(direction); + samy->repaint( false ); + } + + basket->repaint( false); + + if (state == ko) + newTry(); + else if (state == out) + levelUp(); + + QPixmap levelPix = pix->levelPix(); + bitBlt(this, 0, 0, &levelPix, 0, 0, rect().width(), rect().height()); +} + +void Rattler::keyPressEvent( QKeyEvent *k ) +{ + if (gameState.testBit(Paused)) + return; + + KKey key(k); + if(actionCollection->action("Pl1Up")->shortcut().contains(key)) + direction = N; + else if(actionCollection->action("Pl1Down")->shortcut().contains(key)) + direction = S; + else if(actionCollection->action("Pl1Right")->shortcut().contains(key)) + direction = E; + else if(actionCollection->action("Pl1Left")->shortcut().contains(key)) + direction = W; + else if ((k->key() == Key_Return) || + (k->key() == Key_Enter) || (k->key() == Key_Space)) { + if (!gameState.testBit(Demo)) { + k->ignore(); + return; + } + restart(); + } + else { + k->ignore(); + return; + } + k->accept(); +} + +void Rattler::mousePressEvent( QMouseEvent *e ) +{ + if (gameState.testBit(Paused)) + return; + + uint button = e->button(); + if (button == Qt::RightButton) + { + switch (direction) + { + case N: direction=E; + break; + case E: direction=S; + break; + case S: direction=W; + break; + case W: direction=N; + break; + } + e->accept(); + } + else if (button == Qt::LeftButton) + { + switch (direction) + { + case N: direction=W; + break; + case E: direction=N; + break; + case S: direction=E; + break; + case W: direction=S; + break; + } + e->accept(); + } + else + e->ignore(); +} + +void Rattler::closeGate(int i) +{ + board->set(i, brick); + pix->restore(i); +} + +void Rattler::openGate() +{ + board->set(NORTH_GATE, empty); + pix->erase(NORTH_GATE); +} + +void Rattler::scoring(bool win, int i) +{ + Fruits fruit = basket->eaten(i); + + if (gameState.testBit(Demo)) + win = true; + + int p = 0; + + switch (fruit) { + + case Red: + if (win) { + if (!timerHasRunOut) + p = 1 + skill*2; + else p = 1; + } + else p = -2; + break; + + case Golden: + if (win) { + if (!timerHasRunOut) + p = 2 + (skill*2) + (numSnakes*2) + (numBalls+2); + else p = 2; + } + else p = -5; + break; + + default: + break; + + } + score(p); +} + +void Rattler::score(int p) +{ + points += p; + points = (points < 0 ? 0 : points); + emit setPoints(points); + + while (points > check*50) { + check++; + if (trys < 7 && !gameState.testBit(Demo)) + emit setTrys(++trys); + } +} + +void Rattler::killedComputerSnake() +{ + if (!gameState.testBit(Demo)) + score(20); +} + +void Rattler::pause() +{ + if (gameState.testBit(Init)) + return; + + if (gameState.testBit(Playing)) { + + gameState.toggleBit(Playing); + gameState.setBit(Paused); + stop(); + + KAction* tempPauseAction = KStdGameAction::pause(); + + label = new QLabel(this); + label->setFont( QFont( "Times", 14, QFont::Bold ) ); + label->setText(i18n("Game Paused\n Press %1 to resume\n") + .arg(tempPauseAction->shortcutText())); + label->setAlignment( AlignCenter ); + label->setFrameStyle( QFrame::Panel | QFrame::Raised ); + label->setGeometry(182, 206, 198, 80); + label->show(); + + delete tempPauseAction; + //emit togglePaused(); + } + else if (gameState.testBit(Paused)) { + gameState.toggleBit(Paused); + gameState.setBit(Playing); + start(); + cleanLabel(); + //emit togglePaused(); + } +} + +void Rattler::cleanLabel() +{ + if (label) { + delete label; + label = 0; + } +} + +void Rattler::restartDemo() +{ + if (!gameState.testBit(Demo)) + return; + + int r = 50000+ (kapp->random() % 30000); + QTimer::singleShot( r, this, SLOT(restartDemo()) ); + + stop(); + level->create(Intro); + pix->initRoomPixmap(); + init(false); + repaint(); + start(); +} + +void Rattler::demo() +{ + static bool first_time = true; + + if(gameState.testBit(Init) || gameState.testBit(Playing)) + return; + + stop(); + + QTimer::singleShot( 60000, this, SLOT(restartDemo()) ); + gameState.fill(false); + gameState.setBit(Init); + gameState.setBit(Demo); + resetFlags(); + + if(!first_time) { + level->create(Intro); + pix->initRoomPixmap(); + } + repaint(rect(), false); + init(false); + run(); + first_time = false; +} + +void Rattler::restart() +{ + if (gameState.testBit(Init)) + return; + stop(); + + if (gameState.testBit(Paused) || gameState.testBit(Playing)) { + + switch( KMessageBox::questionYesNo( this, + i18n("A game is already started.\n" + "Start a new one?\n"), i18n("Snake Race"), i18n("Start New"), i18n("Keep Playing"))) { + case KMessageBox::No: + if (!gameState.testBit(Paused)) + start(); + return; + break; + case KMessageBox::Yes: + ; + } + } + + gameState.fill(false); + gameState.setBit(Init); + gameState.setBit(Playing); + + resetFlags(); + + level->setLevel(room); + level->create(Banner); + pix->initRoomPixmap(); + + cleanLabel(); + + repaint(); + QTimer::singleShot( 2000, this, SLOT(showRoom()) ); +} + +void Rattler::newTry() +{ + stop(); + + if(trys==0) { + gameState.fill(false); + gameState.setBit(Over); + level->create(GameOver); + pix->initRoomPixmap(); + repaint(); + QTimer::singleShot( 5000, this, SLOT(demo()) ); + emit setScore(points); + return; + } + --trys; + gameState.fill(false); + gameState.setBit(Init); + gameState.setBit(Playing); + + level->create(Room); + pix->initRoomPixmap(); + init(true); + repaint(); + QTimer::singleShot( 1000, this, SLOT(run()) ); +} + +void Rattler::levelUp() +{ + stop(); + + gameState.fill(false); + gameState.setBit(Init); + gameState.setBit(Playing); + + score (2*(level->getLevel())+(2*numSnakes)+(2*numBalls)+(2*skill)); + + level->nextLevel(); + level->create(Banner); + pix->initRoomPixmap(); + repaint(); + + QTimer::singleShot( 2000, this, SLOT(showRoom()) ); +} + +/* this slot is called by the progressBar when value() == 0 +or by a compuSnake wich manages to exit */ +void Rattler::restartTimer() +{ + timerHasRunOut = true; + timerCount = 0; + emit rewind(); + + if ( board->isEmpty(NORTH_GATE) ) + closeGate(NORTH_GATE); + basket->newApples(); +} + +void Rattler::speedUp() +{ + leaving = true; + stop(); + start( 30 ); +} + +void Rattler::resetFlags() +{ + trys = 2; + check = 1; + points = 0; +} + +void Rattler::showRoom() +{ + level->create(Room); + pix->initRoomPixmap(); + init(true); + repaint(); + QTimer::singleShot( 1000, this, SLOT(run()) ); +} + +void Rattler::init(bool play) +{ + leaving = false; + timerHasRunOut = false; + timerCount = 0; + emit rewind(); + + emit setTrys(trys); + emit setPoints(points); + + basket->clear(); + basket->newApples(); + restartBalls(play); + restartComputerSnakes(play); + if(play) + samy->init(); +} + +void Rattler::run() +{ + direction = N; + gameState.toggleBit(Init); + start(); +} + +void Rattler::start() +{ + gameTimer = startTimer( speed [skill] ); +} + +void Rattler::start(int t) +{ + gameTimer = startTimer(t); +} + +void Rattler::stop() +{ + killTimers(); +} + +void Rattler::restartComputerSnakes(bool play) +{ + if( !computerSnakes->isEmpty()) + computerSnakes->clear(); + + int i = (play == false && numSnakes == 0 ? 1 : numSnakes); + + for (int x = 0; x < i; x++) { + CompuSnake *as; + switch(snakesAI) { + default: // random. + as = new CompuSnake(board, pix); + break; + case 1: // eater. + as = new EaterCompuSnake(board, pix); + break; + case 2: // killer. + as = new KillerCompuSnake(board, pix); + break; + } + connect( as, SIGNAL(closeGate(int)), this, SLOT(closeGate(int))); + connect( as, SIGNAL(restartTimer()), this, SLOT(restartTimer())); + connect( as, SIGNAL(score(bool, int)), this, SLOT(scoring(bool,int))); + connect( as, SIGNAL(killed()), this, SLOT(killedComputerSnake())); + computerSnakes->append(as); + } +} + +void Rattler::restartBalls(bool play) +{ + if( !balls->isEmpty()) + balls->clear(); + + int i = (play == false && numBalls == 0 ? 1 : numBalls); + + for (int x = 0; x < i; x++) { + Ball *b; + switch(ballsAI) { + default: // default. + b = new Ball(board, pix); + break; + case 1: // dumb. + b = new DumbKillerBall(board, pix); + break; + case 2: // smart. + b = new KillerBall(board, pix); + break; + } + balls->append(b); + } +} + +void Rattler::setBalls(int newNumBalls) +{ + numBalls = balls->count(); + + if (!(gameState.testBit(Playing) || gameState.testBit(Demo)) || numBalls == newNumBalls) + return; + + while ( newNumBalls > numBalls) { + Ball *b = new Ball(board, pix); + balls->append(b); + numBalls++; + } + while (newNumBalls < numBalls) { + Ball *b = balls->getLast(); + b->zero(); + balls->removeLast(); + numBalls--; + } +} + +void Rattler::setBallsAI(int i) +{ + ballsAI = i; +} + +void Rattler::resizeEvent( QResizeEvent * ) +{ + pix->initPixmaps(); + pix->initBrickPixmap(); + pix->initbackPixmaps(); + pix->initRoomPixmap(); +} + +void Rattler::setCompuSnakes(int i) +{ + CompuSnake *cs; + numSnakes = i; + int count = computerSnakes->count(); + + if (gameState.testBit(Playing) || gameState.testBit(Demo)) { + if ( i > count) { + while ( i > count) { + CompuSnake *as; + switch(snakesAI) { + default: // random. + as = new CompuSnake(board, pix); + break; + case 1: // eater. + as = new EaterCompuSnake(board, pix); + break; + case 2: // killer. + as = new KillerCompuSnake(board, pix); + break; + } + connect( as, SIGNAL(closeGate(int)), this, SLOT(closeGate(int))); + connect( as, SIGNAL(restartTimer()), this, SLOT(restartTimer())); + connect( as, SIGNAL(score(bool, int)), this, SLOT(scoring(bool,int))); + connect( as, SIGNAL(killed()), this, SLOT(killedComputerSnake())); + computerSnakes->append(as); + i--; + } + } + else if (i < count) { + while (i < count) { + cs = computerSnakes->getLast(); + cs->zero(); + computerSnakes->removeLast(); + i++; + } + } + } +} + +void Rattler::setSnakesAI(int i) +{ + snakesAI = i; +} + +void Rattler::setSkill(int i) +{ + skill = i; + if (gameState.testBit(Playing) || gameState.testBit(Demo)) { + stop(); + start(); + } +} + +void Rattler::setRoom(int i) +{ + room = i; +} + +void Rattler::reloadRoomPixmap() +{ + pix->initbackPixmaps(); + pix->initRoomPixmap(); + demo(); +} + +#include "rattler.moc" + |