161
3D Shooters Episode I:
Wolfenstein 3D for Android
The next two chapters are my personal favorites and the most exciting of this book. We start by looking at the real thing: Wolfenstein 3D (also referred to as Wolf 3D), the godfather of all 3D shooters. The main goal of this chapter is to show you how easy is to bring Wolf 3D from the PC to the Android device, but also in this chapter, you will learn how to do the following:
• Maximize code reuse by compiling high-performance native code in a dynamic shared library.
• Write JNI code to connect Java and C subroutines.
• Cascade graphics back and forth the native and Java layers.
• Handle sound requests sent by the native layer with the Android media player.
• Build the Android project and test in the emulator.
Let’s get started.
Gathering Your Tools
Some Java developers simply dismiss other languages, especially procedural languages like C. I believe that you should embrace the elegant object oriented features of Java and the raw power of C and there is nothing you cannot do in the gaming world.
Before we start, you will need to acquire the things explained in this section to make the most of this chapter.
Downloading the Chapter Source Code
My 1.210goal in here is to create a balance between the object-oriented features of the Java language and the power of C. Thus I have provided not only the Java source but the C code, neatly organized in this chapter source code. You should import the project to workspace as you move along this chapter. Some of the listings have been stripped for simplicity. To import the chapter source to your Eclipse workspace, follow these steps:
162
1. From the main menu click File ➤ Import.
2. In the Import dialog, select Existing Projects into Workspace. Click Next.
3. Navigate to the Chapter source ch06.Wolf3D.SW; optionally check “Copy project into workspace”. Click Finish.
The automated build will kick in immediately; make sure there are no errors in the project. Next, try to familiarize yourself with the folder layout, which is divided in the following subfolders:
• src: This folder contains the Java layer of the game.
• assests: This folder contains the game files for the shareware version of Wolf 3D compressed in the zip file: wolfsw.zip.
• libs/armeabi: This folder contains the Wolf 3D native library libwolf_jni.so.
• native: This folder contains the source of the Wolf 3D C engine. The version I choose is Wolf 3D for the Game Park gaming device (a popular Korean handheld also known as GP32).
• res: This folder contains Android resources: graphics, sounds, layouts, and strings.
Introducing Wolf 3D
When Wolf 3D came to the game scene of the 1990s, it revolutionized PC gaming forever. It was the first game of its kind: a game with immersive 3D graphics where the player navigates the Nazi underground picking up weapons, opening secret doors, and shooting up rabid dogs and evil Nazis (see Figure 6-1).
Figure 6-1. Wolf 3D running on the emulator
163
Even though the game’s environment appears to be 3D, it really is not. In reality, the game uses atechnique called ray casting pioneered by John Carmack from id Software (one of the original creators of the game) to simulate a 3D environment. Ray casting is also called 2.5D and provides the geometry to render perspectives and other pseudo-3D elements.
■ Tip A nice ray casting tutorial by F. Permad discusses the basics such as drawing textures, floors, ceilings, walls, shading, and more. Plus, it has some neat Java examples. It can be found at
http://www.permadi.com/tutorial/raycast/index.html
.
According to an article on Wikipedia at http://en.wikipedia.org/wiki/Wolfenstein_3D, Wolf 3D was released by id Software in 1992 to a huge success. It popularized the first-person shooter game for the PC. The source code was later released under a shareware strategy that helped the game to be ported to almost any platform imaginable, including these:
• Windows and Pocket PC
• Linux
• Nintendo Entertainment System (NES) and Super Nintendo (SNES)
• Atari Jaguar
• Mac OS
• Game Boy Advance
• PlayStation and PSP
• Xbox 360
• iPhone and iPod Touch
When I started fiddling with the idea of bringing Wolf 3D to Android, I knew the key of the project would be to find a highly portable version for Linux, because first, Android is built on Linux, and second, high portability will minimize potential compilation and optimization errors that are very common when using different versions of the GNU C compiler. The best two candidates I could find on the web follow:
• Wolfenstein 3D for GP32: This is a port to the Gamepark32, a Korean handheld device similar to the PSP. It is written in C. Wolf 3D for GP32 is available online at http://sourceforge.net/projects/gp32wolf3d/.
• Wolf3D S60: This is port of Wolfenstein 3D and Spear of Destiny for Nokia S60 cell phones. Wolf3D S60 is available online at http://sourceforge.net/projects/
wolf3d-s60/.
Digging through the source of both projects, I realized that both were almost identical and based on a defunct port for Linux found on the Web. Of these two, the Gamepark32 version seemed the cleanest and easiest to understand, so I decided to use it. If you wish to understand why nobody has taken the time to port this code to Java, take a look at Listing 6-1.
164
Listing 6-1. Total Number of Lines of Source and Headers for Wolf 3D for Gamepark32 gp2xwolf3d>wc -l *.c
165
795 wl_act3.h1401 wl_def.h 212 wl_menu.h 4494 total
Listing 6-1 shows the total number of lines of code (.c files plus .h header files) of Wolf 3D for the Gamepark32. It’s close to 30,000 lines of code. It doesn’t seem that much for today’s standards, but consider this: when I was in school, one of my computer ethics professors said that, statistically, a software developer can deliver ten lines of production-quality code per day. If you do the math, 3,000 days is the time that a single person would take to deliver a high-quality product. Compound this with the fact that that the work must be done pro bono. Wolf 3D falls under the GNU Public License (GPL), which would allow you to sell your Java version; however, the GPL also requires for you to give up the source, which will prevent you from reaping the product of your hard work.
In my quest to bring this game to Android, I even played with the idea of rewriting this code in Java.
I found people who attempted a Java and JavaScript port of the game, but I was quickly discouraged after looking at the complexity and size of the source. These are the reasons why a pure Java port of this game is not feasible:
• Size: The code base is too big and complex (even for such an old game).
• Licensing: All work must be done for free, which is not good for business.
• Time: Writing the game will take too long even for a small team of developers.
The only solution with potential time and cost savings is to create a dynamic shared library of the game and cascade messages back and forth between Java and C using JNI. This is what you will learn in this chapter. Let’s get started by looking at the game architecture from a high level perspective.