This project is an incarnation of Tetris using Java. This was my final project for AP Computer Science in my junior year of high school, and I worked with one other student. The game features pentominoes as well as tetrominoes for added diversity. The original creator of Tetris decided to use tetrominoes instead of pentominoes because he thought pentominoes would make the game too complicated. I wanted to test this theory. It turns out he was right; the game is much more difficult and complex with pentominoes. We used Eclipse IDE to write the code and Github to collaborate. Github page Our project was much more advanced than most of the others in the APCS class, and the only project to include comprehensive graphics. We were also the only group to use github.
Current Features and Bugs
The game has standard implementation of most tetris functions. Blocks appear at the top, can be moved laterally and spun, and land in a location. Currently, blocks stop moving the instant they hit the bottom, instead of stopping moving the game cycle after. This is a bug and will hopefully be fixed. The game features tetrominoes and pentominoes with three game modes. Mode 1 is both block types, mode 2 is only tetrominoes, and mode 3 is only pentominoes. Lines clear and score is kept based on how many lines are cleared at a time and what the current level is. Real Tetris has a much more complicated scoring system, which I think is just rediculous because the vast majority of points come from clearing lines. The number of lines cleared, points, current level, and the next block are all shown in boxes on the right. The game gets faster with higher levels, with similar intervals to real tetris, starting at 1 second and decreasing by 0.1 seconds for each level until level 10 (after level 10 it decreases by 0.01 seconds, then stays the same after level 20) The game did not include the I tetromino originally. This is because blocks that do not have a center are very difficult to spin correctly. For blocks with a center, the spin can be referenced to the middle square, but this can't occur for I blocks. I later implemented a solution, where the block does not actually "spin," it just flips between two states. The same was done to implement I pentiminoes. Sound is present: The tetris A theme and a game over sound effect are played.
The GUI uses the Java Swing library to create the window (JFrame) and graphics. The Graphics2D class of Java Swing is used to draw the game's 2D graphics. The KeyListener interface was used for keyboard input. The SoundClip libarary is used to play the sound effects. The Timer API was used to time the game loop. ArrayLists and Colors are also used.
This project has (at the time of this being written) 29 classes. Each block type has its own class, so 19 of the classes store info for the 19 current block types and do nothing else. (mainly copy/pastes of each other with small differences) For the other 10, there is one interface and 9 classes that perform functions in the game.
- Window - extends the JFrame class of Java Swing; creates the game window; contains the main method
- BlockSquare - contains info for each individual square on the field including color, name, and if it is an axis of rotation
- Block - interface that all the block classes inherit
- Block[type] - implments Block interface; contains the position of BlockSquares in the Block
- PlayingField - contains a 2D array of BlockSquares that stores the position of each BlockSquare in the playing field; has methods that manipulate this array including makeBlockAppear and clearLines
- BlockManipulator - contains the Move and Spin methods (most difficult part of the project)
- KeyboardListener - implements the KeyListener interface; has methods that get called when keys are pressed to call other methods
- Sound - uses the SoundClip library to make sound clips
- PointCounter - keeps track of points and levels; has methods to input new points based on lines cleared
- GraphicsDrawer - uses the Graphics2D class to draw the graphics of the game and title screen
- Game - contains the game loop using the Timer API, which controls the overall gameplay and sequence; calls methods from many other classes to make the game run
Raspberry Pi/4H Fair
This project was later ported to a Raspberry Pi for use at the 2017 4H Fair. The purpose of this was to give the fairgoers the ability to play my version of tetris at the robotics tent. It also acted as my personal project for the Robostorm Robotics Club. (every member is required to do a personal proeject) I used a Raspberry Pi 3 model B for the job, since earlier versions ran the game much slower due to the resource intensiveness of Java Swing. Getting it to work on a pi was simple, since Java Swing is supported on Raspbery Pi. I edited my program to display in a full screen mode, fixed the position of the field and text boxes, and changed added a nicer menu selection on the title screen. I also fixed plenty of bugs along the way. I then made the pi start tetris on startup. I did this by creating a systemd routine and symlink.
I also created a gamepad for use at the fair, so a keyboard would not be necessary. I could have used a normal USB gamepad, but I wanted my project to be even more DIY. I made my own controller using a custom-built PCB and a 3D printed enclosure. I used the toner-transfer method to make the circuit board, which I designed in KiCAD. The PCB was simple; it only contained the six tact switches and holes for soldering the cable.
I designed a 3D printable case using Onshape, a free cloud-based CAD software similar to Autodesk. This was printed in PLA, but the buttons were printied in NinjaFlex, a flexible 3D printer filament. This makes the buttons soft and squishy, like buttons usually are on commercial gamepads .
The gamepad plugged into the GPIO (General Purpose Input/Output) pins on the Raspberry Pi. I used cat6 (ethernet) cable to connect the gamepad to the pi. I didn't bother crimping ends onto the cable, since I was afraid some idiot at the 4H Fair would plug it into the actual ethernet plug on the pi, which could damage the pi. I used the Adafruit RetroGame library to convert the GPIO signals into emulated keyboard input. I also 3D printed a case for the pi with a mounting holes, so the pi could be mounted to the back of the display.