WARNING: NOT SUITABLE FOR CHILDREN UNDER THE AGE OF 7 DUE TO WEAPONS AND KILLING.
For the final project, we created a game, "Space Invasion", that is similar to a classic game from 90s: Space Invader. However instead of using a joystick to control the ship we used a distance sensor.
Space Invasion is a game in which a spaceship has to pass through the walls, without crashing. There are monsters trying to kill the spaceship. So the spaceship has to destroy them before getting destroyed. The game has no end, it is point based. The spaceship has two different types of guns: a rocket and a regular gun. There are different worlds in the game. Each world consists of 8 objects and is generated randomly. The objects could be gaps, walls or monsters. Each world has different types of monsters too. Some monsters are stronger, so the spaceship might have to use the rocket to destroy them. Also, the spaceship cannot fire the rocket all the time. After using it once, it has to wait for the rocket to reload, whereas the gun is always be loaded with an infinite number of bullets. The spaceship has three lives. If a monster hits the space ship or the space ship crashes into a wall, the user loses a life. One hit is all it takes to kill the spaceship. Also the game can store the user’s high score. The user’s gets points if he/she destroys a wall or monster, or if he/she survives for a period of time. The spaceship can only move right or left. We will assume that it is always going forward with constant speed. So, the user can only be able to shoot, change guns or direct the spaceship to move right or left. The user uses buttons to shoot and change guns, but does not use a joystick to control the spaceship. Instead the user uses a distance sensor that detects how far away the user's hand is from the sensor. When the user moves his/her hand away from the sensor the space ship moves to the left of the screen and vice versa. The game is shown on a monochromatic screen. There are also sound effects in the game when the user shoots the gun or rocket, or when the space ship crashes into a wall.
Today, kids grow up with technology all around them. 2-year olds play games on their dad’s IPads. However, we as teens born in the 90s, had a different perception of technology when we were kids. Instead of touch screen tablets, laptops or game consolers, we only had Atari. Even though the games were simple, not very user friendly and don’t look that good, we still spent so much time playing them. The game, Space Invasion is a game from the Atari years. We wanted to recreate the game we liked so much when we were kids, as we are the last generation to play this game. The game we implemented uses TV circuitry and distance sensors. The game includes many collisions, interrupts, drawings, and updates, or in other words complicated software. We wanted our final project to also be something we can enjoy and game architecture is both challenging and exciting. So, we combined hardware and software to implement a game we adored as children.
The reason we chose to implement this game was that it was using both complicated hardware and software. We wanted to recreate a popular game from 90s and possibly make it better and harder. Instead of using buttons to direct the spaceship, we decided to use a distance sensor. Using the sensor to direct the spaceship makes the game more user-friendly and better for gamers. Many people suffer from many different musculoskeletal diseases. Using your hand freely instead of the buttons will decrease the risk drastically. Another thing about this game is that playing the game on a microcontroller uses so many interrupts. The TV gets updated every frame, which is one sixtieth of a second. Our spaceship moves every 8 frames, and the collisions occur every 15 seconds. So it was really challenging and fun at the same time to be able to handle all the interrupts without the game flickering.
The project was completed by dividing the idea into steps and implementing them one by one. First we made sure that our basic microcontroller circuitry was working. Then, we tested our TV circuitry, which is the same circuitry we used in lab 3. After that we implemented our distance sensor circuitry. This was the most challenging component of the hardware. We used two low pass filters to eliminate the noise. We amplified the signal and use it to position the spaceship. Once we were sure that the sensor circuitry was working we started developing the software. We created the frame and the shapes of the walls, monsters, rockets, bullets and the spaceship. After that, we started implementing the collision algorithm. The logic of the game is very simple. The spaceship is controlled by the user. The spaceship moves forward all time. Every eight frames the position of the spaceship gets updated. Roughly every fifteen frames, the program checks collisions between the spaceship and the walls / monsters. Also every 15 frames the bullets and rockets in game are checked to see if they hit walls or monsters. If the spaceship collides with something it loses a life. The user gets only three lives. When the user loses all three the game is over and the final score is printed on the screen. The user can restart the game by pressing the shoot button.
The following is a logical diagram of our game.
There is one spaceship at the bottom of the screen. The spaceship has two types of guns: a rocket and a regular gun. The regular gun can be used constantly, as we will assume that the regular gun is always loaded with infinite number of bullets. The rocket takes 60 frame cycles to load and the power of the rocket is 5 times the power of the gun. The rocket is able to destroy the stronger monsters, and also some of the walls. If the spaceship collides with a wall or a monster the user loses a life. The user has a total of three lives and if all three lives are lost the user loses the game.
The space ship can only move left or right on the bottom of the screen. The movements of the spaceship are controlled by a distance sensor. The distance sensor measures the distance between the sensor and the first obstacle it sees. This result in an output voltage from the sensor, which gets amplified and passes through 2 low pass filters to eliminate the nose factor. Then the result is hardwired to the ADC of the microcontroller. The converted signal is used to position the spaceship. In order to make the movement of the spaceship accurate and precise, we measured the result from the sensor every frame and averaged them every 8 frames. Then we used this average to move the spaceship. When the user moves his/her hand closer to the distance sensor the spaceship moves right. When the user moves his/her hand further away from the sensor the spaceship moves left. Pushbuttons are used to fire the guns and change between the regular gun and the rocket.
There are two different types of walls. One of them is glass and one of them is stone. The rocket or a bullet is able to destroy one of those types, the glass type; it cannot destroy the stone type. The user has to navigate the spaceship to move between the walls without crashing into the walls. The spaceship loses a life if it crashes in to any of the walls.
We changed our world algorithm since the proposal. We were thinking of creating different worlds in the beginning. Then, we came up with a better idea. We used a randomizer to create the worlds. The worlds consist of lines of eight objects. These objects could be gaps, where the spaceship can pass, the two types of walls or the two types of monsters. Every “pace” frames (pace is a variable that starts as 40 and decreases as the games go on, making the game harder), the world arrays move down the screen. There are 11 world arrays on the screen at all times. Nevertheless, 8 of these world arrays consist of only spaces, giving a chance for the spaceship to move. The world array generator generates random worlds every four times and generates all gaps the rest of the time. The generator uses the rand() function from the C library. The seed for this generator is the x position of the spaceship. As the spaceship moves, the seed changes and the generator generates a different world every time.
There are two different types of monsters. The first type can be killed with one shot from both the regular gun and the rocket. The second type can only be killed by one shot from the rocket. It cannot be killed by the regular gun. If any of the monsters collides with the spaceship the user loses 1 life.
The RS170 and NTSC standards are used to display our game on to the TV.
The only trademark that is associated with our project is with the original space invaders game. The original space invaders game is a trademark of and is copyrighted by Taito America.
There wasn't a lot of hardware used in this project. The hardware used in this project consists of an ATMega 1284 microcontroller, a Sharp GP2Y0A51SK0F distance sensor, a LM358 op-amp, two lowpass filters, 2 pushbutton switches attached to pull-up resistors, a monochromatic screen and a few resistors connecting the screen to the ATMega 1284. The complete circuit schematic is shown in the appendices section.
The Sharp distance sensor is used to detect the user's hand movements and move the space ship to the left and right accordingly. It can detect distances anywhere from 2 to 15cm. The distance sensor consists of an IR-LED (infrared emitting diode), a PSD (position sensitive detector) and a signal procession circuit. The light from the IR-LED gets reflected off an object and hits the PSD. This signal gets sent to the signal processing circuit which produces an output voltage based on how far the first object it sees (in this case the user's hand) is from the sensor. The closer the user's hand is to the sensor the higher the output voltage. This output voltage is then lowpass filtered amplified and lowpass filtered again. Then it is used by the microcontroller to determine where to draw the spaceship. The diagram of the distance sensor is shown below.
When we measured the voltage with a multi-meter at the V0 pin, we discovered that the output voltage ranged from 0.332V when the user's hand in 15cm away to 1.250V when the user's hand is 3cm away from the distance sensor. However, the range needed for the ADC (analog to digital converter) in the microcontroller was from 0V to about 5V. So we decided to amplify the signal using a non-inverting amplifier made from a LM358 and some resistors and then tune the ADC with software to get the right increment for our spaceship. Since the voltage the ADC required was roughly 5 times the output voltage of the distance sensor, we decided we should design an amplifier with a gain of 5. So we calculated the resistor values with the equation:
with R1 and R2 being the two resistors. We calculated that R1 should be either 10ohms or 10kohms and that R2 should be either 30ohms or 30kohms. When we tested the circuit in the lab with the different resistors, we found that R1 should be 10kohms and that R2 should be 30kohms. The diagram of our LM358 Op-amp is shown below.
When we first hooked up the distance sensor to the microcontroller, we found that the spaceship was moving even when our hand was not in front of the sensor. Since the spaceship was just a little jittery, we know we had some noise, so we decided to filter it out with a low pass filter. Since the noise was very subtle we decided that a lowpass filter made up of a 1kohm resistor and a 0.1pf capacitor would work. So we built one and hooked it up in between the amplifier and the microcontroller. However, there was still some noise. So we hooked up another one of the same amplifier in between the distance sensor and the amplifier. With the filters hooked up like that, the first filter filters out the noise from the distance sensor and the second filter filters out the noise from the amplifier. We also did a little filtering in our software. When we hooked up both filters and turned on the game, the spaceship stayed still when our hand was not in front of the sensor.
The push button switches are hooked up to 330ohm resistors, which are hooked up to ports c6 and c7 of the microcontroller. One of the buttons allows the user to file the gun and the other one allows the user to switch between the gun and the bazooka. When one of the buttons is pressed the value on one of the ports goes low depending on the button pressed and the microcontroller knows either to fire the gun or switch weapons.
The circuit to hook up the TV to the microcontroller is made up of two resistors R1 and R2 hooked up in parallel. R1 is a 1kohm resistor and R2 is a 330ohm resistor. R1 is hooked up to port D0, which is the sync port, and R2 is hooked up to D1, which is the video port. The other end of the resistors is hooked up to the video port of the monochromatic screen. A signal is sent through port D1 to the screen whenever an image needs to be drawn.
The program for the spaceship was rather simple. The spaceship was drawn with a series of horizontal lines. The movement of the spaceship was controlled by the ADC. Every frame we took a sample from the ADC and stored it into an array. Then every 8 frames we averaged the results by adding up the 8 values in the array and right shifting the sum by 3, which is effectively dividing it by 8. We then adjusted the average so that it falls between the values 0 and 160 when the user's hand is between 2cm and 15cm away from the sensor. In the end the average was 0 when the user's hand was 15cm away from the sensor and 160 when the user's hand was 2cm away. Then we checked to make sure the values did not go over 160 or under 0. Since the values wrapped around, we fixed the x value to be 0 if the average-11 was greater the 159, which is the x value for our right boundary. We fixed the x value to be 147 if the average is greater then 147.
We debounced the push buttons by using a state machine. When the user pushes one of the buttons the state changes from state NoPush to state MaybePush to indicate that the user might have pushed the button. In the next frame if the button is still pushed the state changes from MaybePush to Pushed indicating that the user has pushed the button. Then the program decides which button has been pushed by checking the ports C6 and C7 and seeing which port is low. If C6 is low the program draws a bullet or a rocket in front of the space ship and stores the x and y values of the bottom of a bullet of the bottom center of a rocket in an array. depend on the type of gun the user has selected which we have stored in a variable called type. If type equals 0 the bullet is selected and if type equals 1 the rocket is selected. If the rocket is select the program also checks to make sure that the draw variable is zero. If it is zero the program draws a rocket. If it is not zero, it means that a rocket has been fired in one of the past few frames and it is too soon to fire another rocket. In that case the program does not draw anything. The programs is designed so that the user can only fire one rocket every second. When one of the push buttons is released the state changes from pushed to MaybeNoPush indicating that the user might have released the button. In the next frame, if the button is still released, the state changes from MaybeNoPush to NoPush indicating that the user has definitely released the button. The bullets that are on the screen are programmed to move 11 pixels up the screen every 15 frames. The rockets that are on the screen are programmed to move 11 pixels up the screen every 16 frames.
As it is mentioned above, there are two types of monsters. The spaceship loses life if it collides with any of them. The world array moves down every “pace” frames. When it moves to the same level as the spaceship, there is a subfunction that checks if the spaceship hits the walls or monsters. If it does, the spaceship loses a life and the world array that hits the spaceship gets deleted. The spaceship has an ability to shoot. It shoots rockets or bullets. When the rockets or bullets are on the screen , they are saved in an array. Every fifteen frames, quarter of a second, all bullets and rockets are checked to see if they collide with anything. If a bullet or rocket collides with the first type of monster, it kills the monster. Monster 2, however, can only be killed with a rocket. The bullet or the rocket can break the glass wall too. Nevertheless, none of them can break the stonewall. The spaceship has to try to avoid colliding into the stonewall in order not to lose a life. When the spaceship collides with an object, the world array containing the object blinks three times before it disappears. The game stops for 40 frames and then continues where it left off. In order to avoid flickering of the TV, we check the collisions every 16 frames for the spaceship and 14 frames for the bullets. Even though we aimed at updating everything every 15 frames, by using 14 and 16 frames for some of the collisions we divide the amount work that had to be done in one frame. At the same time a one-frame delay does not change the game at all for the user, it only severely decreases the amount work that needs to be done for the main function, which helps the TV not to flicker because of all the drawing, and deleting of objects on the screen.
We initially did not mention that we are going to have sound in our proposal. But, our lab TA Eileen suggested that we add sound to our game and we thought it was doable. So we added sound effects to parts of our game. There are sound effects when the user fires the gun or the rocket, when the rocket or bullet hits a wall or a monster and when a wall or a monster hits the spaceship. The sound effects of the game were done with a square wave sound synthesizer and the PWM on the microcontroller. This made the sound effects sound more game like. The pitches of the notes that we wanted to play were stored as integers in an array called “notes”. The higher the integer stored, the lower the pitch of the note. When we wanted to play a sound effects, we would send the values of the notes we wanted to play from the array to the OCR0A register of the PWM one at a time. If we had to play more then one note we had the microcontroller wait for a few frames (usually 2-3 frames) between each note we had to play. So, the notes sound like they had been played together, since a 1/60 second delay is inaudible to the human ear. After we played the sound, we would let the sound go on for 5-15 frames depending on how long we want the sound effect to go on for and how many notes we had to play. For example, the sound that is played when the spaceship collides with a wall consisted of four notes, so we had it go on for roughly 15 frames. After letting the sound play form the amount of frames needed we set the OCR0A register of the PWM to 0 to turn off the PWM.
We can say that the speed of execution of the game was even better than what we anticipated. We used some helper functions to check for possible collisions before the collision happens, which increased the speed of execution. Also during collisions we disabled the interrupt. Even though this created a small delay, it helped the game to be played without any flickering or any other bugs that would have been created because of untimed interrupts. So we can say that the speed of execution was perfect for the game. We used the variable “frame” to keep track of the execution time. We used the microcontroller’s timer interrupt to increase the frame variable. One frame corresponds to one sixtieth of a second. The spaceship movements are updated every 8 frames and collisions are checked roughly every 15 frames. Also, the game gets faster and faster as the user plays. This makes the game harder as time goes on, which is a common feature for video games. The pace at which the walls are moving (which the user observes as the speed of the spaceship) changes. It starts as every 40 frames and it goes down to every 20 frames. So the user has to get faster in order to keep playing without losing a life. The microcontroller’s timer interrupt is fast and accurate enough for use to the state that the speed of execution of the game is flawless and at the level we wanted it to be.
Accuracy was important mainly in three different cases. First of the accuracy of the distance sensor circuitry was very important. The movement of the spaceship was very accurate. The sensor worked perfectly and with our LPF and amplifier, and the software algorithm. Therefore, the movement of the spaceship corresponding to the position of the user’s hand in front of the sensor was very accurate and precise. This made the game playable and user friendly. When the user wants to move the spaceship immediately to avoid collision, the game responds very quickly and accurately. The other scenario was the collisions between the bullets/rockets and the monsters/walls. Since we were checking the y position of the bullet and the obstacles to check if there was a collision, sometimes the collisions were not that accurate. The bullet constantly moves up while the walls move down. This made it harder to detect the bullets immediately. Nevertheless, even though it wasn’t perfectly accurate, it was accurate enough so that the logic of the game wasn’t violated and the accuracy of the game was sound. The third case was the collisions between the spaceship and the world array. This also had to be flawless for the soundness of the game. Since we checked the collision right after the world array moves down to the same level as the spaceship, it made the game very accurate and close to reality. The gamer is able to physically detect the possibility of a collision, which gave him/her the chance to try his/her best to avoid collisions. The size of the spaceship was slightly smaller than the size of the walls and the monsters; therefore, it was not hard to move between walls and stay alive. In conclusion, we can say that the game was very accurate, which made the game fun to play while keeping the logic of the game sound.
The project is a mainly a software project. Therefore the safety was not a big issue for us. The hardware we had was safely implemented. We included resistors to keep the microcontroller channels safe and to avoid any burned channels. The distance sensor is a very safe device and it was also implemented with pull up resistors and decoupling capacitors to avoid it drawing too much current, which could burn the microcontroller or the sensor itself. So we can say that safety was not a huge issue for our program and we took every possible precaution to keep our circuit safe. For the safety of the gamer, it is pretty much really safe. Nevertheless, if the gamer plays the game for too long we cannot prevent the gamer from getting one of the video-game related musculoskeletal diseases. However, as abovementioned, using a sensor instead of buttons decreases this risk drastically. In conclusion, it is a safe game to play for the user and the circuitry is pretty safe and should last really long.
In conclusion, the results exceeded our expectations. The speed of execution was very sound. There was no flickering of the screen even though we were drawing many lines on the screen. This was partly due to the memcopy function and partly due to us splitting up the work into different frames. The distance sensor was very responsive and fast. If the user wanted to move immediately to avoid a collision with the wall, the spaceship would react immediately. If we were to do this project again, we would use a different algorithm to calculate the collision, since some collisions were occasionally not calculated correctly. Nonetheless, the game worked flawlessly.
Our design conforms to the applicable RS170 and NTSC standards. The TV we're using is able to render black and white pictures. Our refresh rate is 60Hz since one frame is 1/60th of a second.
The main structure of the code was taking from Professor Land's sample code for lab three. Since everybody has access to the code, we used code from the public domain. We didn't reverse-engineer anything nor did we have to sign a non-disclosure to get a sample parts (since we didn’t use any). Since our game mimics a copyrighted game "Space Invaders", there are no patent or publishing opportunities for our project.
Throughout our project we followed the IEEE Code of Ethics. We worked in a friendly environment and had friendly interactions with our professor and teaching assistants. Moreover, the circuit is safe to use. We have insulated the microcontroller channels with resistors so that channels don’t get burned. Therefore, the user would not get injured from a hot microcontroller. We were honest in what we can accomplish and disclosed anything that was different from what we proposed, such as how we did the world. We also disclosed that this game is not appropriate for children under the age of 7 due to concepts of death and violence in the game. We accepted all suggestions that our professor gave us and corrected our errors in both the hardware and the software. We help each other with writing and debugging the code when the other person was busy. We give credit to others who we borrowed code from by disclosing that information on our webpage and by putting their name in our commented code where applicable. Also, we disclosed that fact that “Space Invaders” is a copyrighted game and we are making a game similar to it called “Space Invasion”. We didn’t accept any bribery and stayed well within our budget.
Even though this is a replica game of a game it already exists, legally it is not illegal to create a similar game. Nevertheless, the name of the game cannot be the same of the actual game. The name of the actual game was Space Invaders and therefore our game’s name is Space Invasion instead. So legally there are no problems.
Please click here to see our commented code
Below is the full schematic of our circuit
Below is a table of our cost details
|White Board x2||$12|
|Power Supply x2||$10|
Below is the table of specific tasks done be each person.
|Task||Who did it|
|Writing the Code||Both|
|Testing the code||Both|
|Ordering Parts for the project||Kaiyuan|
|Writing the Report||Both|
|Making the Webpage||Kaiyuan|