|
|
|
/****************************************************************************
|
|
|
|
**
|
|
|
|
** Definition of GenericTetris, a generic class for implementing Tetris.
|
|
|
|
**
|
|
|
|
** Author : Eirik Eng
|
|
|
|
** Created : 940126
|
|
|
|
** Modified by Nicolas Hadacek
|
|
|
|
**
|
|
|
|
** Copyright (C) 1994 by Eirik Eng. All rights reserved.
|
|
|
|
**
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
**
|
|
|
|
** The GenericTetris class is an abstract class that can be used to implement
|
|
|
|
** the well known game of Tetris. It is totally independent of any hardware
|
|
|
|
** platform or user interface mechanism. It has no notion of time, so you
|
|
|
|
** have to supply the timer ticks (or heartbeat) of the game. Apart from
|
|
|
|
** that this is a complete Tetris implementation.
|
|
|
|
**
|
|
|
|
** In the following it is assumed that the reader is familiar with the game
|
|
|
|
** of Tetris.
|
|
|
|
**
|
|
|
|
** The class operates on a grid of squares (referred to as the "board" below),
|
|
|
|
** where each of the different types of pieces in Tetris covers 4 squares. The
|
|
|
|
** width and height of the board can be specified in the constructor (default
|
|
|
|
** is 10x22). The coordinate (0,0) is at the TOP LEFT corner. The class
|
|
|
|
** assumes that it has total control over the board and uses this to optimize
|
|
|
|
** drawing of the board. If you need to update parts of the board
|
|
|
|
** (e.g. if you are using a window system), use the updateBoard() function.
|
|
|
|
**
|
|
|
|
** An implementation of the game must subclass from TetrisBoard and must
|
|
|
|
** implement these abstract functions:
|
|
|
|
**
|
|
|
|
** virtual void drawSquare(int x,int y,int value)
|
|
|
|
**
|
|
|
|
** This function is called when a square needs to be drawn
|
|
|
|
** on the Tetris board. A value of 0 means that the square
|
|
|
|
** should be erased. Values of 1 to 7 indicate the different
|
|
|
|
** types of pieces. (Thus a minimal implementation can
|
|
|
|
** draw 0 in one way and 1-7 in a second way). The x and y
|
|
|
|
** values are coordinates on the Tetris board (see above).
|
|
|
|
**
|
|
|
|
** virtual void gameOver()
|
|
|
|
**
|
|
|
|
** This function is called when it is impossible to put a new
|
|
|
|
** piece at the top of the board.
|
|
|
|
**
|
|
|
|
** To get a working minimal implementation of Tetris the following functions
|
|
|
|
** must be called from the user interface:
|
|
|
|
**
|
|
|
|
** void startGame()
|
|
|
|
**
|
|
|
|
** Clears the board and starts a new game.
|
|
|
|
**
|
|
|
|
** void moveLeft()
|
|
|
|
** void moveRight()
|
|
|
|
** void rotateLeft()
|
|
|
|
** void rotateRight()
|
|
|
|
**
|
|
|
|
** The standard Tetris controls for moving and rotating the
|
|
|
|
** falling pieces.
|
|
|
|
**
|
|
|
|
** void dropDown();
|
|
|
|
**
|
|
|
|
** Another Tetris control, drops the falling piece and calls the
|
|
|
|
** virtual function pieceDropped(), whose default implementation is
|
|
|
|
** to create a new block which appears at the top of the board.
|
|
|
|
**
|
|
|
|
** void oneLineDown();
|
|
|
|
**
|
|
|
|
** This is where you supply the timer ticks, or heartbeat, of the
|
|
|
|
** game. This function moves the current falling piece one line down
|
|
|
|
** on the board, or, if that cannot be done, calls the virtual
|
|
|
|
** function pieceDropped() (see dropDown() above). The time between
|
|
|
|
** each call to this function directly affects the difficulty of the
|
|
|
|
** game. If you want to pause the game, simply block calls to the
|
|
|
|
** user control functions above and stop calling this function (you
|
|
|
|
** might want to call hideBoard() also).
|
|
|
|
**
|
|
|
|
** And that's it! There are several other public functions you can call
|
|
|
|
** and virtual functions you can overload to modify or extend the game.
|
|
|
|
**
|
|
|
|
** Do whatever you want with this code (i.e. the files gtetris.h,
|
|
|
|
** gtetris.cpp, tpiece.h and tpiece.cpp). It is basically a weekend hack
|
|
|
|
** and it would bring joy to my heart if anyone in any way would find
|
|
|
|
** it useful.
|
|
|
|
**
|
|
|
|
** Nostalgia, comments and/or praise can be sent to: Eirik.Eng@troll.no
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#ifndef GTETRIS_H
|
|
|
|
#define GTETRIS_H
|
|
|
|
|
|
|
|
#include <tqpoint.h>
|
|
|
|
|
|
|
|
#include <krandomsequence.h>
|
|
|
|
#include <kgrid2d.h>
|
|
|
|
|
|
|
|
#include <kdemacros.h>
|
|
|
|
|
|
|
|
class Piece;
|
|
|
|
class BlockInfo;
|
|
|
|
class Block;
|
|
|
|
|
|
|
|
struct GTInitData {
|
|
|
|
int seed;
|
|
|
|
uint initLevel;
|
|
|
|
};
|
|
|
|
|
|
|
|
class KDE_EXPORT GenericTetris
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
GenericTetris(uint width, uint height, bool withPieces, bool graphic);
|
|
|
|
virtual ~GenericTetris();
|
|
|
|
virtual void copy(const GenericTetris &);
|
|
|
|
|
|
|
|
void setBlockInfo(BlockInfo *main, BlockInfo *next);
|
|
|
|
virtual void start(const GTInitData &);
|
|
|
|
|
|
|
|
uint moveLeft(int steps = 1) { return moveTo(KGrid2D::Coord(-steps, 0)); }
|
|
|
|
uint moveRight(int steps = 1) { return moveTo(KGrid2D::Coord(steps, 0)); }
|
|
|
|
bool rotateLeft() { return rotate(true); }
|
|
|
|
bool rotateRight() { return rotate(false); }
|
|
|
|
virtual void oneLineDown();
|
|
|
|
virtual void dropDown();
|
|
|
|
|
|
|
|
KRandomSequence &randomSequence() { return _random; }
|
|
|
|
uint score() const { return _score; }
|
|
|
|
uint level() const { return _level; }
|
|
|
|
uint nbClearLines() const { return _nbClearLines; }
|
|
|
|
uint nbRemoved() const { return _nbRemoved; }
|
|
|
|
bool graphic() const { return _graphic; }
|
|
|
|
uint firstClearLine() const { return _matrix.height() - _nbClearLines; }
|
|
|
|
const KGrid2D::Coord ¤tPos() const { return _currentPos; }
|
|
|
|
const Piece *nextPiece() const { return _nextPiece; }
|
|
|
|
const Piece *currentPiece() const { return _currentPiece; }
|
|
|
|
const KGrid2D::Square<Block *> &matrix() const { return _matrix; }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
Piece *_nextPiece, *_currentPiece;
|
|
|
|
|
|
|
|
virtual void pieceDropped(uint /*dropHeight*/) {}
|
|
|
|
virtual bool newPiece(); // return false if cannot place new piece
|
|
|
|
virtual void gluePiece();
|
|
|
|
virtual void computeInfos();
|
|
|
|
|
|
|
|
virtual void updateRemoved(uint newNbRemoved) { _nbRemoved = newNbRemoved;}
|
|
|
|
virtual void updateScore(uint newScore) { _score = newScore; }
|
|
|
|
virtual void updateLevel(uint newLevel) { _level = newLevel; }
|
|
|
|
|
|
|
|
void setBlock(const KGrid2D::Coord &, Block *);
|
|
|
|
virtual void removeBlock(const KGrid2D::Coord &);
|
|
|
|
void moveBlock(const KGrid2D::Coord &src, const KGrid2D::Coord &dest);
|
|
|
|
|
|
|
|
virtual void updateNextPiece() {}
|
|
|
|
virtual void updatePieceConfig() {}
|
|
|
|
void bumpCurrentPiece(int dec);
|
|
|
|
void partialMoveBlock(const KGrid2D::Coord &, const TQPoint &dec);
|
|
|
|
|
|
|
|
private:
|
|
|
|
TQPoint toPoint(const KGrid2D::Coord &) const;
|
|
|
|
uint moveTo(const KGrid2D::Coord &dec);
|
|
|
|
bool rotate(bool left);
|
|
|
|
void clear();
|
|
|
|
bool canPosition(const KGrid2D::Coord &newPos, const Piece *newPiece) const;
|
|
|
|
|
|
|
|
GenericTetris(const GenericTetris &); // disabled
|
|
|
|
|
|
|
|
uint _score, _level, _nbRemoved;
|
|
|
|
uint _nbClearLines, _initLevel;
|
|
|
|
KGrid2D::Coord _currentPos;
|
|
|
|
BlockInfo *_main;
|
|
|
|
bool _graphic;
|
|
|
|
KGrid2D::Square<Block *> _matrix;
|
|
|
|
KRandomSequence _random;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|