<<Previous Archive | Next Archive>>

JavaScript vs C++: Creating the same 3D game in both

I wrote the exact same first person shooter 3D game both in C++ and JavaScript. In this article, I am writing down my findings. Please skip the next indented paragraph if you are not interested in the background details.

A few years ago, when WebGL started to work in most browsers, I had the idea to write a first person shooter game in JavaScript and HTML. It was a crazy idea back then, but it worked, and the performance wasn't that bad (try it out yourself). I extended the game's code in my free time, and after a few years, a lot of features were added, and the game started to be fun.

Then, Electron arrived (basically it's a way to bundle your website in a package together with the Chrome browser and pretend you created a native app), and I thought:

"Woha! Why not make a real native app out of my WebGL game? I only put it into Electron and that's it!"

I did that, and Electron worked surprisingly well. Nice piece of software. But the result wasn't very convincing: Although I put a lot of effort into making the electron app feel like a native app instead of a HTML site, it had a lot of drawbacks like input lag, lack of hardware, 3D and fullscreen settings, bad working cursor locking and similar.

So I decided to rewrite the entire game in C++. Because - why not. And it shouldn't be that complicated: The JavaScript code of the game is based on the open source 3D engine CopperLicht (which I created), which has a similar API to the C++ 3D engine Irrlicht (which I created too), on which my game engine Framework CopperCube is based on anyway. So it wasn't that much work, I only had to rewrite the game logic. Everything else, from Window / UI / Collision / Font / Texture / Sound / Image / File handling etc was already there, with a very similar API.

The port was done within a handful of weekends and the game is now a native Win32 C++ program. You can try it if you like.

Comparison

So now, I have a rare possibility to compare the development of the same app written both in C++ and JavaScript:

Performance

This was the biggest surprise for me: The performance of both implementations is very comparable. Even the most CPU intensive parts, namely procedural generation of houses and the collision detection for the physics engine run at acceptable speed in JavaScript. And only about twice as slow as in the C++ version. Chrome's JavaScript optimization is really impressive. Unfortunately, the JavaScript version of the game feels to be much, much slower. See next why.

Control of the details

While I have full control of nearly everything in my C++ implementation, I need to rely on the browser for a lot of things in the JavaScript version of the game. And that's where the problem is. The procedural generation of the world is laggy in the JavaScript version, because some WebGL calls sometimes shortly freeze the browser. It is just a few milliseconds, but these aggregate and slow down the game very much. I wrote several workarounds solving some cases, only for other cases to appear, unfortunately. In C++, you have direct access to everything, so if a problem like this appears, you have much more ways to work around them.

The JavaScript version runs at a similar speed as the C++ version, at about 120 frames per second on my development system. But the JavaScript version *feels* very, very slow. Depending on your operating system and hardware, the browser behaves differently, and with a lot of combinations, input is laggy. Even if drawing the scene very fast, mouse input is lagging behind, and especially for a first person shooter game, the game feels very slow because of that. You have two methods of doing a "game loop" when using WebGL: requestAnimationFrame() and setInterval(). One version solves this issue sometimes on some systems, one version sometimes on other systems. It's quite frustrating.

There were similar problems, but they all had this in common: With JavaScript, you are depending on the implementation of the browser, which isn't always doing what you need, unfortunately. In C++, that's not a problem.

Development speed

I'm quite fluent in both JavaScript and C++, and I feel that both languages have about the same development speed. You have to type quite a bit more usually in C++ than in JavaScript, but C++'s type system makes it easier to find certain types of bugs earlier, usually. Thanks to modern browsers, debugging is as nice in JavaScript as it has been for nearly two decades in C++. For me, personally, both are languages with their weaknesses and strenghts, but after all, they are just tools to get the job done.

Recap

If you ever want to create a first person shooter 3D game and sell it as native game, I'd recommend not to do it in JavaScript/HTML/WebGL. It's fine for games in websites and prototypes but not to be treated as finished native product. At least not now. But who knows: in a few years, the situation will look better. I know a lot of people are creating 2D games successfully that way. And it seems to work nicely. But for me, 3D from the first person view hasn't worked yet.

For now, I'm developing my game further in C++. And hope to have it finished within the next months. You can follow its progress on its website, if you like.



First Windows .exe build

I uploaded the first build of the game for Windows here. The game now runs at about 150 FPS instead of the felt 10 FPS when it ran inside a browser.

I also re-created the gameplay video with that build, I think you can see now that it feels much, much smoother now:



Any feedback of the build would be welcome, it is just a 12 MB download.



Borders

I originally wanted the game to have no borders, and an unlimited area to explore, but for technical reasons (floating point precision), I now limited it to an area of about 120 square kilometers (or 75 square miles). The border looks like this:

It is a bit abrupt, but the only way to keep the player from climbing over it. I think 120 kmē is still enough to play the game and have fun.