As we wrap up development on our Arduino version for the 50th anniversary of Spacewar! at MIT, undergraduate Kaivan Wadia reflects past few weeks in the following blog post.
3 2 1... Blast off! Spacewar! is ready to be played with all the peculiar features of the original game. The last blog post mentioned the clever manner in which the spaceships were drawn. We decided not to use that exact technique but instead use the Gameduino's sprite technology to implement our version. This turned out to be very efficient in terms of management of the game state and had the added bonus of making collision seem easy to implement, even though we did not use the Gameduino's collision detection mechanism in the end. The night sky background was also implemented using the sprite technique, thereby remaining true to the original game, where each star is drawn separately after checking to see whether it is in the viewable region of the screen.
Next, we went on to add the thrust and hyperspace features for the spaceships. Hyperspace required a bit of repeated manipulation to get the counters correct for the time spent in hyperspace and the cool down time between two hyperspace jumps. The thrust for the spaceships was implemented using sine and cosine functions, which also posed a problem considering the limited capabilities of the Arduino microcontroller. Using floating point and long variables was not very efficient, as there was limited RAM on the Arduino, which would be used up quickly if we kept using them.
Once we got the thrust feature working, the next logical feature to tackle was gravity, which posed the same computational problems. One of the main features of Spacewar! is the ever-changing gravity and its sling-shot effect on spaceships under certain circumstances. To implement the change in gravity we first simply divided a constant by the distance between the sun and the spaceship. This gave a very positive result in terms of the effect of gravity but did not produce the sling-shot effect that Spacewar! originally had. We then decided to implement gravity as the ratio between a constant and the square of the distance between the sun and the spaceship. This gave us the desired sling-shot effect. It was then just a matter of adjusting the thrust and gravity constants to make the game interesting and playable. One peculiar result of this implementation of gravity was that when you approached the star at a certain angle and certain speed you could be bounced of in a completely different direction or pass right through the star at a very high speed, which was crazy but fun and true to the original game.
The next task was to get the spaceships to be able to blast torpedoes at each other. This was relatively simpler to implement considering our experiences with the thrust and gravity problems. The amazing feature here was that the torpedo velocity also depended on the velocity of the spaceship. This later caused a problem in collision detection: if you were travelling at a very high velocity, turned around, and fired, you would shoot yourself. This solution to this problem was to store the velocity of the torpedo separately and have the first appearance of the torpedo completely independent of the velocity of the spaceship.
One of the last tasks was the collision detection algorithm. The Gameduino itself has an in-built pixel perfect collision detection mechanism, which seemed the logical choice, but later posed a lot of problems. The problem with the Gameduino's collision algorithm was that it only detected a single collision and could not report multiple collisions for the same sprite. Since we had implemented the stars as sprites it was very tedious to detect whether a spaceship was colliding with a star or something else. In some cases a collision would not be reported at all!
We finally decided to implement the collision algorithm used in the original game. The original algorithm considered imaginary circles around the spaceship and detected whether any object capable of blowing it up was within that circle. This resulted in a slightly mysterious effect where torpedoes could pass through the spaceship occasionally. Sometimes two spaceships could pass through each other at certain angles. A spaceship could also be blown up by a passing torpedo that was not going to hit it, but was simply within the circle. This was faithful to the original PDP-1 game, and thus acceptable for our version. Implementing this algorithm was computationally heavy on the Arduino but did not slow it down. We also got the desired effect we were looking for: torpedoes would occasionally pass through a spaceship.
After collision detection, we were left with the explosion of the spaceships. In the original game the explosion of a spaceship resulted in a large number of dots on the screen at the site of the explosion. We wanted to implement the same but with a Gaussian distribution. On implementing the algorithm to generate random number in a Gaussian distribution the game slowed down dramatically when an explosion took place. Although this did not matter much as the game would be over after the collision, it did not look very good. After manipulating the algorithm to remove square roots and logarithms, we finally reached a point where the explosion looked good and did not affect the game speed drastically.
You'll be able to play our version of Spacewar! on February 8 at the Stata Center.