![](images/cover.png)
In 2008 I wrote an incomplete 3D game called ‘Tiberian Tanks’.
I wouldn’t be able to release it because it uses copyrighted assets from the long since disbanded Red Alert 2 / Tiberian Sun games, but I thought it might be worth writing about as an interesting project from my past.
![](/tiberian-tanks-3d/images/loading-screen_hu31b4af0fb584f1b046af5032e022bc10_852435_350x0_resize_box_3.png)
When I wrote this engine I had no knowledge of how to code properly (I was self-taught until I got to University), and things like Unreal Engine / Unity were not really a thing. I also had an obsession with reinventing the wheel (Actually I still do 😅).
The game is written in Delphi, and uses OpenGL. There is no scene graph. Instead things are drawn in-order with plain OpenGL calls, so transparency never worked quite right (see the loading screen!)
For those unaware of how a 3D engine should work, you must draw triangles from back to front so that the front triangles can blend with what’s already on the screen. The right way to do this is by storing all your meshes into a giant scene graph, clip it (cull) so that you’re only looking at meshes within the current view (frustum), then iterate through the graph from back to front. This is one of the many things that engines like Unreal / Unity do for free!
Delphi/ObjectPascal itself was an interesting language. It’s very different from the usual C-like languages. For example, here’s part of the main Timer procedure which is responsible for drawing everything:
procedure TfmMain.TimerTimer(Sender: TObject);
var
Rect: array[0..3] of TVector3f;
fnt: pGLFont;
i: integer;
LPos: array[0..3] of GLFloat;
begin
DoQuit := false;
FPSTime := GetTickCount;
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity;
// ...snip...
glBindTexture(GL_TEXTURE_2D, SkyboxTex[0].Tex);
glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex3f(-1, 1,-1);
glTexCoord2f(1,0); glVertex3f( 1, 1,-1);
glTexCoord2f(1,1); glVertex3f( 1, 0,-1);
glTexCoord2f(0,1); glVertex3f(-1, 0,-1);
glEnd;
// ...snip...
SwapBuffers(DC);
cSetStatus('FPS: '+floattostr(round(FPS*10)/10));
end;
One thing Delphi did well was that it had a great separation of code (implementation) and definition (interface). This made compling code fast and importing compiled libraries extremely easy.
As far as I know, no other mainstream language did this
- C/C++ have source and headers, but headers are really just a hack.
- C# / Python have a great object model, but don’t separate interface from implementation.
Another great thing was the amazing GUI designer and visual component system. Not even Visual Basic / Visual Studio came close to it…
I wouldn’t use Delphi in a serious project anymore though. It’s just not widely used enough, and there are much nicer languages like C#, Python, and even modern C++11.
![](/tiberian-tanks-3d/images/tiberiantanks-1_huc7a856b83403b23de23606ebf7a438d2_993687_367x0_resize_box_3.png)
![](/tiberian-tanks-3d/images/tiberiantanks-3_hu4a093227f8d6e74ae4f44a094ae55fce_784767_367x0_resize_box_3.png)
Returning to the game itself, here’s some of the neat features my engine had:
- A particle system engine (defined by INI files) - see the waterfall in the loading menu
- A Voxel model loader & renderer, specifically to load voxel models from Tiberian Sun / RA2.
- I believe this was adapted from an open-source voxel-viewing program also written in Delphi.
- A proprietary image / model encoding (I don’t know why I did this)
- A Blender extension to export models to my proprietary format
- The GUI was defined by the native Delphi 7 GUI editor, but rendered in OpenGL with custom textures
It also had a map editor: (basically a simple height-map + texture editor)
![](/tiberian-tanks-3d/images/editor-1_hu70b82733bab580a18011b751e36cf9c1_784022_750x0_resize_box_3.png)
Unfortunately I never implemented multiplayer or a decent collsion-detection system, so this isn’t useful for anything except as a bit of history.