WolfenGo: a Wolfenstein 3D clone in Go

It is sometimes nostalgic to try to implement an old (and supposedly simple) classic game in your new language of choice, just because you can. This is the story of WolfenGo, my port of a Wolfenstein3D clone to Go language, and how I came to narrow down the inadvertently introduced bugs in the days before its release.

First, let’s give a look to the original Wolfenstein3D, so you know what we are trying to approximate here:

(c) idSoftware & probably 3D Realms now

Isn’t it beautiful, in its pixel glory? I understand not everybody might agree here — although to be honest I am myself more of a Doom fan.

I was looking around for a Wolfenstein3D clone in Go, and since I couldn’t find any I picked this Java port by BennyQBD (material for his video tutorial, as I understand) and started porting it to Go with a simple OpenGL 2.1 engine.

The conversion itself didn’t take much time, but the very first time WolfenGo compiled and ran, I only got an uninviting black screen. Kind of expected. My first step into troubleshooting was to enable OpenGL debugging features of go-gl, but that alone didn’t help much.

My lack of knowledge regarding shaders/programs was also an issue, as last time I tweaked around OpenGL everything was commanded from outside the GPU. The real deal was to move all OpenGL code into a wrapper package, and then track all such calls on the Java port side to be able to compare them (meld was used in the process).

This approach proved fruitful as I could fix an improper use of glBufferData with ELEMENT_ARRAY_BUFFER where it should have been ARRAY_BUFFER, finally leading to my first non-black screen:

Maybe a surreal version of Wolfenstein3D, but definitely not what I was aiming for…

Seeing color is already something. This was already on 19th January, 2 weeks after the initial port done on 4th January.

The next bug I fixed was due to camera movement/perspective correction, and this was the admirable result:

I start to see something there..no.

After fixing integers incorrectly handled as 32bit values:

I see doors.

After loading the correct map data:

Now this is progress!

But still mouse look didn’t seem to work properly, as I don’t remember a Lunar Gravity powerup in Wolfenstein3D:

And finally, here we go:

Around the end I dropped my gl wrapper package and started using apitrace to get a better comparison of rendered frames; this tool proved very useful, although OpenGL debugging is to me not much less hard than it was ~10 years ago.

Plans & conclusion

The performance — as expected — is quite high, 60+ FPS can be easily achieved.

I plan to extend this port into something more usable/playable, and I also have some nice ideas about features to add. Feel free to contribute through the GitHub project.

The game in its current form is already complete for its educational purposes, although some bugs are still lingering around. It was overall a nice experience and seeing those blocky pixels on screen via Go/OpenGL is gratifying; it is always surprising to realize how complex were games even in 1992.

I have programmed some other games as a hobby in the past and most of them were C/C++, so this time I enjoyed being able to have this 2.5D game running with Go instead of C, knowing that under the hood it’s still doing an amazingly efficient job.