RTS round-up: improving Construct through game development

24
Official Construct Post
Ashley's avatar
Ashley
  • 7 Dec, 2022
  • 1,969 words
  • ~8-13 mins
  • 2,846 visits
  • 5 favourites

In September I started part-time development of a real-time strategy (RTS) game in Construct using JavaScript coding. I've been posting regular updates on it on my own blog, but today I'm posting on the main Construct blog with a round-up of the development so far.

Goals

Construct's excellent block-based event sheets have always been a major part of what Construct is about, and they always will be too. However we wanted to highlight the impressive JavaScript coding capabilities of Construct, as they are powerful, exceptionally fast and highly competitive with other tools - and yet isn't as widely used as it could be. So this project aims to draw attention to what you can achieve using JavaScript coding in Construct.

Another of the key goals of the project was to improve Construct itself along the way, and in a couple of months a lot has been done to enhance Construct for everyone, even if you don't use coding! It's also helped drive Construct towards being a more professional development tool, and further demonstrated some of the amazing capabilities of JavaScript. Let's highlight some of the results of the project so far.

Gameplay

After a couple of months of part-time development, much of the focus has been on getting the overall architecture working, and so less work has been done on the gameplay itself. However you can try it out for yourself at CommandAndConstruct.com, where you can battle 1000 tanks!

Hundreds of tanks in combat, running smoothly and with a low bandwidth requirement.Hundreds of tanks in combat, running smoothly and with a low bandwidth requirement.

Partly thanks to the extraordinary performance of JavaScript, it runs perfectly smoothly even on a mobile phone with intense combat. It also uses a multithreaded architecture, with the browser, Construct runtime, and game server all running in their own threads, allowing making use of multicore CPUs to enhance performance even further. Read more about performance in the architecture blog post and in this blog post on optimizations.

It also works multiplayer allowing two players to battle over the Internet, with a unique approach to minimize bandwidth, using at most 50 KiB/s even with intense combat.

So while the game is just a big tank battle at the moment, it's got a pretty robust foundation. However there is still plenty more to do! There is not yet any network smoothing to compensate for laggy connections, and obviously there could be a lot more gameplay features too.

JavaScript code

The whole project file, including all the JavaScript code it uses, is available on GitHub.

The code makes good use of JavaScript modules (import and export) and classes, generally sticking to one class per module. This works out as a really nice way to organise large amounts of code. The project is up to 5000 lines of JavaScript and it still feels easy to manage.

