This assignment is a 2 part project designed to test your overall understanding of the concepts covered in the course, including object-oriented design, graphical user interfaces, events, and animation.
For this project, you will write a set of classes to play a graphical game of Tetris. Tetris is a game in which the player moves and rotates dropping pieces so that they form solid lines. Completely filled lines are cleared, giving points to the player. The Wikipedia page for Tetris is a very good source of information about the various incarnations of the game.
There are seven pieces in standard Tetris, typically referred to by letter (picture from Wikipedia):
Our abstraction will be that a MovableTetrisPiece object represents a single Tetris piece with position and rotation state.
A piece can be rotated 90° clockwise. Enough rotations get you back to the original orientation. Each Tetris piece has one (the O), or four (the L, J, T, I, S and Z) distinct rotational states as shown on the next page. At the top of the diagram notice the increasing series of numbers 0 – 3 which represent the various rotational states.
New pieces are initialized to the 0 state. Clockwise rotations increment the rotational state.
Rotation: 0 1 2 3
Figure 2
A piece is represented by the coordinates of its blocks, which we can refer to as the “body” of the piece. Each piece has its own coordinate system with its (0, 0) origin in the lower left of the rectangle that encloses the body as shown in figure 2. The coordinates of blocks in the body are relative to the origin of the piece. So, the four blocks of the O piece are:
(1,1) – the lower left-hand block (1,2) – the upper left-hand block (2,1) – the lower right-hand block (2,2) – the upper right-hand block
Here is another example: Rotation 2 of the S piece, with the axes drawn explicitly:
[(0,0), (1,0), (1,1), (2,1)]
Note that not all pieces will actually have a block at (0, 0). For example, the next rotation of the S has the following body:
[(0,1), (0,2), (1,0), (1,1)]
The provided Tetris model is a set of classes to represent all game pieces and the game board.
If you choose to make anychanges and/or additions to these classes, then the following requirements apply:
1) Add a non-javadoc (implementation) comment to the code wherever you make changes. These comments must explain the purpose of everychange that you make to the provided code.
2) Provide complete javadoc comments for everynew interface, class, field, constant, or method which you add to the provided code.
3) Additionally, LIST and briefly describe everychange and/or addition you have made to the provided code in your executive summary. (Provide a numbered list of changes in your summary.)
NOTE: You will NOT need to make any changes to the model code to implement a fully functional Tetris game. You should certainly NOT need to make any changes for part A. However, for some types of part B extra credit it is possible that you may need to make changes and/or additions to the model code.
NOTE: The piece classes and the Board class serve a specific function. The abstractions they define are the geometry of the game. You should NOT add code to these classes which represents some other abstraction, such as the information tracked by the current game for scoring purposes (the score, the level, the total number of lines cleared in a game, etc.). Information needed by the game which is not related to the geometry of the game should be stored and manipulated elsewhere. The model code (pieces and Board) should not contain ANY code to implement GUI features, such as colors, graphics, or sound.
NOTE: No new classes should be added to the model package or to the ‘default’ package. All of your GUI classes should be in the view package, or in other named packages. DO NOT change ‘private’ or ‘protected’ access modifiers of fields or methods in the model code to ‘public’ to make them visible in other packages. The model code already exposes an adequate API upon which you can build a graphical front end.
A piece keeps track of its position on the Board and rotational state. A piece has methods to move in various directions (left, right, down, rotate).
A piece has a local coordinate system, as described above; rotating the piece means changing the locations of its 4 blocks in the local coordinate system, and moving a piece means changing its position on the board in the board’s coordinate system. A piece does not make any assumptions about the board it will be placed on. In particular, it does not assume any particular board position is valid or invalid, because it is the board’s job to determine whether a piece is in a legal position. A piece is printable via a toString method, which generates a 2D text drawing which clearly depicts the rotational state of the piece. This is useful for testing.
The project includes a class called Board which is a representation of a Tetris game board. The board is essentially a grid of squares that may be filled with previously dropped pieces (and remnants thereof). The standard Tetris board is 10 squares wide and 20 squares tall, but can be initialized with arbitrary dimensions.
The Board class contains the following data and functionality:
· A representation of all filled squares.
· A current piece-in-progress, which conceptually starts above the middle of the board; this means that the piece does not occupy any of the squares on the board when in its starting position. (The piece should not be visible in the GUI when it is first instantiated.)
· Methods to move the current piece left, right, and down and to rotate the current piece while doing collision detection – that is, if the method to move the current piece left is called, and the current piece cannot move left (because that would cause it to collide with a previously frozen piece, or move off the board), the current piece does not move. Rotations near walls will cause the piece to offset enough to allow the rotation when necessary (wall kicks).
· The ability to provide a specific sequence of pieces to use – by default the Board uses randomly generated pieces (see below).
· The down() method updates the game state by one step. Calling down() causes the current piece-in- progress to move down by one row, and may cause additional changes to the board as follows:
o when the piece-in-progress is resting on top of existing filled squares or reaches the bottom row of the Board and attempts to move down one more time, it freezes and its blocks become part of the board’s grid of filled squares
o when the piece-in-progress freezes, if any lines are completely filled, they are cleared from the board; all squares above a filled line drop downward by one line (note that up to 4 lines may be cleared at a time)
o when the piece-in-progress freezes, a new piece-in-progress is chosen either randomly or from a predetermined sequence of pieces.
There are multiple reasons for the ability to specify whether the board uses random pieces or a specific piece sequence. The ability to specify a sequence of pieces is helpful for testing; it allows you to drop pieces in a specific order, onto the board to see that they give correct board layouts as they drop. The ability to specify a sequence of pieces can also be useful for gameplay features because it gives you the ability to “replay” games, or to always use the same sequence of pieces (as in tournament play). Clearly, the ability to randomly generate pieces is important in standard gameplay, as it makes the game unpredictable for players.
The game is advanced externally, by using a timer to call the down() method.
The Board class fires PropertyChangeEvents, so that the GUI you write will be notified of changes that occur on the game board. The Board notifies of changes whenever a piece moves, rotates, or lines are cleared (and does not notify when a piece attempts to move left or right, or rotate, but does not change position because of bounds checking).
The first version of your code is an initial graphical user interface (GUI) for the Tetris game. The GUI must contain the following:
· a graphical representation of a 10 x 20 Tetris game board, showing its filled squares and its piece-in- progress
· a graphical display of the “next” piece that will come after the current piece-in-progress. This piece preview must show the “next” piece in the same rotational state in which it will appear on the board.
· the ability for the user to move the piece in progress left, right, rotate it clockwise, move it down 1 line, and instantly drop the piece downward to the bottom using keyboard keys. You must encode the following default key controls:
Move Left left arrow and ‘a’ (both must work) Move Right right arrow and ‘d’ (both must work) Rotate up arrow and ‘w’ (both must work) Move Down down arrow and ‘s’ (both must work) Drop space
· an animation timer that makes the game board update once per second, causing the current piece to fall
· some message or indication that the game is over, displayed when the game ends (that is, when frozen pieces extend above the top of the board)
· the GUI MUST implement PropertyChangeListener to complete the pattern for communication between the GUI and the board. Neither your Timer nor your KeyListener should call repaint(). Instead, they should call methods of the Board class, which will, in turn, notify the GUI after updating the model.