|
|
The Making of WarpTris - Part 1Written by Paulo Gago da Camara |
IntroductionThis article is about the concept and design of WarpTris, a small game I developed last summer in order to learn Presentation Manager programming. I assume here that you have working knowledge of the C++ programming language and basic knowledge of the OS/2 PM. WarpTris was developed under Visual Age C++ 3.0 for OS/2. I don't know if it will compile on GCC+EMX or any other C++ compiler. Remember that WarpTris was my first PM program so there might be (and there are) some parts of it that could be done in a more effective way. Nevertheless I hope that this text might be of some help on understanding the WarpTris source code and, who knows, it might even help someone that, just like myself, is learning PM programming. It is recommended that you download the WarpTris source code in order to best understand each part of it that will be described here. You can download it and the compiled game at my Web Page. The URL is as follows: http://www.geocities.com/SiliconValley/Heights/1856 About the GameThe original idea for the game belongs to my former C/C++ teacher, Dr. Ghunter Funk, who proposed the game as an assignment in C++. When I first developed WarpTris (the initial name was 4Tris), I did it with a colleague and it was programmed in Borland C++ 3.0 for DOS. The original program was in text mode (50 lines) and it wasn't very attractive to the eye. Still, we got a nice grade with it. Later, during Summer holidays, I bought the OS/2 Warp Programming for Dummies book and started learning PM. When I finished reading the book I needed to put to practice all the things I thought I had learned. That was when my friend Jorge Martins (an OS/2 user and developer since version 1.0), gave me the idea of developing 4Tris for OS/2, and then WarpTris was born. WarpTris isn't a port from the original version for DOS although some code from the game engine was reused (mainly some methods of the 'Board' class and the 'Figure' class). Many parts were modified and most of them were rewritten from scratch. WarpTris differs from normal Tetris by the fact that the game figures appear at the middle of the game window and then start falling towards one of the four sides randomly. This way you can make lines on all four sides of the game window. When one figure is falling towards one side, you can only move that figure parallelly to that side. If some part of a figure covers any square of the gray area at the middle, the game ends. There are also three levels of difficulty. The difference between them is the 'impulse' that each figure receives at start, and the score given by each piece. The WarpTris user interface consists of a main parent window and four child windows: the Game, Score, High Scores and Next windows. Initially WarpTris had only a window where the game was played, but then I had to change the design to what it is now. The sounds that are played during the game are on a separate thread of execution using an object window to avoid slowing down the figure movements. Since my knowledge of the multimedia API is very restricted I opted to use the MCI command string interface which is quite simple but has its limitations. I plan to include a background MIDI music and more sounds, but first I have to read more about the OS/2 multimedia subsystem. WarpTris Source Code Files DescriptionThe WarpTris source code contains the following files:
The Game EngineThe WarpTris game engine is mainly composed of two classes: Board and Figure. As stated earlier, these classes and their methods are defined on the Board.h and Figure.h header files. The Board ClassThe grid where we play the game is represented by this class. The data structure I used to represent it is the matrix of integers named 'board'. Each element of this matrix can have a value of 0 (if empty) or the resource ID of the square bitmap that is to be drawn there (if occupied). There is also a private member called 'hwndClient' which is the handle of the game window client area. This is used to pass to the functions that actually draw or clear a square on that window (These functions are declared and defined on the WarpTris.cpp file). Private members:
Constructor:
Public methods:
class Board
{
private:
INT board[COLUMNS][LINES]; // The logical board
HWND hwndClient; // Handle of the game client window
VOID EraseLine(INT line); // Removes a line
VOID EraseColumn(INT column); // Removes a Column
// Returns the limit of a given side of a piece
INT Limit(DIR side, INT definition[5][5]);
// Draws a square on the board
VOID DrawSquare(INT x, INT y);
// Searches one side of the board for full lines
INT SingleEvaluate(DIR side);
public:
// Constructor
Board(HWND hwnd);
// Draws a given area of the board, for performance reasons
VOID DrawArea(DIR side);
// Searches the board for full lines on a way that depends
// on the side the piece is falling to, it returns the number
// of lines removed.
INT Evaluate(DIR side);
// Puts a figure on the board (logical)
// Returns TRUE if possible on (x,y)
BOOL PutFigure(INT x, INT y, INT definition[5][5]);
// Removes a figure from the board
VOID RemoveFigure(INT x, INT y, INT definition[5][5]);
// Is the game over ?
BOOL Finished();
};
4.2 The Figure classThis class is used to logically represent the figure being played. It's also used to represent the next figure that will appear. During the game there are always two objects of this class. One for the currently playing figure and one for the next figure. The overloaded operator '=' is used to assign the figure displayed in the Next window to the new playing figure. Private members:
Constructor:
Public methods:
class Figure
{
private:
// The current position of the figure in squares coordinates
INT posX, posY;
// The logical representation of the figure
INT definition[MAX_FIGURE_X][MAX_FIGURE_Y];
// Which bitmap used to draw the figure
INT bitmapID;
// Is it a pair figure (to do with the rotation of the figure)
BOOL pairFigure;
// Handle of the game client window
HWND hwndClient;
public:
// Constructor
Figure(HWND hwnd,
INT bitmap,
INT def[MAX_FIGURE_X][MAX_FIGURE_Y],
INT px=0,
INT py=0,
BOOL animated=TRUE,
BOOL draw=TRUE);
// Rotate the figure on the board (if possible)
VOID Rotate(Board &board);
// Erase last figure from the game window
VOID ClearLastFigure(INT x=0, INT y=0);
// Draw the figure
VOID Draw(INT x=0, INT y=0);
// Draw the figure on the next window
VOID DrawNext(INT x=0, INT y=0);
// Move it on a given direction (if possible)
INT Move(DIR d, Board &board);
// Let it fall to a given side
VOID Fall(DIR d, Board &board);
// To assign a figure to another (to do with the Next figure)
VOID operator=(Figure &figure);
// Get method of the private var, bitmapID
INT GetBitmapID() {return(bitmapID);}
};
The game engine, as we saw, is mainly composed of these two classes. Next
we will take a look inside the WarpTris Presentation Manager code.
ConclusionNext month I will deal with the PM portion of the game. Until next month! |