Tetris is a very simple, but elegant game. Blocks of four bricks each are falling down in a play field, and the player can rotate and move the block sideways. When the block hits ground or another block below, it stays there. If one line of bricks is full, then that line is removed. As the game is running, the falling speed increases. The goal of the game is to keep playing as long as possible, which is getting really hard as the speed increases. I have implemented Tetris for the virtual game system.
Due to the complexity of the game, there was no RAM left for sound, would probably have been possible to add sound if the game would have been written in assemler, but that would have been much more work and not the reason why I made this game. This was the second game I wrote for the system.
Most of the code is written in C and compiled with Hi-tech PIC-C. It is the best c-compiler available for the PIC, but it comes with a primitive DOS IDE. However, it is possible to integrate the compiler with MPLAB and then you'll have an extremely powerful easy-to-use development environment. It is this combination that I've used developing the virtual tetris game, and it is what I recommend you to use when developing complex programs for PIC. It is amazing to see how tight code it produces.
The code is built as a state machine with states "init screen", "playscreen" and "game over screen". In both init and gameover the message is scrolled until fire. The game state is the most complicated, a lot of memory saving optimizations was needed because the RAM and ROM is very limited. The game-field is kept in memory as a 19byte array. One byte is one line on the screen, where the first 4 lines are shown at the top left of the screen and the rest of the lines are shown in the middle (the playable area of the game field). The area to the upper left is for showing the next block, and by making it a part of the game field it is possible to use the same block-drawing routines as for the game, and thereby saving memory. Each frame, the falling block is first removed from the game-field, and then tests are performed if the block can move, as the player wants it to. Then the block is drawn back to the screen at the new position. When a block is to be tested, put or removed, it first must be generated. To generate a block means compressing it from the compressed data, rotating it, and then store the relative coordinates of the block in the block array. The block data is compressed in relative coordinates. In compressed format, each coordinate is stored in two bits for both x and y, where the two bits can represent the numbers –1,0,1,2. These values need to be uncompressed to 4*2 byte sized values representing the coordinates in two’s complement format. Depending of the angle the block should have, the coordinates might need to be mirrored or/and swapped. When the block have been created it can easily be put, removed or tested. The test routine checks if there is any pixels set on the block positions where the block should be put. If pixels are set, then the block can’t be put there. The test bit routine returns a bit is set if the bit is outside the game-field, this prevents the blocks from moving outside the game-field. When sending the game info to the graphics card, the Load command is used, this is column oriented, while the game-field is line oriented, so the bytes have to be "rotated". It is also during this load that the borders around the game-field are created, by sending 0xFF on those columns. Using the putchar command, the score is shown. New blocks are selected at random, where the random number is a counter that increases for every frame, making the random number dependent of how long it takes for the player to place the block, making a quite good random number.
The speed of the game is increasing constantly, this is achieved by using the upper digit of the score when calculating the falling delay.
Unfortunately there was not enough ram left to add a music interrupt routine.
How to play
This game is only using joystick 1. When turning on the game, a greeting message is scrolled showing "Virtual Tetris © Rickard Gunee" until fire is pressed. Then the game starts. The game screen shows the game-field in the middle, the score is shown at the right of the screen, and the next block kind is shown at the left top of the screen.
By moving the joystick left and right the falling block is moved left and right. Pressing fire rotates the block. The falling process can be made faster by moving the joystick down. When a line is full, the line is removed and the points increase by one. For every ten removed lines, the speed increases. When there is no more room for blocks in the gamefield, the game is over and a game over message is shown.
Source-code and hex-files are available in mtetris.zip(15k)
More mechanically scanned stuff
If you want to know more about mechanically scanned stuff, check out some of these links:
Virtual Tetris (C) Rickard Gunee. This is open source, use this at your own risk ! You may use the information on this page for your own projects as long as you refer to the original author (by name and link to authors homepage), don't do it for profit and don't hurt or harm anyone or anything with it. The author can not be held responsible for any damage caused by the information on this and related pages.