Code Size
"ATmega328P" memory use summary [bytes]: Segment Begin End Code Data Used Size Use% --------------------------------------------------------------- [.cseg] 0x000000 0x0003fe 960 62 1022 32768 3.1% [.dseg] 0x000100 0x000600 0 459 459 2048 22.4% [.eseg] 0x000000 0x000000 0 0 0 1024 0.0% Assembly complete, 0 errors. 0 warnings
Playing The Game
Each player is represented by a red or blue tank positioned on a randomly generated terrain background. When it is your turn to fire, a white button will appear behind your tank. In addition, the aiming cursor (white cross hair) is displayed in the sky region. The relative position of the aiming cursor and firing point of your tank (top-center of the turret) is used to describe a vector of your projectile's initial velocity (remember this from physics class?)
The relative angle between the aiming cursor and turret describes the angle of fire. The distance between the two describes the amount of powder used to fire the shot. The further away from the turret, the larger the powder charge and the longer the projectile will fly. Touch the "sky" region of the screen to move the aiming cursor.
Once you are happy with where it is placed, press the white button (or your tank) to fire. The path of the projectile will be plotted in real time until it hits something or goes out of bounds. If you miss, the other player will be given a turn to fire on you. If you hit the other player, you are awarded a point and the terrain is regenerated. If you hit yourself, the other player is awarded your point.
Each player's score is displayed at the top of the screen as tally marks. Play continues until a player has scored 3 points, in which case he or she is the winner. A new game is immediately started.
Design Details
The code is broken into several modules located in the real/ subdirectory of the github repo:
main.asm | Main flow of the game |
util.asm | Math routines, copy routines, random number generator. |
tft.asm | LCD interface routines, graphics primitives. |
touch.asm | Touch screen interface routines. |
vector.asm | Vector and rectangle manipulation routines. |
At the top of main.asm, there are a number of constants defined. The most interesting are the SMOOTH_TERRAIN and FLASH_TANK constants. When both are enabled, the size of the code exceeds the 1024 byte limit. For the purpose of submission to the contest, I have chosen to enable SMOOTH_TERRAIN and disable FLASH_TANK. If you don't mind blocky terrain and want a cool flashing effect when a tank gets blown up, then you can change these constants to enable that. Also, you can turn them both on, but the game will no longer fit in 1KB!
The main game loop (in main.asm) is broken up into the ready, aim, and fire sections. Ready draws the board, aim handles manipulating the aiming cursor, and fire plots the projectile path. There is also a new_game section and labels for handling hits an misses. Several subroutines are also defined for generating the terrain.
The game is based on "real physics equations". Each pixel on the screen represents one meter of space. Obviously the tanks are oversized, to make the game possible to play. Position is computed using three vectors - acceleration, velocity, and position. Each vector consits of an X and Y coordinate, stored as 16-bit signed integers. Fixed-point math is used such that 1 meter = 64 units. A frame rate of 16 fps is used to plot the motion of the projectile. Every 16th of a second, the acceleration vector is added to the velocity and the velocity is added to the position. This is, in effect, a numerical integration of the 1/2at^2 equations we all learned in physics class.
The position vector is immediately scaled down into screen coordinates (1 meter = 1 pixel = 1 unit). The remainder of the calculations, such as hit tests and bounds checks are performed in this coordinate system.
The proto/ subdirectory contains an Arduino sketch that was used as a prototype for this game. This allowed me to try out new ideas and figure out how the...
Read more »