Yes, a Tron Clone in 3d.
Armagetron as it's been succinctly put, is a Tron Clone in 3d. It replicates the lightcycle sequence of the movie Tron as an immersive playable game. A game that's been enjoyed by all ages for years. This port to the Raspberry Pi aims to continue that tradition for a new generation of players.
Credit where credit is due, I didn't do this all by myself. In fact, what I've done constitutes the smallest fraction of the work. So please, give thanks to Voodoo who did the hard work of porting the OpenGL engine to OpenGL ES, and to the rest of the Armagetron Advanced development team who have contributed to the project over the years. And of course, don't forget Z-man.
Armagetron in motion...
This is the important bit right here.
This is a release of Armagetron Advanced 0.2.8.3.2 for the Raspberry Pi. The code is released under the GNU General Public License, so the source is available too!
Holy smokes Batman, it's the memory split!
In order to play Armagetron, your Pi needs to have 128 MB of RAM allocated to the GPU. The default is 64 MB so you may have to change this. This is the gpu_mem setting in the config.txt file.
You can also change this setting with the raspi-config program
Select "8 Advanced Options" "A3 Memory Split" and then enter 128.
A bit more direction to help get started.
Well... Not so much installation as running the software. These directions are for Rasbian. As far as I know, all the libraries needed by Armagetron are installed by default. However, if by some chance they are not, the first step would be to install them:
sudo apt-get install libsdl1.2debian libsdl-image1.2 libsdl-mixer1.2 libxml2
Hopefully that will have produced a list of "is already on the newest version" and so you may proceed onto the next step, which is extracting the game:
tar jxvf armagetronad-0.2.8.3.2_dist.tar.bz2
A bunch of text looking like a file listing should have just flashed past. At this point you're practically set to run! What comes next is what you'll have to do every time.
cd armagetronad-0.2.8.3.2 ./armagetronad_main
There you go! The first time the game runs it will ask about language. This can also be changed later. Go to "Play Game" "Local Game" to get started! Z turns left, X turns right. Try not to crash! If the graphics are frozen once you start the match, check your memory split.
So you want to start out from scratch eh?
Right. This time you definitely need to install things. By default GCC, the compiler, is already installed with Rasbian. This is a good start, but we need a bit more.
sudo apt-get install build-essential g++-4.7 libsdl1.2-dev libsdl-image1.2-dev libsdl-mixer1.2-dev libxml2-dev automake
This installs the headers and libraries needed to compile Armagetron. The eagle eyed among you may have noticed build-essential and g++-4.7 in there and those aren't libraries. Correct, that makes sure the bare minimum for compiling is installed and also pulls in the newer version of GCC and friends. The latter produces slightly better code and we want all the help we can get. In order to take advantage of it we need to tell the system to use it though. Debian doesn't have a default way to do this but a kindly fellow has written a script for it, which we can download and run:
wget https://dl.dropboxusercontent.com/u/15313414/Blog/gcc-set-default-version bash gcc-set-default-version 4.7
At this point we can extract the code, enter the Armagetron directory, and it's compile's away! I've created a script to replace the standard ./configure that specifies the appropriate code optimizations for the Pi.
tar jxvf armagetronad-0.2.8.3.2_src.tar.bz2 cd armagetronad-0.2.8.3.2 ./bootstrap.sh ./myconfig.sh make
Go ahead and grab a cup of tea now. This will be about half an hour. But when it's done you can now run the version you yourself compiled!
I'd like to understand what's happened!
Wouldn't we all? I mean, what are we here for man? What's the meaning of life? Oh, you meant the code? Sure. Yeah. Just a sec. *cough*
This is both simple and complex. I'll explain what I've done in general and then move onto some more specific details. As I mentioned in the introduction, Voodoo ported the game's OpenGL to OpenGL ES. This was a translation of the directions of what the pictures on the screen should look like from say Italian to Spanish. Related, sure, but not quite the same thing.
That was a really great start. The work was part of a project to get Armagetron running on the iPhone. He actually succeeded, but was unable to release the game for performance and licensing issues. Apple does not like open source, but Voodoo does, so he made most of his work available, fortunately for us. I downloaded that and wrote a patch on top of it to work with OpenGL ES on the Raspberry Pi and link with the Broadcom libraries. Unfortunately for us, Voodoo did all his work on a fairly old version of 0.2.8. 5 years old from now, 2 years older than 0.2.8.3.2, which is the newer code version I had to port his OpenGL ES work as the final step to producing something I could share.
Great, but what did you actually do?
My changes can be broken down into three categories:
The first step was to learn how to do OpenGL ES on the Pi. Documentation there is surprisingly thin on the ground, but eventually I cobbled together a simple bouncing cube program that had all the essentials. Fortunately I already knew some OpenGL from my work on Androgetron, which while not Armagetron, did use OpenGL ES under Java. The critical pieces are establishing the EGL context, initializing SDL solely for input, and re-implementing the gluPerspective function. (It isn't part of OpenGL, and is definitely not part of OpenGL ES. Hello GLU!)
After learning how OpenGL ES worked on the Pi, the next issue was transplanting that into Voodoo's Armagetron code. Fortunately I've done some Armagetron programming before so I had a rough idea of what I was doing there. gArmagetron.cpp is where the main() function is at, and it was just a matter of hacking out the normal display init function (sr_InitDisplay()) that would take place and replacing it with the OpenGL ES initialization code for the Pi. eglSwapBuffers() had to be added in with the regular OpenGL swap function so that the display would update. The resolution determination from the Pi also had to be connected to the screen resolution variables sr_screenWidth and sr_screenHeight. I also had to add the relevant headers in.
Outside of the regular code, on the automake side of things, the configure.ac file had to be edited to remove checks for OpenGL and GLU that were patently going to fail anyway. Linking to the Broadcom libraries was achieved through CPPFLAGS and LIBS environment variables to the configure script. Half an hour later for compile and voilà! It worked! I almost couldn't believe it. Of course, nothing is perfect. If you've watched my video above, that's how it looks out of the box with only those code changes applied.
So it was time for bug fixing. Primarily centered around texturing. Double floor texturing causes problems, so the default is now single texturing. OpenGL ES appears to be unable to handle anything other than RGBA textures, so not only did all of the textures have alpha channels added, the code had to be hacked to stop the automatic stripping of the alpha channel that takes place to save memory. The textures also needed to be in power of 2 sizes (256, 512, 1024, etc.). OpenGL ES has these quirks... Cycle coloring was also going mental. I can't quite remember why what I did fixes it, but it does. Just for tidiness I also removed the options for changing resolution from the configuration menu. They don't do anything now (the game is full screen only) so why tempt fate.
The final step before release was porting all of this onto the 0.2.8.3.2 codebase instead of Voodoo's 2 years out of date Revision 1015 code. Fortunately this was fairly straight forward. (But it could have been awful!) I checked out a clean copy Revision 1015, ran a diff on Voodoo's+My changes to create a patch file, which I then applied to a clean 0.2.8.3.2 source tarball. Fortunately the conservative nature of the 0.2.8 branch of Armagetron code meant nothing too major happened in this period, particularly with the rendering code, letting the patch apply more or less cleanly. There were only like 3 places where I had to manually tweak the code to get everything applied. This is where the luck comes in, because this could have been really, really bad.
And there we are! End of story and the change I made. I've got two patches available to highlight the code changes:
Yikes! It's supposed to do that?
Well, no. Probably not. As far as I know there are two definite bugs and potentially a third one.