Writing a Real-Time Strategy Engine From Scratch, Or How I Made Pong In Only 3 Years

Published September 10, 2020
Advertisement

Hello gamedev.net!

The time has come for me to exit the shadows in which I lurked.

In the fall of 2017, I started going through some OpenGL tutorials and trying to put together my own renderer. It was fun. Maybe it was this feeling of fun that led me down the path that I followed. Here's one of the first screenshots of the RTS engine. It actually took me an ungodly amount of time to debug the skeletal animation. I almost gave up and abandoned the project altogether. At the very beginning, I feel it is easiest to give up. Later down the path, you are far more invested and, driven by the sunk cost fallacy, your mind keeps nagging at you to “finish” the project. Well, I really hope to bring this to some sort of conclusion - if not “the end”, at least “an end”.

Anyways, it started the way many hobbyist engines do. With a basic window. Then with a mesh inside that window.

Then after adding shading:

At first, I didn't think the project was going to be anything more than a simple renderer just for my own learning. But after I finished it, I had no project to keep me occupied. There was this hole in my life. I was thinking of what to do and had an idea of trying to make an RTS game building on my renderer. Yeah, people say that when you do gamedev, you've got to start small. Just make tetris in Unity. Definitely DON'T make an RTS in your own C engine! I guess I just always looked towards the heavens and wanted to build grandiose things - Unity tetris just didn't do it for me.

Fast forward a bit, and I got basic Minecraft-esque terrain up:

Then I tossed in CPython into the engine, debugged whack reference-counting bugs for a bunch of days and got a very early scripting system in. Why Python? One reason is that I personally wanted to learn the language, and this was just an excuse to do it. The second reason is that it's a popular and expressive language and I thought it would be really user-friendly to modders. Yeah, it has it's cons as well. But the choice was made.

Then, making use of the scripting system, I made a basic editor:

I started learning more about shader programming, trying to figure out how to dodge the “Minecraft” look, and came up with some bilinear interpolation type of stuff:

This too, took a bunch of time to debug. Here's a screenshot from that battle:

So far it's not an RTS, is it? Just a basic mediocre-looking terrain renderer using bad OpenGL. So I tried to fix that. I started working on a pathfinding system. One that would support “a lot” of units. Here's some early rendering of terrain pathability (the yellow lines are boundaries between different chunks).

Here's some debug visualization of the flow fields used for pathfinding. The yellow tiles are the ones currently in vision of the 2 knights.

Here are some early shots of groups of units moving around. The units flock (using Craig Reynolds' flocking behaviours) and use flow fields for going to their destination. Note the jitter and shaking of the units. This was something that was in the engine for a long time. I didn't make the pathfinding system “in one go”. It was a lot of incremental improvements based on learnings of what didn't work so well…

I added shadows, which immediately made the game look 5.6x better, in my opinion:

Later, I softened up the shadows and went back to make the maps look better. I added smooth interpolation of the normals to create a softer terrain look. Under the hood, the map was still a tile-based “Minecraft-like” map. But some shader “tricks” made it look less bland:

I added some animated water:

I went back and improved the pathfinding system a good amount. Reduced the jitter. Made it more robust. Handled a lot more edge cases. Besides some super next-level “Hybrid Reciprocal Velocity Obstacle" collision avoidance stuff that I managed to dig up online, adding a simple moving average to smooth out the velocities over time was like half the battle. But even that basic idea took months to enter my mind.

I added some profiling code. I tried to improve performance such that higher unit counts could be supported. I had only moderate success in this area. There's still a lot of space for improvement in this area. At the time I decided to focus on more pressing things, like complete lack of features of gameplay. Yeah.

Well, not before I took a detour and spent a bunch of time working on a batch rendering system that I also haven't made use of so far:

Finally taking a step back towards features and mechanics, I added Fog-of-War mechanics. Here's an early WIP. The good news is that, having walked the long and difficult path to make, debug, and profile the engine up until here, I definitely felt my power level increase. I now had an idea of what OpenGL performance was about. I could come up with my own ideas regarding how to implement the fog-of-war effect in a relatively efficient manner.

For a long time, this was an evening hobby project that I kept being passionate about, but didn't know if it was ever going go “go somewhere”. At one point I resolved to actually finish and release a game. I began working on asset production. I put up a Steam page. Most important of all, I made a twitter account. Or roughly in that order of importance.

Here are a couple of screenshots of the new game, EVERGLORY, using the engine tech:

The title? Oh right, the title. The very last thing I worked on was enhancing the Python scripting API to add cooperative tasks. To test this out, I made a ghetto version of pong within the engine:

Then, I had a funny thought. Wow, I'm working on this for like 3 years and the “summit” of my progress is Pong! Something people code in like 30 minutes when they're first learning to program. And it only took me 3 years to get here. Ha! I get why people say, “don't write your own engines”. However, I know a lot of you guys will sympathize with me - it's a lot of fun, and it's incredibly fulfilling.

Anyways, this was just a blitz through a little under 3 years of progress. There's a tonne of stuff that I missed. Like the saving/loading system that took forever. The fiber system. All the “under the hood” changes and reworks that can't really be shown in GIFs or pictures.

If you guys are interested, the engine is fully open-source. Yes, it's OPEN SOURCE. Like, today. The code is here on GitHub.​ At this point it's well into 40,000+ SLOC of C99. And the aforementioned Pong Python script? You can check out pong.py for yourselves.

I haven't been blogging much about the game, but I wanted to share my journey, and brag about my code a bit. This one is an “into” episode but I'm planning to do some more, about the progress and a deep dive into the different engine systems. Let me know what you guys want to know about most of all.

I've already been putting up some blog videos on YouTube over the past few months, and I'm at 8 episodes so far:

I would say the devlogs are fairly technical. I go into more depths into the algorithms, the systems, and at times even the code.

That's it. That's the brief synopsis of how I spent like 3 years writing my own C RTS game engine. It actually is only now hitting me why people tell you not do this. When you spend too long on the first 90%, you don't budget enough time for the last 90% (i.e. the game!). Whatever. Some lessons have to be learned through your own life experience. I'm still fighting thought. The base-building mechanics are coming next. As are more blogs on this site.

Cheers,

Eduard

3 likes 2 comments

Comments

ZerohBeat

Congrats on your progress. Thank you for writing this, it was really interesting to read.

September 14, 2020 09:39 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement
Advertisement