Commit 641ce99f authored by Dmitry Suzdalev's avatar Dmitry Suzdalev
Browse files

Score is working now.

And game over condition is checked,
so no more Great Hungry Infinite Loop at the end.
It magically transformed into nice "GAME OVER" message on stderr :).

svn path=/trunk/KDE/kdegames/klines/; revision=616700
parent 1bd1eb33
......@@ -38,6 +38,7 @@
#include "prefs.h"
#include "linesboard.h"
#include "mwidget.h"
#include "scene.h"
#include "prompt.h"
enum { Nb_Levels = 5 };
......@@ -56,6 +57,9 @@ KLines::KLines()
mwidget = new MainWidget(this);
setCentralWidget( mwidget );
connect(mwidget->scene(), SIGNAL(scoreChanged(int)), SLOT(updateScore(int)));
connect(mwidget->scene(), SIGNAL(gameOver(int)), SLOT(gameOver(int)));
lsb = mwidget->GetLsb();
connect(lsb, SIGNAL(endTurn()), this, SLOT(makeTurn()));
connect(lsb, SIGNAL(eraseLine(int)), this, SLOT(addScore(int)));
......@@ -147,6 +151,19 @@ void KLines::initKAction()
setupGUI( Save | Keys | StatusBar | Create );
}
void KLines::updateScore(int score)
{
statusBar()->changeItem(i18n("Score: %1", score), 1);
}
void KLines::gameOver(int score)
{
KScoreDialog d(KScoreDialog::Name | KScoreDialog::Score, this);
KScoreDialog::FieldInfo scoreInfo;
if (d.addScore(score, scoreInfo, true))
d.exec();
}
void KLines::startGame()
{
score = 0;
......@@ -169,7 +186,7 @@ void KLines::startGame()
generateRandomBalls();
undoAction->setEnabled(false);
endTurnAction->setEnabled(true);
updateStat();
updateStatusBar();
}
void KLines::setLevel(int level) {
......@@ -413,7 +430,7 @@ void KLines::slotDemo()
}
}
updateStat();
updateStatusBar();
demoTimer->setSingleShot(true);
demoTimer->start(1000);
return;
......@@ -492,7 +509,7 @@ void KLines::undo()
nextBalls[i] = nextBalls_undo[i];
}
score = score_undo;
updateStat();
updateStatusBar();
lPrompt->SetBalls(nextBalls);
lsb->undo();
switchUndo(false);
......@@ -533,7 +550,7 @@ void KLines::addScore(int ballsErased)
{ if(ballsErased >= 5){
score += 2*ballsErased*ballsErased - 20*ballsErased + 60 ;
if( !lPrompt->getState() ) score+= 1;
updateStat();
updateStatusBar();
};
if (bDemo)
{
......@@ -547,7 +564,7 @@ void KLines::addScore(int ballsErased)
}
}
void KLines::updateStat()
void KLines::updateStatusBar()
{
statusBar()->changeItem(i18n(" Score: %1", score), 1);
}
......
......@@ -27,6 +27,7 @@ class LinesBoard;
class LinesPrompt;
class MainWidget;
// FIXME dimsuz: rename to KLinesMainWindow
class KLines : public KMainWindow
{
Q_OBJECT
......@@ -54,9 +55,10 @@ public slots:
void switchNumbered();
void undo();
void slotDemo();
private slots:
void viewHighScore();
void updateScore(int score);
void gameOver(int score);
private:
LinesBoard* lsb;
......@@ -86,7 +88,7 @@ private:
void searchBallsLine();
void generateRandomBalls();
void placeBalls();
void updateStat();
void updateStatusBar();
void switchUndo( bool bu );
void stopDemo();
};
......
......@@ -36,8 +36,8 @@ MainWidget::MainWidget( QWidget* parent )
lsb = new LinesBoard(bPainter, this);
// grid->addWidget( lsb );
lsb->hide();
KLinesScene* klscene = new KLinesScene(this);
KLinesView* klview = new KLinesView( klscene, this );
m_scene = new KLinesScene(this);
KLinesView* klview = new KLinesView( m_scene, this );
klview->setCacheMode( QGraphicsView::CacheBackground );
grid->addWidget( klview );
......
......@@ -24,18 +24,24 @@ class BallPainter;
class LinesBoard;
class LinesPrompt;
class KLinesScene;
class MainWidget : public QFrame
{
LinesBoard * lsb;
LinesPrompt * lPrompt;
BallPainter *bPainter;
public:
MainWidget( QWidget* parent=0 );
~MainWidget();
LinesBoard * GetLsb();
LinesPrompt * GetPrompt();
void updatePix();
KLinesScene* scene() { return m_scene; }
private:
LinesBoard * lsb;
LinesPrompt * lPrompt;
BallPainter *bPainter;
KLinesScene* m_scene;
};
#endif
......@@ -44,7 +44,7 @@ void KLinesView::resizeEvent( QResizeEvent* ev )
// =============== KLinesScene =======================
KLinesScene::KLinesScene( QObject* parent )
: QGraphicsScene(parent), m_numBalls(0)
: QGraphicsScene(parent), m_numFreeCells(FIELD_SIZE*FIELD_SIZE), m_score(0), m_gameOver(false)
{
m_renderer = new KLinesRenderer;
m_animator = new KLinesAnimator(this);
......@@ -74,15 +74,25 @@ void KLinesScene::resizeScene(int width,int height)
void KLinesScene::nextThreeBalls()
{
QList<BallItem*> newItems;
newItems.append( placeRandomBall() );
newItems.append( placeRandomBall() );
newItems.append( placeRandomBall() );
BallItem* newBall;
for(int i=0; i<3; i++)
{
newBall = placeRandomBall();
if( newBall )
newItems.append(newBall);
else
break; // the field is filled :).
}
m_animator->animateBorn( newItems );
}
BallItem* KLinesScene::placeRandomBall()
{
m_numFreeCells--;
if(m_numFreeCells < 0)
return 0; // game over, we won't create more balls
// FIXME dimsuz: in old klines ball positon had score and levels of
// difficulty were implemented around it. Check this out and consider implementing
// as current pos finding isn't very good - theorectically it can search forever :).
......@@ -102,7 +112,6 @@ BallItem* KLinesScene::placeRandomBall()
newBall->setColor(c);
newBall->setPos( fieldToPix( FieldPos(posx,posy) ) );
m_field[posx][posy] = newBall;
m_numBalls++;
return newBall;
}
......@@ -147,8 +156,7 @@ void KLinesScene::moveAnimFinished()
m_selPos.x = m_selPos.y = -1; // invalidate position
kDebug() << "calling sae1" << endl;
m_placeBallsAfterErase = true;
m_placeBalls = true;
// after anim finished, slot removeAnimFinished()
// will be called
searchAndErase();
......@@ -156,7 +164,14 @@ void KLinesScene::moveAnimFinished()
void KLinesScene::removeAnimFinished()
{
if(m_itemsToDelete.isEmpty() && m_placeBallsAfterErase)
if( m_itemsToDelete.isEmpty() && m_numFreeCells == 0 )
{
kDebug() << "GAME OVER" << endl;
emit gameOver(m_score);
return;
}
if(m_itemsToDelete.isEmpty() && m_placeBalls)
{
// slot bornAnimFinished() will be called
// when born animation finishes
......@@ -164,29 +179,50 @@ void KLinesScene::removeAnimFinished()
}
else
{
// expression taked from previous code in klines.cpp
int numBallsErased = m_itemsToDelete.count();
if(numBallsErased)
m_score += 2*numBallsErased*numBallsErased - 20*numBallsErased + 60 ;
qDeleteAll( m_itemsToDelete );
m_itemsToDelete.clear();
// it is needed after qDeleteAll()
// as an optimisation we may update only rects
// in which items from m_itemsToDelete were before
// deletion
update();
emit scoreChanged(m_score);
}
}
void KLinesScene::bornAnimFinished()
{
// note that if m_numFreeCells == 0, we still need to
// check for possible 5-in-a-row balls, i.e. call searchAndErase()
// So there's another gameOver()-check in removeAnimFinished()
if( m_numFreeCells < 0 )
{
kDebug() << "GAME OVER" << endl;
emit gameOver(m_score);
return;
}
// There's a little trick here:
// searchAndErase() will cause m_animator to emit removeFinished()
// If there wasn't m_placeBallsAfterErase var
// If there wasn't m_placeBalls var
// it would cause an infinite loop like this:
// SaE()->removeAnimFinished()->next3Balls()->bornAnimFinished()->
// SaE()->removeAnimFinished()->next3Balls()->...
// etc etc
m_placeBallsAfterErase = false;
m_placeBalls = false;
// after placing new balls new 5-in-a-row chunks can occur
// so we need to check for them
kDebug() << "calling sae2" << endl;
//
// And because of that we check for gameOver in removeAnimFinished()
// rather than here - there's a chance that searchAndErase() will remove
// balls making some free cells to play in
searchAndErase();
}
......@@ -212,6 +248,7 @@ void KLinesScene::searchAndErase()
{
m_itemsToDelete.append(m_field[i][y]);
m_field[i][y] = 0;
m_numFreeCells++;
}
}
else
......@@ -236,6 +273,7 @@ void KLinesScene::searchAndErase()
{
m_itemsToDelete.append(m_field[x][j]);
m_field[x][j] = 0;
m_numFreeCells++;
}
}
else
......@@ -265,6 +303,7 @@ void KLinesScene::searchAndErase()
{
m_itemsToDelete.append(m_field[i][j]);
m_field[i][j] = 0;
m_numFreeCells++;
}
}
else
......@@ -294,6 +333,7 @@ void KLinesScene::searchAndErase()
{
m_itemsToDelete.append(m_field[i][j]);
m_field[i][j] = 0;
m_numFreeCells++;
}
}
else
......
......@@ -77,7 +77,9 @@ public:
*/
inline FieldPos pixToField( const QPointF& p ) const {
return FieldPos(static_cast<int>(p.x()/32), static_cast<int>(p.y()/32)); }
signals:
void scoreChanged(int);
void gameOver(int);
private slots:
void moveAnimFinished();
void removeAnimFinished();
......@@ -120,14 +122,22 @@ private:
*/
FieldPos m_selPos;
/**
* Number of balls currently in field
* Number of free cells in the field
*/
int m_numFreeCells;
/**
* Current game score
*/
int m_numBalls;
int m_score;
/**
* Varable which is needed for little trick (tm).
* Read more about it in removeAnimFinished() slot
*/
bool m_placeBallsAfterErase;
bool m_placeBalls;
/**
* Indicates game is over
*/
bool m_gameOver;
/**
* Items pending for removal after remove-anim finishes
*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment