wolfSharp; C# implementation/rewrite of Wolfenstein 3D

In my effort to update this blog more often, I want to make a quick update of what I have going on.

I’ve been working on shader-based texture decompression for a bit; I’m planning to write a series of what I’ve done thus far. I’ve worked out three ways for decompression, two with my own written compressors and one that supports DXT1 textures. It’s not really a problem that anyone has but it caught my attention long enough that I wanted to see some results.

Right now, I’ve been reminiscing quite a bit about id software games and how I’ve played them my entire life. They’re kind of the reason I’m into this stuff and always wondered how they work when I was younger. I’m decent enough to know now and went ahead to look into the first id software game I’ve played: Wolfenstein 3D.

One thing lead to another and eventually I made myself believe that I’ll learn things a lot better if I just rewrite Wolfenstein 3D in C#. So that’s what I’m doing.

Out of the jail cell

I’m mostly following along the iPhone source code (and using all of the iPhone version of the assets, though I’m planning to implement full support for the original data later), though the ray casting was a little messy and confusing. Even though the iPhone version was rendered using OpenGL ES, it still used ray casting to determine which ’tiles’ were visible from the camera. Ray casting is actually not very expensive for Wolfenstein; it’s mostly the matter of iterating through the horizontal and vertical intercepts of the grid by using offsets. To see if the ray hit anything, you just check the tile position of the current iteration if it’s within a wall.

I’ve rewritten the ray casting part in the way that I understood it (with theĀ absenceĀ of Cos, Sin and Tan tables since they’re mostly superfluous now), which took a little doing since I’m prone to making dumb mistakes. I’ve finally gotten to the point where it’s rendering levels correctly, though.

First area

First area

As you can tell in the window title, I’m writing it in Playstation Mobile, but I’m writing the code in mind to be very portable. I’ve abstracted away the renderers and platform system functions so people would be able to just fill in the stuff needed to get it running on some different set of graphics APIs and such. After I’ve gotten the game feature complete, I’m planning to port it to XNA very quickly to see if I’ve done a decent job.

My philosophy with this rewrite is to keep it true to the original, but also architect it in a way that I’d write games today. In other words, same damage and movement models, but based on an entity framework.

The other part of this rewrite is the rendering systems, which I’m quite proud of. I’ve abstracted enough of the rendering system away, yes, but it’s all written in mind to only make a single draw call for the world rendering (two draw calls if you include UI). Doesn’t sound too great at first glance, developers batch quads for sprites and particles all the time to make that single draw call. Well, the other part of this, at least for Wolf3D, is that all the textures are not atlas’ed. I could process atlas textures offline, but that wouldn’t fit well with my goal of eventually supporting the original Wolf3D files. Instead, at level load, I automagically create an atlas texture for the level (which includes all the sprites and wall textures the level would use, even enemy sprites). Since any level in Wolf3D would never go beyond a 2048×2048 atlas texture, it makes it all done in a single draw call.

For now, all I have is level rendering of only the walls. From there, I’m going render doors and decorative sprites. After than, I’ll get started on the game, then polish up on the UI to emulate the original PC UI as possible.

This probably won’t be going on PSM and rather just reside only on my Vita so I can play Wolf3D where ever (unless id software would like to release it on PSM! That’d be cool!). Regardless of what happens, I’m hoping to open source it once I get it to a state where all the original features are implemented.