The code also makes widespread use of private class features (e.g. properties named #foo) for encapsulation. These are a relatively new set of features in JavaScript - so much so that I've hardly used them before - but they also prove to be a great way to organize code, clearly separating internal details from methods used elsewhere.

There's also quite a lot of destructuring, which provide a handy way to return multiple values from a function. For example you can see here an example of getting both the X and Y co-ordinates from a single function call with const [x, y] = this.GetPosition();.

There's plenty more modern JavaScript used, such as generator functions, for-of loops, and Set. All of these features are so exceptionally well-optimized by modern JavaScript engine that, as noted in this blog, a loop using several of these features took just 37 CPU cycles per iteration. That's in the realm of nanoseconds.

My workflow has been to write all the code inside Construct's own code editor, and I'm also using GitHub Desktop to push and pull updates.

Overall the coding has worked out great! I know I'm biased, but it's genuinely been a joy to write and I've been pleasantly surprised at how well everything has worked together.

Construct improvements

One of the fun things about this project is any time I came across something that didn't look or work quite right, I switched over to Construct, fixed it, and then kept on going. There's plenty more to Construct than just JavaScript coding, and there were lots of changes that will benefit everyone using Construct, even if you use only event sheets. Let's take a look at some of the changes that were instigated by this project.

Folders in Project Bar

While not directly a result of working on this project, I knew beforehand that this project would need subfolders in the Project Bar to act like real folders in preview and export. Previously Construct put all files in the same folder regardless of their Project Bar organisation, and also lowercased their names (which we now call "flat" mode). This doesn't make much sense anyway and has caused some confusion over the years, and proper use of subfolders is what someone would expect of a professional tool. It's also important if you write a lot of JavaScript code, to make sure import statements work as you expect with folders - and this project uses lots of folders. So despite the complicated upgrade work, we improved Construct's use of subfolders to work more intuitively.

While working on this project in a beta release I also spotted a possible project corruption bug with the new folders mode, and made sure to fix it before it got to a stable release!

Source control & folder project improvements

For this project I've been using a folder-based project and pushing and pulling changes with GitHub Desktop. Using this workflow I noticed unnecessary file changes sometimes came up after saving the project, which clogged up the list of changes with things unrelated to the work I'd just done. This included the order and versions of the "usedAddons" entry in the project file, and writing the same file content causing a metadata-only change to come up in GitHub Desktop. I changed Construct to avoid causing these unnecessary changes, which makes using source control with Construct folder projects smoother for everyone.

A side-effect of avoiding unnecessary changes was it also improved performance when saving folder projects! Avoiding writing a file unnecessarily for source control also meant skipping the time it'd have taken to write the file.

Finally, when working with source control and reverting some changes, I found a Construct bug where sometimes saves would fail if an optional file unexpectedly went missing. I fixed the bug to make sure this doesn't stop you saving the project.

Multiplayer improvements

While investigating how to minimize bandwidth for this game, I had the idea to try compressing all the data sent over the network. Some browsers now have a built-in way to compress data with CompressionStream, which makes the compression bit easier. At first I was going to implement it just for the game, but then I thought, why not build it in to the Multiplayer object itself? It was quite tricky but that's what I did in the end, and so now all Construct multiplayer games benefit from automatic data compression, saving bandwidth without having to do anything!

Along the way I also discovered a bug with latency simulation that could incorrectly cause ordered messages to become unordered, so I fixed that too.

Misc other improvements

A few other additions, changes and fixes I made along the way include:

  • Adding a --construct-scale CSS variable to help scale content in HTML Element objects
  • Adding project properties 'Near distance' and 'Far distance', since zooming out a very long way can need a larger far distance, and this also allows better customisation of 3D Cameras
  • Improved how mouse and touch inputs are tracked in worker mode so inputs work more smoothly
  • Fixed a couple of bugs in the Layout View when using Z axis scale 'Regular'
  • Fixed a usability issue with new files not always being immediately visible after adding them to the Project Bar
  • Fixed network requests to project files not always working in preview with worker mode
  • While not a direct consequence of this project, the new tile randomization feature for Tiled Background was partially motivated by seeing the repetitive background pattern when zooming out a long way. (Tile randomization was also in turn a motivating factor to support WebGL 2 shader variants.)

Script API improvements

There were also a number of improvements specifically for JavaScript coding. That includes a range of new APIs, including a Multiplayer script interface (for the multiplayer part of the game), drawing APIs for Drawing Canvas (for the minimap), methods to set the cursor (for mouse control), runtime viewport properties, new "beforelayoutend" and "afterlayoutend" events, and a createWorker() helper method. All these were necessary for parts of the game code, but can also be used by anyone else using code in Construct.

The coding style I used for this project also regularly uses destructuring, such as getting both an X and Y co-ordinate from one function call. This works very well and also appears to be well-optimized in modern JavaScript engines, which motivated adding lots of Construct APIs in a similar style, such as setPosition() and getPosition().

Coding editor improvements

While you can use external editors like VS Code to edit code in folder projects, I stuck to Construct's own editor to make sure it worked robustly. I was particularly sensitive to autocomplete since it's so useful, and I ended up making several improvements for autocomplete. These included adding support for autocompleting public/private class fields and methods, fixing autocomplete in export declarations, improving suggestions to prefer matching case, and ensuring this.runtime and this.#runtime autocomplete the same as just runtime. I also updated CodeMirror to the latest version v5.65.10 which included a couple of bug fixes.

New scripting examples

Some of the new scripting examples in Construct are derived from either code used for this project, or other things added for this project. These include 'Handling multiple events' (based on a useful MultiEventHandler helper class), 'Imports & exports', 'Multiplayer scripting' and 'Tracking pointers' (based on the handy pattern of using a Map to track simultaneous pointers).

Summary

There were a range of improvements specifically for JavaScript coding, but also many that will benefit other Construct users. Notably Construct's handling of subfolders, folder projects and source control is now much improved, there are new options for styling HTML elements and controlling the view distance, and a number of bugs that weren't otherwise reported got fixed.

However this has only ever been a part-time project, and over the same time span, many, many more improvements were made in my usual day-to-day work on Construct, most of which centers on the non-programming features. So even if you don't think anything listed here is relevant to you, fear not - you can see much more that has been done in the changelogs on the releases page over the same time period. And making Construct a more professional tool that appeals to a wider audience will only benefit Construct in the long run!

Conclusion

There's still a lot more to be done on the game, but it's already helped make Construct a more professional and powerful tool. It demonstrates how robust and advanced JavaScript coding is in Construct, and it's also helping drive improvements to Construct along the way - for both coding and non-coding purposes - and all as just a part-time side project!

You can play the game right now at CommandAndConstruct.com, see all the code on GitHub, and go to Ashley's blog to read more on the past blog posts and find new ones when they're posted.

Interested in trying out JavaScript coding in Construct? Take the Get started with JavaScript guided tour for an easy introduction.

Subscribe

Get emailed when there are new posts!

  • 16 Comments

  • Order by
Want to leave a comment? Login or Register an account!
  • You quit saying simply all the time. Your writing has improved.

  • Thank you for explicitly starting with reaffirming Scirras commitment to event sheets to address the concerns of many C3 users.

    It might be a bit early for it but would you be willing to port the same game over to event sheets after you are done with the JS version (or a different game of similar complexity)?

    Obviously a port to events sheets could not support as many units and such, but would still create the opportunity for even more C3 improvements, but this time more focused on the visual scripting workflow.

    • I think a port to event system by Ashley isn't feasible, since it's only a part-time project to show "JS" capabilities of Construct 3.

      However, this game is open-source and the community doesn't have to wait for Scirra's permission to get involved with a port. I personally would volunteer to do a small portion of it and with a dozen more people, it will be possible.

      • You are missing the point, no one cares about the end product, it is about Ashley working with the engine, on a complex project, in the same way the majority of his customers do. With event sheets.

        Optimally he would actually run into every single possible problem users have experienced, so that he can find a way to fix, or improve them.

        Load more comments (4 replies)
  • This project has helped construct development considerably by the looks of it.

    Would be nice to try another project one day exclusively using the event blocks. Afterall, I suspect most users are using construct that way. Would undoubtedly uncover some improvements!

  • I am glad you also saw the need for extending the glsl version and extension support, very handy for creation of new effects. I hope you continue this project a lot of good has definitely come out of it for C3 and its users. One suggestion I have is take it all the way through to delivering on another platform (e.g. Steam, iOS App store or Google Playstore), so you also get the experience of what is required for that for a C3 export.

    • I agree with going all the way with publishing to feel what a struggle it is the moment we decide to release on any platform other than the Web. If Scirra hires an artist in the end to give the game a facelift, it could also become a good promotional channel for introducing Construct to potential customers.

  • Excellent idea! It's like doctors being forced to be patients in their own hospitals for an extended period. Cheers to whoever came up with this concept, it can only produce great things! Looking forward to watching this!

  • This sounds really cool

  • Amazing!!!

  • Looks good man!

  • Thank you.

    How to use "--construct-scale" CSS variable, please?