<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <title>Advanced Construct</title>
    <link href="https://advancedconstruct.net/feed.xml" rel="self" />
    <link href="https://advancedconstruct.net" />
    <updated>2026-02-17T22:21:43+01:00</updated>
    <author>
        <name>Fodi</name>
    </author>
    <id>https://advancedconstruct.net</id>

    <entry>
        <title>One way to build Cordova Android projects with CLI tools</title>
        <author>
            <name>Fodi</name>
        </author>
        <link href="https://advancedconstruct.net/building-cordova-android-projects-with-cli/"/>
        <id>https://advancedconstruct.net/building-cordova-android-projects-with-cli/</id>
        <media:content url="https://advancedconstruct.net/media/posts/25/android-builds.png" medium="image" />
            <category term="Guides"/>

        <updated>2026-02-02T20:36:22+01:00</updated>
            <summary type="html">
                <![CDATA[
                        <img src="https://advancedconstruct.net/media/posts/25/android-builds.png" alt="Illustration: a green robot head with a plant sprouting from the top of it" />
                    <p class="msg msg--highlight ">Build &amp; sign Android APKs/AABs from Cordova projects on your machine using CLI tools only.</p>

                ]]>
            </summary>
        <content type="html">
            <![CDATA[
                    <p><img src="https://advancedconstruct.net/media/posts/25/android-builds.png" class="type:primaryImage" alt="Illustration: a green robot head with a plant sprouting from the top of it" /></p>
                <p class="msg msg--highlight ">Build &amp; sign Android APKs/AABs from Cordova projects on your machine using CLI tools only.</p>

<p>This is a short guide for seting up a CLI environment to turn Cordova projects into APK / AAB files locally. It's written for Windows, but can be adapted to Linux &amp; macOS as well. You can use it with Construct 3 Android exports, or any other Cordova project. The guide was written in <strong>February 2026</strong> and might not age well.</p>
<h2>Installing required build tools</h2>
<p>We need to install <strong>Node.js</strong>, <strong>OpenJDK</strong>, <strong>Android Command Line Tools </strong>and <strong>Gradle</strong> to build our Cordova Android project.</p>
<p>I like to use <a href="https://scoop.sh/">Scoop</a> (an open source CLI installer for Windows). After adding the <a href="https://github.com/ScoopInstaller/Extras">Extras</a> bucket, you can use this one liner to install all of the above:<br><br><code>scoop install nodejs-lts openjdk17 android-clt gradle-bin</code></p>
<p>Then install <strong>Cordova</strong> globally using the Node.js package manager:</p>
<p><code>npm install -g cordova</code><br><br>At this point we need a <strong>Cordova Android project</strong>. If you already have one, navigate to its directory and skip to the next section. If you're using Construct, go to Export, select Android and on the <strong>Cordova options</strong> screen select <strong>Cordova project</strong>.</p>
<p>If you just want to set up the build environment, create a blank Cordova Android project with the following commands:<br><br><code>cordova create blank-app</code><br><code>cd blank-app</code><br><code>cordova platform add android</code><code></code></p>
<h2>Installing Android SDK Build Tools</h2>
<p>At this point we can try building the project. It will probably download some dependencies and eventually fail and give you an error message, if you don't have the required version of Android Build Tools installed.<br><br><code>cordova build android</code><br><br>The error message will tell you to install a specific version of the Android Build Tools (eg. <code>35.0.0</code>), which should be available from the Android SDK manager. It's best to list all available packages first:<br><br><code>sdkmanager --list</code><br><br>Look for "build-tools" and copy the line that matches or a tiny bit superseeds the version number requested by Gradle. At the time of writing, <code>35.0.0</code> was required, <code>35.0.1</code> also worked, older versions and 36.x didn't. Proceed to install the preferred version (<code>35.0.0</code> in the example):<br><br><code>sdkmanager --install build-tools;35.0.0</code><br><br>To check what's currently installed with this command:<br><br><code>sdkmanager --list</code></p>
<p>If you need to uninstall a version, use this command template:</p>
<p><code>sdkmanager --uninstall build-tools;35.0.0</code></p>
<h2>Running builds</h2>
<p>After Android SDK Build Tools are installed, we can attempt to build again:<br><br><code>cordova build android</code><br><br>This time it will hopefully proceed to install the remaining build dependencies and eventually finish the build successfully. If you have a slow Internet connection, it'll take a while. Subsequent builds will be faster.</p>
<p>The previous command creates a debug build. If you want to make a signed production build, you can use the following command as a template, just replace the <code>???</code> parts with the relevant values:</p>
<p><code>cordova build android --release -- --keystore="???.jks" --keystoreType jks --storePassword=??? --password=??? --alias=???</code></p>
<p>You can use these comment as a part of automations - public deployment scripts, generating nightly builds for continuous testing, et cetera.</p>
<p>That's about it! Happy building :)</p>
            ]]>
        </content>
    </entry>
    <entry>
        <title>Procedural generation cheat sheet</title>
        <author>
            <name>Fodi</name>
        </author>
        <link href="https://advancedconstruct.net/procedural-generation-cheat-sheet/"/>
        <id>https://advancedconstruct.net/procedural-generation-cheat-sheet/</id>
        <media:content url="https://advancedconstruct.net/media/posts/24/proc-gen.png" medium="image" />
            <category term="Links"/>

        <updated>2025-12-28T19:53:09+01:00</updated>
            <summary type="html">
                <![CDATA[
                        <img src="https://advancedconstruct.net/media/posts/24/proc-gen.png" alt="" />
                    <p class="msg msg--highlight ">PRNGs, noise functions, chunk based generation, pathfinding, wave function collapse, shape packing and all that good stuff.</p>

                ]]>
            </summary>
        <content type="html">
            <![CDATA[
                    <p><img src="https://advancedconstruct.net/media/posts/24/proc-gen.png" class="type:primaryImage" alt="" /></p>
                <p class="msg msg--highlight ">PRNGs, noise functions, chunk based generation, pathfinding, wave function collapse, shape packing and all that good stuff.</p>

<p>If you're looking to use procedural generation in your game, you'll probably want to look into seeded PRNGs, noise functions, predefined chunk based generation, labyrinths, pathfinding, wave function collapse, shape packing, hexagonal maps, to just name a few.<br><br>Here are some of my favourite resources on the topic. Most of them are not specific for Construct developers, but all of them can be implemented in, or integrated into Construct (via JavaScript / TypeScript / WebAssembly).</p>
<h1>Construct 3's toolset</h1>
<p>If you're not a Construct dev, feel free to skip this section :)</p>
<ul>
<li>The <a href="https://www.construct.net/en/make-games/manuals/construct-3/plugin-reference/advanced-random">Advanced Random</a> plugin is a great start, it includes a seeded random number generator, a number of 2D &amp; 3D noise functions, permutation and probability tables, gradients and other useful utilities. There's an <a href="https://editor.construct.net/#open=noise-textures">official example for noise generation</a> on a Drawing Canvas, and I have a template project that has a <a href="https://github.com/fodi/construct-3-projects/raw/refs/heads/main/projectfiles/NoiseToTilemap.c3p">basic UI and displays the output on a Tilemap object</a>.<br>You can also set Advanced Random as your "default" seeded random number generator, so it's used for the <code>random</code> and <code>choose</code> expressions and for shuffling arrays.</li>
<li>If you're looking to generate smooth curves (eg. for a side-view 2D terrain), check out the <a href="https://www.construct.net/en/make-games/manuals/construct-3/plugin-reference/timeline-controller">Timeline controller</a> object and it's Ease expression. I have a <a href="https://github.com/fodi/construct-3-projects/raw/refs/heads/main/projectfiles/SmoothTerrainTemplate.c3p">basic demo using multiple easing curves for smooth terrain generation</a>.</li>
<li>Construct's Tilemap object type has <a href="https://www.construct.net/en/make-games/manuals/construct-3/interface/bars/tilemap-bar/tilemap-brush-editor">auto tiling &amp; patch brush support</a> which can be handy for generating terrains with good looking transitions.</li>
</ul>
<h1>Pseudorandom number generators (PRNGs)</h1>
<ul>
<li>If you're interested in the inner workings, read up on <a href="https://en.wikipedia.org/wiki/Pseudorandom_number_generator">pseudorandom number generators</a> in general, and don't stop at <a href="https://en.wikipedia.org/wiki/Linear_congruential_generator">linear congruential generators</a> :). Certain cases might need <a href="https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator">cryptographically secure PRNGs</a>. Thankfully, one is <a href="https://developer.mozilla.org/en-US/docs/Web/API/Crypto">built into JavaScript</a>.</li>
<li>Here are some <a href="https://github.com/bryc/code/blob/master/jshash/PRNGs.md">JavaScript implementations of seeded PRNGs and hashing functions</a>, all under public domain license. I usually use <code>xmur3</code> as the seed function and <code>mulberry32</code> as the PRNG.</li>
</ul>
<h1>Noise functions</h1>
<ul>
<li>If you're new to noise functions, learn the basics of <a href="https://en.wikipedia.org/wiki/Gradient_noise">gradient noise</a> and <a href="https://en.wikipedia.org/wiki/Value_noise">value noise</a>.</li>
<li>Wanna know how Perlin noise is generated? Check out <a href="https://www.youtube.com/watch?v=DxUY42r_6Cg">these</a> <a href="https://www.youtube.com/watch?v=ZsEnnB2wrbI">videos</a>.</li>
<li>Check out <a href="https://www.youtube.com/watch?v=COmtTyLCd6I&amp;list=PLFt_AvWsXl0eBW2EiBtl_sxmDtSgZBxB3">fall-off maps</a> for generating noise based landmass surrounded by water.</li>
</ul>
<h1>Wave function collapse</h1>
<ul>
<li><a href="https://github.com/mxgmn/WaveFunctionCollapse">This GitHub repo</a> is a great starting point, it has a detailed explanation on how WFC works and links to lots of implementations, including <a href="https://github.com/kchapelier/wavefunctioncollapse">a JavaScript one</a>.</li>
<li>My favourite videos on WFC are <a href="https://www.youtube.com/watch?v=2SuvO4Gi7uY">this</a> and <a href="https://www.youtube.com/watch?v=dFYMOzoSDNE">this</a>.</li>
</ul>
<h1>Other algorithms / libraries</h1>
<ul>
<li>The open-source <a href="https://ondras.github.io/rot.js/hp/">rot.js</a> library has a lot of features aimed to help roguelike development, including map generation and pathfinding, with hexagonal maps too. It has an excellent <a href="https://ondras.github.io/rot.js/manual/">interactive manual.</a></li>
<li><a href="https://en.wikipedia.org/wiki/Rectangle_packing">Rectangle</a> or <a href="https://en.wikipedia.org/wiki/Packing_problems">other shape packing</a> algorithms can be useful for room layouts, puzzle generation, placing pre-made or generated chunks on a larger level, etc. For a very neat JavaScript implementation of rectangle packing, check out the <a href="https://github.com/soimy/maxrects-packer/">Max Rects Packer</a> library.</li>
<li><a href="https://store.steampowered.com/app/239350/Spelunky/">Spelunky</a> has a very cool chunk-based level generator using solution paths and room templates. <a href="https://tinysubversions.com/spelunkyGen/">This article</a> sheds some light on how it works and also has a nice interactive demo.</li>
<li>Cellular automaton algorithms can also be utilised to generate mazes, caves and other structures. Notable libraries include <a href="https://sanojian.github.io/cellauto/">cellauto.js</a> and the previously mentioned <a href="https://ondras.github.io/rot.js/hp/">rot.js</a>.</li>
</ul>
<p> </p>
            ]]>
        </content>
    </entry>
    <entry>
        <title>My Construct Cookbook (2025)</title>
        <author>
            <name>Fodi</name>
        </author>
        <link href="https://advancedconstruct.net/my-construct-cookbook-2025/"/>
        <id>https://advancedconstruct.net/my-construct-cookbook-2025/</id>
        <media:content url="https://advancedconstruct.net/media/posts/23/cookbook.png" medium="image" />
            <category term="Productivity"/>
            <category term="Organization"/>
            <category term="Basics"/>

        <updated>2025-12-23T19:39:53+01:00</updated>
            <summary type="html">
                <![CDATA[
                        <img src="https://advancedconstruct.net/media/posts/23/cookbook.png" alt="Illustration, showing an open book with C-shaped pastries flying above it" />
                    <p class="msg msg--highlight ">Development principles, practices, patterns and anti-patterns as seen by a random Construct 3 developer (me).</p>

                ]]>
            </summary>
        <content type="html">
            <![CDATA[
                    <p><img src="https://advancedconstruct.net/media/posts/23/cookbook.png" class="type:primaryImage" alt="Illustration, showing an open book with C-shaped pastries flying above it" /></p>
                <p class="msg msg--highlight ">Development principles, practices, patterns and anti-patterns as seen by a random Construct 3 developer (me).</p>

<p>I've been using Construct 3 for about 5 years now. So far I've made over 30 jam games, countless experiments and prototypes as a hobbyist. Between 2023 and 2024 I built about a dozen smaller scope browser games for various clients, so I guess I can call myself a professional game developer, but I haven't done a "proper" game release on Steam or other big platforms. Although it will probably happen in the future, I have no short term plans to start working on one.</p>
<p>In this article I attempt to summarise the principles and practices I try to apply as a Construct developer. They seem to work well for me, your mileage may vary.</p>
<h2>Processes</h2>
<ul>
<li><strong>Prototype, clean up, repeat.<br></strong>I'm a big fan of <a href="https://www.youtube.com/watch?v=WtDPNoVGZIw">iterative development</a>, but if there's intention to grow the project into something sustainable, periodic clean-ups and refactors are key. Nobody nails everything for the first time, especially while experimenting with different things instead of following a well thought out "recipe". Even if you are, things might turn out to be duds that need to be removed or replaced and usually leave some spaghetti behind. Or hastily coded experiments turn out to be amazing and need to be kept around and built upon. Usually I do clean-ups every third or fourth session on most projects. This is also when I get rid of the sea of "todo" comments I made during development, to mark the bit that need to be refactored, fixed or optimised.</li>
<li><strong>Get to know the tools built by the community.<br></strong>Like <a href="https://advancedconstruct.net/construct-resources/">some of these for example</a>.</li>
<li><strong>Look for automation opportunities.<br></strong>I don't use a lot of automation, but I do have a script that pushes a fresh HTML5 build of a game to Itch.io (via <a href="https://itch.io/docs/butler/">butler</a>) and to Vercel, and another one that <a href="https://github.com/fodi/c3p2git/">converts my versioned .c3p files into git commits</a> and pushes them to GitHub, which I use as an off-site backup.</li>
<li><strong>Aid balancing and content creation workflows that take a long time.</strong><br>If you spend a lot of time balancing a game using variables, consider using "rule" files in an easy to edit format (eg. JSON – or JS, so you can have comments, trailing commas and includes). Rule files should contain the values that need to be balanced, ideally in a <a href="https://fodi.itch.io/free-version-survivors">nice structure</a>. With rule files, changes are easier to track and merge, and it can even act as a data source for generating change logs. A basic rule system can be extended to provide an in-game editor, URL parameter based overrides (eg. <code>?Player_Health=150</code>), portability (saving/loading to local storage, the file system or an API), just to mention a few. I have a basic rules-and-overrides system in <a href="https://github.com/fodi/construct-3-projects/raw/refs/heads/main/projectfiles/BlankTemplate.c3p">my "blank" project template</a>, because I used it quite a few times lately.</li>
<li><strong>Consider your dependencies.</strong><br>Relying on third party addons or services has advantages and disadvantages as well. In general I try to keep my dependencies as low as possible. Limitations fuel creativity anyway!</li>
<li><strong>Write todo lists and change logs.</strong><br>If you're a solo developer (or just prototyping on your own), why not store todo lists and change logs inside the project as files? I've started doing that recently. When I finish something from the todo list, I move it to the change log (with added details if needed), bang. You can even add them to your in-game menu, so players can track what changed and when.</li>
</ul>
<h2>Setup</h2>
<ul>
<li><a href="/setting-up-construct/">Set up the Construct editor</a> as a PWA to maximise screen space and take full advantage of the extra features (eg. file associations, application shortcut).</li>
<li>Avoid unnecessary frustration: prevent data loss &amp; keep "checkpoints" throughout development. I have an article on <a href="/backing-up-construct-projects/">how I back up my projects in Construct</a>; in short, it's one versioned c3p project file per build, stored in Dropbox, eventually converted to git commits and pushed to GitHub.</li>
<li>Learn <a href="/keyboard-mastery/">hotkeys and keyboard navigation</a>, which are especially useful in event sheets. It can be a very nice boost to productivity (and for me it's a lot less frustrating), especially if you're good touch typing. If not, <a href="https://www.keybr.com/">practice</a> :)</li>
<li>Get to know <a href="/finding-things-in-construct/">the features that help you get around in projects</a> and organize your program structure so you can take full advantage of them (more on that later).</li>
<li>Use a template project that has all the boilerplate you need every time (or almost every time). You can <a href="https://github.com/fodi/construct-3-projects/raw/refs/heads/main/projectfiles/BlankTemplate.c3p">download mine</a>, but it's very opinionated and might not make sense to you. In general, if you find yourself re-implementing the same thing for multiple projects (eg. I have one for <a href="https://github.com/fodi/construct-3-projects/raw/refs/heads/main/projectfiles/EightDirectionPlayer+SmoothCamera.c3p">top-down player movement and camera</a>), it's probably a good idea to turn it into a template, so you can hit the ground running faster when starting a new project.</li>
</ul>
<h2>Development patterns</h2>
<ul>
<li><a href="/using-global-names/">Using "global names"</a> and <a href="https://advancedconstruct.net/sheet-management/">sheet organization</a> are two topics I've covered in length, so let's see the other ones :)</li>
<li><strong>Use naming conventions for:</strong>
<ul>
<li><strong>Object types</strong><br>...so they are easier to find when typing their name (eg. <code>Player</code>, <code>PlayerCamera</code>, <code>PlayerHurtbox</code>). Optionally you can apply prefixes that relate to their "type" (eg. 3D object textures, 2.5D billboards, etc: <code>txGrass</code>, <code>txConcrete</code>, <code>bbPlayer</code>, <code>bbEnemy</code>, etc).</li>
<li><strong>Functions </strong>and <strong>custom actions</strong><br>Where it makes sense, and stick to it. Some random examples: an <code>onInput</code> custom action on the Player object that handles one-off button presses, an <code>onClick</code> custom action to handle mouse or touch interactions on a button, Enemy custom actions named <code>spawn</code> and <code>spawnGroup</code>, one spawns a single enemy instance, the other spawns a specified number of enemies in a formation.</li>
</ul>
</li>
<li><strong>Use folders to group elements of your project.</strong><br>Object types, event sheets, files, et cetera – especially if you have a lot of them, so they're easier to locate compared to the default alphabetised list.</li>
<li><strong>Use a level and/or game manager object instead of global variables where appropriate.</strong><br>Resetting global variables can be a pain if some of them need to be kept. Destroying and recreating a global object is easier and it also helps to separate level or game state variables from miscellaneous stuff.</li>
<li><strong>Use the keyboard as much as possible in event sheets.</strong><br>Switching between mouse and keyboards slows me down quite a bit and I prefer the keyboard for programming. Construct as excellent search and autocomplete coverage, you can create events, variables, functions, custom action, groups, code snippets without using your mouse.</li>
</ul>
<h2>Development anti-patterns</h2>
<p>Some of these are heavily influenced by the fact that I prefer keyboard navigation in event sheets and I use "find all references" a lot to get around a project.</p>
<ul>
<li><strong>Using string literals as identifiers.</strong><br>See my article on <a href="/using-global-names/">"global names"</a> for details.</li>
<li><strong>Using "On created" for objects that are dynamically spawned.</strong><br>On created is useful for initialising objects that are on a layout at start. For dynamically spawned objects, I usually have a <code>spawn</code> custom action on a, essentially a wrapper for a "Create object" system action which also handles or calls any initialisation.</li>
<li><strong>Using "On destroyed".</strong><br>I can imagine some rare cases where this could make sense, but using a custom action for handling destruction of objects has better readability, and you can search for references to the custom action too.</li>
<li><strong>Using groups solely for organisation, using long event sheets and nested groups.</strong><br>At the time of writing there's no keyboard shortcut to expand or collapse things (including groups) in the event sheet. I prefer splitting events into multiple event sheets that you can have open side by side.</li>
<li><strong>Using global constants / variables anywhere else but one of the "value" sheets.<br></strong>Having them grouped together by type in separate event sheets makes them easier to locate. These sheets act like a "table of contents", you can use "find all references" as a jump-off point to locate where they are used.</li>
<li><strong>Using extraneous object types for UI when grouping them together makes more sense.</strong><br>I use an instance variable named <code>role</code> instead. A random example: if I have a screen with 10 buttons that can each trigger a special skill of the player, I create a single object type (eg. <code>UI_Button_Skill</code>), and set the <code>role</code> instance variable on each with a different unique value. If a <code>UI_Button_Skill</code> object is clicked, a custom action (eg. <code>onClick</code>) is called with the <code>role</code> instance variable passed to it as a parameter. This custom action takes care of the validation (eg. if the skill is not on cooldown) and activates the skill if possible.</li>
<li><strong>Using the Audio object's "play" actions directly.</strong><br>Instead, I usually have a single <code>PlaySFX</code> custom action on the Audio object, which implements debouncing, sound effect variant randomization, an optional volume multiplier (for balancing the volume of sound effects). It can be extended to add positional audio or anything else you might need. Similarly, I usually have a <code>PlayBGM</code> custom action too, which handles changing the background music.</li>
<li><strong>Keeping "template" object instances for dynamically spawned objects anywhere else but a designated "object templates" layout (aka. "object repository", "repo", etc).</strong><br>Anything else can lead to ambiguity and thus is more error prone. If the instances are on a separate layout, they are easier to find and change. If the game has "static" level designs (made with the layout editor, as opposed to eg. procedurally generated ones), I use statically placed "spawner objects" on layouts that will dynamically spawn the real objects based on instances placed on the "object templates" layout. These spawners all "activate" at the start of the layout and spawn the required object type (optionally with a specified template), with hierarchy if needed.</li>
<li><strong>Using functions that are (mostly) doing something related to a single object type or family </strong>(unless a return value is needed, which is not possible with custom actions at the moment).<br>I usually have custom actions that initialize or spawn, update ("tick") and destroys a certain object type (or family), named <code>init</code> / <code>spawn</code> (depending on whether they are statically or dynamically spawned), <code>tick</code> (that sometimes calls several "sub custom actions", like <code>tick_input</code>, <code>tick_movement</code>, <code>tick_attack</code>, etc), <code>remove</code>/<code>kill</code> (which discards the object instance and takes care of anything else related to it, eg. adding a score).</li>
<li><strong>Using "every X seconds" for anything other then prototyping.</strong><br>In the long run Timers almost always work better. Just don't forget to add a "for each" condition for "on timer" actions if there's a chance multiple instances will finish their timers in the same tick.</li>
<li><strong>Using "Wait for previous actions".</strong><br>Although sometimes it can help make the code more concise, I almost always refactor it so it's no longer needed.</li>
<li><strong>Multiple events with the same top condition / trigger.</strong><br>I prefer a single event with sub events instead. I group my event sheets by the "type" of events contained within the, (eg. <code>eCollisions</code> for collision checks, <code>eSystem</code> for anything from the System category, et cetera - see <a href="https://github.com/fodi/construct-3-projects/raw/refs/heads/main/projectfiles/BlankTemplate.c3p">my "blank" template</a> for more examples). I find it easier to locate events this way.</li>
<li><strong>Using layer IDs.</strong><br>They are indices, so they can change when layers are added, removed or sorted. Instead, I use global constants with a string value matching the layer's name. It helps finding references, and provides an easy way to rename a layer (just change the layer name and the value of the constant).</li>
<li><strong>Using the boolean type.<br></strong>Since Construct doesn't allow passing a dynamic boolean value to functions or custom actions, I just use the numbers instead. I use two global constants (aka. "primitives") called <code>NO</code> and <code>YES</code> with the numeric values 0 and 1 respectively to keep things readable.</li>
<li><strong>Passing UIDs in function or custom action parameters instead of copying existing picks.<br></strong>If instances are already picked, why pick them again, right?</li>
<li><strong>Using the "trigger once" condition.</strong><br>For some reason it just screams spaghetti for me. I've never felt the need to use it.</li>
</ul>
<h1>Things I haven't (really) used in Construct</h1>
<p>These are features in Construct, that I have zero or almost zero experience with at the moment. There's a good chance I'll use some of them at one point, but I haven't had the need for them yet.</p>
<ul>
<li><strong>Timelines</strong><br>If I ever have to do advanced animation in-engine, I'm sure I'll check it out, but I haven't even tried this one.</li>
<li><strong>Flowcharts</strong><br> I'm pretty sure I'll explore this one in the future, it seems really useful for implementing certain types of mechanics.</li>
<li><strong>Signals</strong><br>I'm happy with custom actions and functions so far.</li>
<li><strong>Pure JavaScript or TypeScript projects</strong><br>I'm a web developer by trade (my JS is... okay), but I do almost everything with events. In some cases I sprinkle in some JS code or <a href="https://fodi.itch.io/kenney-jam-2021">glue</a> <a href="https://lasermagnet.itch.io/recoupage">in</a> <a href="https://fodi.itch.io/arucontrol-construct3">external</a> <a href="https://lasermagnet.itch.io/wordpile">libraries</a>. I landed at Construct because I much prefer the event-based system compared to writing actual code. This hasn't changed a bit.</li>
<li><strong>Steam integration</strong><br>I have no intention to release a game on Steam anytime soon.</li>
<li><strong>Networked multiplayer</strong><br>I made a few one-screen local multiplayer games though.</li>
</ul>
<p> </p>
<p>Hey, thanks for reading! Or scrolling all the way down :) I'll try my best to make an updated version of this next year. If you have any feedback, feel free to find and message me in the <a href="https://discord.gg/gZK4GndV">Construct Community Discord</a>!</p>
            ]]>
        </content>
    </entry>
    <entry>
        <title>Links for game developers</title>
        <author>
            <name>Fodi</name>
        </author>
        <link href="https://advancedconstruct.net/game-development-resources/"/>
        <id>https://advancedconstruct.net/game-development-resources/</id>
        <media:content url="https://advancedconstruct.net/media/posts/22/gamedev-links.png" medium="image" />
            <category term="Links"/>

        <updated>2025-10-16T21:57:54+02:00</updated>
            <summary type="html">
                <![CDATA[
                        <img src="https://advancedconstruct.net/media/posts/22/gamedev-links.png" alt="Illustration showing a post it note of a game controller stuck on a piece of paper and secured with a paper clip" />
                    <p>A collection of links for practising and future game developers. Engines and art software, learning resources, assets, project management tools, services, et cetera.</p>

                ]]>
            </summary>
        <content type="html">
            <![CDATA[
                    <p><img src="https://advancedconstruct.net/media/posts/22/gamedev-links.png" class="type:primaryImage" alt="Illustration showing a post it note of a game controller stuck on a piece of paper and secured with a paper clip" /></p>
                <p>A collection of links for practising and future game developers. Engines and art software, learning resources, assets, project management tools, services, et cetera.</p>

<div class="post__toc">
<h3>Table of Contents</h3>
<ul>
<li><a href="#j-t-kmotorok">Game engines</a>
<ul>
<li><a href="#kezd-kre-optimaliz-lt-cuccok">Recommended for beginners</a></li>
<li><a href="#a-nagy-nevek">The big three</a></li>
<li><a href="#m-g-n-h-ny-aj-nl-s">A few more recommendations</a></li>
</ul>
</li>
<li><a href="#mcetoc_1imqelhma227">Assets (2D / 3D graphics, sounds, music)</a></li>
<li><a href="#mcetoc_1ilgrsioa1k">Project management &amp; collaboration</a></li>
<li><a href="#mcetoc_1imqelhma222">Learning resources</a></li>
</ul>
</div>
<h2 id="j-t-kmotorok">Game engines</h2>
<h3 id="kezd-kre-optimaliz-lt-cuccok">Recommended for beginners</h3>
<ul>
<li><a href="https://www.construct.net">Construct 3</a>: a freemium 2D engine with some 3D features, runs in the browser (and works offline too). It has a no-code event system, or you can develop in JavaScript or TypeScript. The free version is quite limited, but it's good for getting a general feel of the engine. The full version requires a subscription.</li>
<li><a href="https://gdevelop.io">GDevelop</a>: A free 2D / limited 3D engine that is fairly similar to Construct. It has some optional paid features.</li>
<li><a href="https://gamemaker.io">GameMaker</a>: this 2D engine has been along for a long time and it's free for non-commercial use. For commercial projects, you need to buy a very fairly priced license (one-time purchase).</li>
<li><a href="https://microstudio.dev">microStudio</a>: Open source 2D engine, has a browser based and downloadable version too. Supports many programming languages, including its own Lua-like microScript language, as well as Lua, Python, Javascript, and Typescript.</li>
<li><a href="https://www.gbstudio.dev">GB Studio</a>: open source development environment for making GameBoy or GameBoy Color games, that can run on real hardware, emulators or in the browser. It has a block based no-code programming interface.</li>
<li><a href="https://ctjs.rocks">Ct.js</a>: open source 2D engine and development environment. Has a block based no-code interface called Catnip, or you can use JavaScript to code your game.</li>
<li><a href="https://twinery.org">Twine</a>: open source engine for making interactive fiction games. Runs in the browser, requires no coding, but it can be extended with CSS and JavaScript.</li>
<li><a href="https://bitsy.org">Bitsy</a>: open source 2D no-code engine for making retro games.</li>
<li><a href="https://whimtale.com/" target="_blank" rel="noopener noreferrer">Whimtale</a>: free 2D no-code engine inspired by Bitsy. It has browser based and downloadable versions as well.</li>
<li><a href="https://rpginabox.com">RPG in a Box</a>: very fairly priced 2D/3D engine and editor primarily for making RPG games. It has a no-code interface with optional scripting support with its own Bauxite language.</li>
<li><a href="https://www.rpgmakerweb.com/">RPG Maker</a> MZ / MV / VX / XP / etc: a family of 2D no-code engines for making RPGs. Requires a one time purchase, but most versions have 30 day free trials available.</li>
<li><a href="https://store.steampowered.com/app/1066860/RPG_Paper_Maker/" target="_blank" rel="noopener noreferrer">RPG Paper Maker</a>: open source 2.5D engine inspired by RPG Maker. Its free for non-commercial use, making commercial games requires a fairly priced lifetime license.</li>
<li><a href="https://www.puzzlescript.net/index.html">PuzzleScript</a>: open source brower based 2D engine and scripting language for primarily for making retro puzzle / action games.</li>
<li><a href="https://www.adventuregamestudio.co.uk/">Adventure Game Studio</a>: an open source game engine actively developed since 1997, primarily for making point-n-click adventure games.</li>
</ul>
<h3 id="a-nagy-nevek">The big three</h3>
<ul>
<li><a href="https://godotengine.org">Godot</a>: popular open source 2D/3D engine. Can be programmed via its own Python-like GDScript language, or C#.</li>
<li><a href="https://unity.com">Unity</a>: popular commercial 2D/3D engine, with a massive community and array of learning resources. Can be programmed via a node based no-code interface, or C#. It has a free version and multiple subscription based plans with advanced features.</li>
<li><a href="https://www.unrealengine.com">Unreal Engine</a>: free engine primarily for making 3D games. Can be programmed via Blueprint, a node based no-code interface, or C++.</li>
</ul>
<h3 id="m-g-n-h-ny-aj-nl-s">A few more recommendations</h3>
<ul>
<li><a href="https://love2d.org">LÖVE</a>: open source 2D engine based on the Lua language.</li>
<li><a href="https://www.lexaloffle.com/pico-8.php">PICO-8</a>: commercial (but very fairly priced) Lua based 2D engine and "fantasy console" for making retro games.</li>
<li><a href="https://tic80.com">TIC-80</a>: open source engine and "fantasy console", similar to PICO-8.</li>
<li><a href="https://morgan3d.github.io/quadplay/">quadplay✜</a>: open source engine and "fantasy console", which can be programmed using its own language called PyxlScript.</li>
</ul>
<h2 id="mcetoc_1imqelhma227">Assets (2D / 3D graphics, sounds, music)</h2>
<ul>
<li><a href="https://itch.io/game-assets">Itch.io</a>: an asset marketplace with tons of free and commercial 2D/3D art,  sound effects and music.</li>
<li><a href="https://opengameart.org/">OpenGameArt</a>: free and mostly permissively licensed asset repository.</li>
<li><a href="https://kenney.nl/">Kenney</a>, aka. <a href="https://www.assetjesus.com/">Asset Jesus</a>: an incredible collection of hand made CC0 licensed 2D and 3D assets, music, sound effects.</li>
<li><a href="https://quaternius.com/">Quaternius</a>: CC0 licensed low poly 3D models.</li>
<li><a href="https://poly.pizza/">PolyPizza</a>: free and mostly permissively licensed 3D low poly asset repository.</li>
<li><a href="https://www.sharetextures.com/">Share Textures</a>: a collection of CC0 licensed textures.</li>
<li><a href="https://polyhaven.com/">Poly Haven</a> and <a href="https://ambientcg.com/">ambientCG</a>: a collection of CC0 licensed 3D models and textures.</li>
<li><a href="https://99sounds.org/sounds/">99Sounds</a>: a collection of free to use sound effects.</li>
<li><a href="https://lospec.com/">Lospec</a>: a repository of pixel art palettes and tutorials.</li>
<li><a href="https://incompetech.com/music/royalty-free/music.html">Incompetech</a>: CC-BY licensed music by Kevin MacLeod.</li>
<li><a href="https://freesound.org/">Freesound</a>: free and mostly permissively licensed sound effect repository. Downloading requires a free account.</li>
<li><a href="https://www.fontspace.com/">FontSpace</a> and <a href="https://fonts.google.com/">Google Fonts</a>: free and mostly permissively licensed fonts.</li>
<li><a href="https://gwfh.mranftl.com/fonts">Google Webfonts Helper</a>: alternative Google Fonts frontend for downloading fonts in specific formats (woff, woff2, ttf, otf, eot, svg).</li>
<li><a href="https://pixabay.com/" target="_blank" rel="noopener noreferrer">Pixabay</a>: a repository of free nad permissively licensed 2D, 3D, vector graphics, sound and music assets.</li>
<li><a href="https://game-icons.net/">Game-icons.net</a>: a huge collection of two-color SVG icons available under CC-BY 3.0 license.</li>
<li><a href="https://www.drpetter.se/project_sfxr.html">sfxr</a>, <a href="https://www.bfxr.net/">bfxr</a>, <a href="https://jfxr.frozenfractal.com/">jfxr</a>, <a href="https://chr15m.itch.io/jsfxr">jsfxr</a>: open source sound effect generators</li>
<li><a href="https://sfbgames.itch.io/chiptone">Chiptone</a>: free sound effect synth</li>
<li><a href="https://labbed.net/software/labchirp/">LabChirp</a>: free cross-platform sound effect synth</li>
</ul>
<h2 id="mcetoc_1ilgrsioa1k">Project management &amp; collaboration</h2>
<ul>
<li><a href="https://trello.com/">Trello</a>: kanban-style freemium project management tool.</li>
<li><a href="https://miro.com/">Miro</a>: "infinite board" type freemium collaboration tool.</li>
<li><a href="https://www.notion.com">Notion</a>: freemium tool for collaboration.</li>
<li><a href="https://obsidian.md/">Obsidian</a>, <a href="https://logseq.com/">Logseq</a>: popular open source apps for knowledge bases, planning, note taking, documentation, et cetera.</li>
</ul>
<h2 id="mcetoc_1imqelhma222">Learning resources</h2>
<ul>
<li><a href="https://www.redblobgames.com/">Red Blob Games</a>: free interactive visual explanations of math, algorithms and game mechanics.</li>
<li><a href="https://www.gameuidatabase.com/">Game UI Database</a>: game UI reference for designers.</li>
<li><a href="https://www.bscotch.net/podcast">Coffee with Butterscotch</a>: a gamedev comedy podcast by Butterscotch Shenanigans, an indie game studio, equally hilarious and insightful.</li>
<li><a href="https://saint11.art/blog/pixel-art-tutorials/">Pixel Art Tutorials</a>: incredible animated pixel art tutorials by Pedro Medeiros (Saint11).</li>
<li><a href="https://www.omnicalculator.com/math">Omnicalculator</a>: learning resource and interactive calculators.</li>
<li><a href="https://deepnight.net/games/game-feel/">Game Feel Demo</a> by Deepnight Games: an interactive demonstration of a lot of ways to add "juice" to a game.</li>
<li><a href="https://gameprogrammingpatterns.com/">Game Programming Patterns</a> (Robert Nystrom): free resource on video game programming practices.</li>
<li><a href="https://matthias-research.github.io/pages/tenMinutePhysics/index.html">Ten Minute Physics</a>: excellent explainers on various 2D and 3D physics simulations of rigid bodies, soft bodies, fire, fluids, cloth, et cetera.</li>
</ul>
<h1>Marketing tools</h1>
<ul>
<li><a href="https://bluepinstudio.com/tools/">Blue Pin Studio's tools</a>: awesome free market research tools using data scraped from Steam</li>
<li><a href="https://app.sensortower.com/vgi/">Video Game Insights</a>: Steam market research tool</li>
</ul>
<p>If you like this list, be sure to check out a similar <a href="https://docs.google.com/document/d/1IinnBt7pj2dnydrdsHC_4t9p4tq4QIjkQ75HJot7gz0/">collection by clovelt</a>, which also contains resources on business, marketing and publishing.</p>
            ]]>
        </content>
    </entry>
    <entry>
        <title>Links for Construct developers</title>
        <author>
            <name>Fodi</name>
        </author>
        <link href="https://advancedconstruct.net/construct-resources/"/>
        <id>https://advancedconstruct.net/construct-resources/</id>
        <media:content url="https://advancedconstruct.net/media/posts/21/construct-links.png" medium="image" />
            <category term="Links"/>

        <updated>2025-10-12T22:38:06+02:00</updated>
            <summary type="html">
                <![CDATA[
                        <img src="https://advancedconstruct.net/media/posts/21/construct-links.png" alt="Illustration showing an &quot;under construction&quot; barrier and links of a chain" />
                    <p>If you're a Construct developer, check out these neat resources made by the community. Tutorials, tips, optimisation techniques, 3rd party tools, et cetera.</p>

                ]]>
            </summary>
        <content type="html">
            <![CDATA[
                    <p><img src="https://advancedconstruct.net/media/posts/21/construct-links.png" class="type:primaryImage" alt="Illustration showing an &quot;under construction&quot; barrier and links of a chain" /></p>
                <p>If you're a Construct developer, check out these neat resources made by the community. Tutorials, tips, optimisation techniques, 3rd party tools, et cetera.</p>

<h2>Learning resources</h2>
<ul>
<li><a href="https://thinkery.co.uk/u/james/construct3">Construct 3 tips, best practices &amp; notes by James</a></li>
<li><a href="https://fed-4.gitbook.io/c3-cheat-sheets/">Construct 3 cheat sheets by Federico Calchera</a></li>
<li><a href="https://www.construct.net/en/tutorials/performance-tips-community-3247">Performance tips by Federico Calchera</a></li>
<li><a href="https://howtoconstructdemos.com/">HowToConstruct.com templates &amp; demos</a></li>
<li><a href="https://www.construct.net/en/users/198994/skymen/tutorials">Construct 3 tutorials by Skymen</a></li>
<li><a href="https://www.youtube.com/@XanderwoodGameDev">Construct 3 video tutorials by Xanderwood</a></li>
<li><a href="https://www.youtube.com/@gamedesignwithreilly">GameDesign With Reilly (video tutiorials)</a></li>
<li><a href="https://www.youtube.com/@FoozleCC/videos">Construct 3 tutorials and showcase videos by Foozle</a></li>
</ul>
<h2>Tools</h2>
<ul>
<li><a href="https://github.com/skymen/construct-crawler">Construct Crawler by Skymen</a>: cross platform app for manipulating Construct projects</li>
<li><a href="https://pipelab.app/">Pipelab by Armaldio</a>: freemium cross platform app for automating deployment of Construct projects</li>
<li><a href="https://github.com/fodi/c3p2git/">c3p2git by Fodi</a>: Windows CLI utility for turning c3p project files into Git commits</li>
<li>Sprite font generators
<ul>
<li><a href="https://stmn.itch.io/font2bitmap">Font To Bitmap by stmn</a> (browser based)</li>
<li><a href="https://spritetype.netlify.app/">SpriteType by Dokse</a> (browser based)</li>
<li><a href="https://www.construct.net/en/forum/game-development/tools-and-resources-27/sprite-font-generator-v3-64038">Sprite Font Generator by blackhornet</a> (Windows app)<a href="https://easings.net/"></a></li>
</ul>
</li>
<li><a href="https://fodi.github.io/construct-3-projects/ConstructColorConverter/">Construct Color Converter by Fodi</a>: batch convert hexadecimal RGB palettes into Construct 3 color values &amp; global constant declarations</li>
<li><a href="https://store.pixelperfectstudio.mx/shop/">Construct 3 addons by Pixel Perfect Studios</a></li>
<li><a href="https://skymen.github.io/construct-shader-graph/">Construct Shader Graph by Skymen</a>: a node based visual shader editor with WebGL 1, WebGL 2 and WebGPU support.</li>
<li><a href="https://gwfh.mranftl.com/fonts">Google Webfonts Helper</a>: for downloading free font files from Google Fonts in any format (including TTF)</li>
<li><a href="https://comigo.itch.io/placeholder-gen">CoMiGo's Placeholder Generator</a>: a simple, free and engine-agnostic placeholder sprite generator, great for grayboxing.</li>
<li><a href="https://github.com/bryc/code/blob/master/jshash/PRNGs.md">Javascript PRNGs</a>: public domain code for various seed generators, seeded PRNGs and hashing functions. Can be useful for making games with procedurally generated content.</li>
<li><a href="https://easings.net/">Easing Function Cheat Sheet</a>: although not specific to Construct, it's displays all easing functions available in Construct's Tween behaviour in a visual way (with animations as well).</li>
<li><a href="https://range-input-css.netlify.app/">Range Input (aka. "Slider bar") CSS generator</a>: define default styles for the slider bar object (which also make sure it looks the same on all platforms and browser engines)</li>
</ul>
<h2>Services</h2>
<ul>
<li>Free(mium) webhosting services for HTML5 builds:<br><a href="https://itch.io/">Itch.io</a>, <a href="https://gamejolt.com/">GameJolt</a>, <a href="https://docs.github.com/en/pages" style="font-size: inherit;">GitHub Pages</a>, <a href="https://docs.gitlab.com/user/project/pages/" style="font-size: inherit;">GitLab Pages</a>, <a href="https://pages.cloudflare.com/" style="font-size: inherit;">Cloudflare Pages</a>, <a href="https://vercel.com/" style="font-size: inherit;">Vercel</a>, <a href="https://www.netlify.com/">Netlify</a>, <a href="https://surge.sh/">Surge</a></li>
<li>Game porting services:<br><a href="https://mp2.dk/">MP2 Games</a>, <a href="https://ratalaikagames.com/">Ratalaika Games</a>, <a href="https://www.seaven-studio.com/">Seaven Studio</a></li>
</ul>
            ]]>
        </content>
    </entry>
    <entry>
        <title>Sheet management</title>
        <author>
            <name>Fodi</name>
        </author>
        <link href="https://advancedconstruct.net/sheet-management/"/>
        <id>https://advancedconstruct.net/sheet-management/</id>
        <media:content url="https://advancedconstruct.net/media/posts/20/event-sheets.png" medium="image" />
            <category term="Organization"/>

        <updated>2025-09-16T19:06:36+02:00</updated>
            <summary type="html">
                <![CDATA[
                        <img src="https://advancedconstruct.net/media/posts/20/event-sheets.png" alt="Illustration: a chicken sitting on a bunch of books" />
                    <p class="msg msg--highlight ">An article on function sheets, action sheets, value sheets, top level sheets... oh, and event sheets of course. And emojis.</p>

                ]]>
            </summary>
        <content type="html">
            <![CDATA[
                    <p><img src="https://advancedconstruct.net/media/posts/20/event-sheets.png" class="type:primaryImage" alt="Illustration: a chicken sitting on a bunch of books" /></p>
                <p class="msg msg--highlight ">An article on function sheets, action sheets, value sheets, top level sheets... oh, and event sheets of course. And emojis.</p>

<p>What is an event sheet? A sheet that contains events, right? But what if there is a sheet that only has global variables or constants? Or one containing functions exclusively? Or custom actions, for that matter.</p>
<p>In the last few years I've been using a system that involves having top level event sheets and four subfolders, one for sheets with custom actions, one for sheets with functions, one for sheets with global values (variables and constants) and one for actual event sheets. The subfolders are named <strong>Actions</strong>, <strong>Events</strong>, <strong>Functions </strong>and <strong>Values</strong>, all sheets in the subfolders are prefixed with the letters "a", "e", "f" and "v" respectively, so it's easier to navigate the open tabs.</p>
<p>In this article I go through the details of this setup (with some sidenotes here and there). I have a <a href="https://github.com/fodi/construct-3-projects/raw/refs/heads/main/projectfiles/BlankTemplate.c3p">blank project template that you can download</a> with the folders and most commonly used event sheets (most of them are empty, prefixed with an underscore).</p>
<p>A slightly weird thing I also like to do is to add emojis at the end of event sheet names. They act a bit like icons, so when I have a lot of tabs open, it's easier for me to find the one I'm looking for. Emojis also signify the fact that the tab is an event sheet, and not a layout.</p>
<p class="msg msg--info"><strong>Sidenote</strong><br>If you put emojis in the names of Construct 3 event sheets (or other primitives, eg. objects) and save your project as a folder instead of a <code>c3p</code> file, make sure that your file system and apps that handle your project folders are okay with emojis in the file names. For example, Dropbox isn't  - at the time of writing, it refuses to sync files with emojis in their names. Using <code>c3p</code> project files inside a Dropbox folder is a workaround for this issue, since those are really <code>zip</code> files, which handle emoji filenames in them without problems.</p>
<p>Okay, let's dive in!</p>
<h2>Top level sheets</h2>
<p>My rule is to only have sheets on the top level if they are assigned to at least one layout. When I'm prototyping, I usually start dumping everything in a top level event sheet, then organize it later by moving everything to other sheets. I like to go fast and do periodic clean-ups after things are in a working state.</p>
<p>For simpler layouts (eg. the crappy low effort menus that I usually make for jam games and prototypes), I just put all events in a top level sheet, since there aren't too many anyway.</p>
<p>For complex ones (like levels) I create a top level event sheet (eg. <code>Level 🗺️</code>) and only put event sheet includes in it, nothing else. There's no need to include sheets that only contain functions, global variables, constants or custom actions, as those are all globally available by default. <span style="text-decoration: underline;">Actual</span> event sheets do have to be included in top level event sheets in order to run.</p>
<h2>Actions folder</h2>
<p>This folder is for sheets with custom actions only, one sheet per object type (or family). The sheet's names match the object or family name, prefixed with the letter "a" (short for "action") and suffixed with an emoji, eg. <code>aPlayer 🧑</code>, <code>aEnemy 👾</code>, etc.</p>
<p>Common custom actions include <code>spawn</code> (which spawns an instance of its object type or family) and <code>tick</code> (which is called in an every tick event and does various things with the instance). If a game has players and/or enemies with health, I usually have one called <code>changeHealth</code> on the object type which is called when an instance is damaged or healed. This action takes care of changing the health instance variable, doing audio and visual feedback based on the change, checking if health is zero and doing the destruction of the instance, if needed.</p>
<h2>Events folder</h2>
<p>This folder is for <span style="text-decoration: underline;">actual</span> event sheets, only containing events (sometimes enclosed in groups). These sheets have to be included in at least one top level event sheet in order to work (unlike <strong>function</strong>, <strong>action</strong> and <strong>value</strong> sheets). I never put any global variables, constants, custom actions or functions in these sheets.</p>
<p>Sheets in this folder are named according to the kind of conditions (mostly triggers) that are in them. Here are the ones I use most frequently:</p>
<ul>
<li><code>eCollisions 💥</code> for "On collision with another object" events only. I used to put overlap checks in here too, but nowadays I usually do those inside <code>tick</code> custom actions instead (and other non-trigger events too). I find it very handy to have all collision checks in a single sheet.</li>
</ul>
<p class="msg msg--info"><strong>Sidenote<br></strong>When setting up collision checks, I try to set the first object to the one that (probably) has fewer instances in a layout, and the second to the one that (probably) has more. I read somewhere that this has better performance. Also don't forget to set a reasonable collision cell size for your layout, the default is usually way too big.</p>
<ul>
<li><code>eCreated ✨</code> for "On created" events only, and only for object types / families that have instances on a layout at start, not ones that are dynamically spawned during runtime. In the former case, I usually make an <code>init</code> custom action which initializes the object and call it from the "On created" event.<br>If an object type only spawns dynamically during runtime, I usually have a <code>spawn</code> custom action for it, which takes care of the spawning and any initialization as well. I keep at least one instance of dynamically spawned objects is in a "repository layout" - nowadays I name it <code>@ Templates</code>. Most official examples have one called <code>ObjectRespository</code>.</li>
<li><code>eTimers ⏰</code> for "On timer" events only.</li>
</ul>
<p class="msg msg--info"><strong>Sidenote<br></strong>Don't forget to add a "for each" to "On timer" events if there's a chance that multiple instances of the same object might finish their timer in the same tick. If that happens and there's no "for each", only one instance will be picked by the "On timer" trigger, which is a bit of a footgun, if you ask me (by the way I'm also planning an article on Construct 3 footguns). That said, there's a <a href="each" target="_blank" rel="noopener noreferrer">warning in the official docs</a> about this behaviour.</p>
<ul>
<li><code>eTweens 🌓</code> for the Tween behaviour's "On finished" events only. As far as I know, there's no need to "for each" those like Timers.</li>
<li><code>eInput_Global 🔘</code> and <code>eInput_Level 🕹️</code> for anything that is input related: keyboard, mouse, touch and game pad events including triggers and non-triggers (eg. "is down"). <code>eInput_Global 🔘</code> contains input events which have to run on multiple or all layouts (eg. toggling full screen or restarting the whole game, etc). This also means that it's included in multiple top level event sheets. <code>eInput_Level 🕹️</code> only has input handling related to the level and I usually have events split into multiple groups: one for player movement (or one for each player in a local multiplayer game), one for UI, one for developer cheats and so on.</li>
<li><code>eSystem ⏱️</code> exclusively for events of the "System" category. Usually it contains a single "On start of layout" event and a single "Every tick" event with multiple function and custom action calls. Any other triggers from the "System" category also go in this sheet, eg. "On signal", "On canvas snapshot, "On save complete", etc.</li>
</ul>
<p>Here are some less frequently used ones:</p>
<ul>
<li><code>eAJAX 📡</code> for trigger events of the AJAX object, like "On completed" and "On error".</li>
<li><code>eAnimations 🎞️</code> for animation related trigger events, like "On finished" and "On frame changed".</li>
<li><code>eMovement 🏃</code> for movement behaviour related triggers, like "On landed" for the Platform behaviour, "On step" for the Bullet behaviour, "On target acquired" for the Turret behaviour, et cetera.</li>
</ul>
<h2>Functions folder</h2>
<p>This is for sheets containing functions only.</p>
<p>There's usually one called <code>fUtilities 🧰</code>, which contains a handful of frequently used math functions which calculate and return values like <code>volumePercentToDb</code> (for converting a 0-100 percent value to decibels for Audio object actions), <code>distance3D</code> (like the system expression <code>distance</code> but for 3D coordinates), <code>expDecay</code> (the function I usually use <a href="https://www.youtube.com/watch?v=LSNQuFEDOyQ" target="_blank" rel="noopener noreferrer">instead of</a> <code>lerp</code>).<br>I frequently have some helper functions like <code>toggleFullscreen</code> which requests or cancels full screen mode and <code>toggleLayer</code> which simultaneously toggles the visibility and interactivity of a given layer.</p>
<p>In almost all projects I have a sheet called <code>fLevel 🎬</code>, which contains "game life cycle" functions like <code>initLevel</code>, <code>endGame</code> and other game-specific functions that do a lot of things with a lot of objects.</p>
<p>In some projects I used to have a sheet called <code>fAudio 🎵</code> for functions like <code>playSFX</code> and <code>playBGM</code> to play sound and music according to the current volume settings, with optional debouncing and random variations for sound effects. Nowadays I create an <code>aAudio 🎵</code> sheet in the Actions folder and put similarly named custom actions on the Audio object.</p>
<p class="msg msg--info"><strong>Sidenote</strong><br><a href="https://github.com/fodi/construct-3-projects/raw/refs/heads/main/projectfiles/BlankTemplate.c3p">My blank project template</a> also includes the <code>fRules 📜</code> sheet, with a very specific set of functions, for loading a default rule set for the game from a JSON file and allowing URL parameter based rule overrides to help with balancing / testing. It's a whole thing, I'll probably write an article about it at one point.</p>
<h2>Values folder</h2>
<p>The <code>Values</code> folder is for sheets containing only global variables or constants. I have a fixed set of 4 sheets in this folder:</p>
<ol>
<li><code>vPrimitives 🍞</code> containing global constants for a handful of "generic" values and characters that I use frequently in expressions:
<ul>
<li><code style="font-weight: var(--font-weight-normal);">NOTHING</code><span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);"> with the numeric value of </span><code style="font-weight: var(--font-weight-normal);">-1</code><span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);">, which is the next best thing to null (which is not a thing in Construct). Eg. if I have an instance variable for storing object UIDs, I use this to "clear" its value (or to check if it's set or not), since <code>-1</code> not a valid UID. Some system expressions </span><span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);">also return </span><code style="font-weight: var(--font-weight-normal);">-1</code><span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);"> (eg. <code>find</code> when there are no results), so it comes handy for those too.</span></li>
<li><code>NO</code> and <code>YES</code>: with the numeric values <code>0</code> and <code>1</code> respectively. I almost never use booleans in my projects, instead I use numbers with these values. My main beef with booleans in Construct 3 is that I can't pass a dynamic value to a function or custom action with a boolean parameter. When calling one, I have to use a checkbox to either pass true or false, I cannot pass the result of an expression or a variable. Because of this I refrain from using boolean variables in functions and custom actions, and use the numbers 0 and 1 instead.</li>
<li><code>EMPTY</code>, which is an empty string, the <code>NOTHING</code> of string variables. I use it to clear a string variable or to check if it's empty.</li>
<li><code>COMMA</code>, <code>UNDERSCORE</code>, <code>SPACE</code> and <code>DOT</code>: single character string constants that contain a comma, an underscore, a space and a dot (or full stop, period, etc) respectively. I use <code>DOT</code> when writing JSON object path expressions, the rest are for dealing with comma / underscore / space delimited strings (aka. "cheapskate arrays"), eg. with <code>tokenat</code> and <code>tokencount</code>.</li>
</ul>
</li>
<li><code style="font-weight: var(--font-weight-normal);">vNames 🗃️</code><span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);"> contains global constants that act as "enums" or "macros" (not sure of the right terminology). I have a whole </span><a href="https://advancedconstruct.net/using-global-names/" style="font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);">article on "global names"</a><span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);"> that goes into details on what is in this sheet.</span></li>
<li><code style="font-weight: var(--font-weight-normal);">vConfig 💎</code><span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);"> contains global constants prefixed with <code>C_</code>, which are all magic numbers or magic strings that do not need to change during runtime. The contents of this sheet are specific to the project, but here are some real-life examples from our game </span><a href="https://lasermagnet.itch.io/wordpile" target="_blank" rel="noopener noreferrer" style="font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);">Wordpile</a><span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);">:</span>
<ul>
<li><code style="font-weight: var(--font-weight-normal);">C_Tile_TweenOut_Time</code><span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);">: tween time for fading out a Tile object.</span></li>
<li><code>C_DIR_Layouts</code>: path of the folder that contains level layouts (which are loaded via AJAX).</li>
<li><code>C_UI_Hold_Interval</code>: the amount of time a player needs to hold a button to activate its secondary function.</li>
<li><code>C_Color_Red</code>: a certain red color value (in this case <code>-281479422673919</code>) that I use in a some "set color" actions.</li>
<li><code>C_Player_Count_Max</code>: hard limit of players that can join a local multiplayer match (the game supports 1-4 players).</li>
</ul>
</li>
<li><code style="font-weight: var(--font-weight-normal);">vState ♻️</code><span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);"> only contains global variables (and no constants) that hold internal state of the game. These are camel cased by default, but sometimes I group them with prefixes and use an underscore after a prefix. Some random examples:</span>
<ul>
<li><code>locale</code>: contains 2 character code for the currently selected UI language (eg. "en"), used for configuring the Internationalization plugin after the a language is chosen on the UI.</li>
<li><code style="font-weight: var(--font-weight-normal);">volumePercentBGM</code><span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);"> and </span><code style="font-weight: var(--font-weight-normal);">volumePercentSFX</code><span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);">: 0-100 values of the background music and sound effects.</span></li>
<li><code style="font-weight: var(--font-weight-normal);">level_seed</code><span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);">: current seed of the level used for initializing the AdvancedRandom object.</span></li>
<li><code style="font-weight: var(--font-weight-normal);">level_currentPlayerId</code><span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);">: contains which player's turn is it in a multiplayer game (0 for first player, 1 for second, etc).</span></li>
<li><code style="font-weight: var(--font-weight-normal);">level_penaltyTotal</code><span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);">: when the level ends, the player gets an amount of penalty points based on how they did and it gets tallied up in this variable.</span></li>
</ul>
</li>
</ol>
<p>That's about it, really. The system hasn't changed much recently, but sometimes I do decide to rename or restructure a few things. I'll try to keep this article updated if that happens.</p>
            ]]>
        </content>
    </entry>
    <entry>
        <title>Downloadable projects</title>
        <author>
            <name>Fodi</name>
        </author>
        <link href="https://advancedconstruct.net/downloadable-projects/"/>
        <id>https://advancedconstruct.net/downloadable-projects/</id>
        <media:content url="https://advancedconstruct.net/media/posts/18/downloadable-projects.png" medium="image" />

        <updated>2025-09-01T21:29:50+02:00</updated>
            <summary type="html">
                <![CDATA[
                        <img src="https://advancedconstruct.net/media/posts/18/downloadable-projects.png" alt="Illustration: a parachuting filing cabinet drawer full of files" />
                    <p>I have some free template &amp; example projects, all available under the MIT license.</p>

                ]]>
            </summary>
        <content type="html">
            <![CDATA[
                    <p><img src="https://advancedconstruct.net/media/posts/18/downloadable-projects.png" class="type:primaryImage" alt="Illustration: a parachuting filing cabinet drawer full of files" /></p>
                <p>I have some free template &amp; example projects, all available under the MIT license.</p>

<p>You can find a list of projects and demos here:<br><a href="https://fodi.github.io/construct-3-projects/">https://fodi.github.io/construct-3-projects</a></p>
<p>You can grab the source files from this monorepo:<br><a href="https://github.com/fodi/construct-3-projects">https://github.com/fodi/construct-3-projects</a></p>
<p>I also have some example &amp; experimental projects hosted on Itch.io, you can find them in this collection:<br><a href="https://itch.io/c/6291129/fodis-open-source-projects">https://itch.io/c/6291129/fodis-open-source-projects</a></p>
<p>Have fun!</p>
<p>If you find any of them useful, and would like to <a href="https://buymeacoffee.com/fodi" target="_blank" rel="noopener noreferrer">buy me a coffee</a>, you can :)</p>
            ]]>
        </content>
    </entry>
    <entry>
        <title>Using &quot;global names&quot;</title>
        <author>
            <name>Fodi</name>
        </author>
        <link href="https://advancedconstruct.net/using-global-names/"/>
        <id>https://advancedconstruct.net/using-global-names/</id>
        <media:content url="https://advancedconstruct.net/media/posts/14/global-names-2.png" medium="image" />
            <category term="Organization"/>

        <updated>2025-08-13T21:56:00+02:00</updated>
            <summary type="html">
                <![CDATA[
                        <img src="https://advancedconstruct.net/media/posts/14/global-names-2.png" alt="Illustration: a clipboard showing a list of three items each with a roll of string, and a big green checkmark" />
                    <p class="msg msg--highlight ">String literals? Yuck. More typo protection, better autocompletes, enhanced usage lookups? Yes please!</p>

                ]]>
            </summary>
        <content type="html">
            <![CDATA[
                    <p><img src="https://advancedconstruct.net/media/posts/14/global-names-2.png" class="type:primaryImage" alt="Illustration: a clipboard showing a list of three items each with a roll of string, and a big green checkmark" /></p>
                <p class="msg msg--highlight ">String literals? Yuck. More typo protection, better autocompletes, enhanced usage lookups? Yes please!</p>

<p>OG Construct developer <a href="https://bsky.app/profile/salmanshh.bsky.social">Salman Shurie</a> referred to the engine's event system as "super intellisense" a couple of times - turns out the phrase was coined by <a href="https://bsky.app/profile/wtfmig.bsky.social">@wtfmig</a>. Nevertheless, I think it's on point.</p>
<p>When you're using the event system (and no JS/TS code), you can't mistype names of variables, constants, behaviours, objects, families or functions, because the editor simply won't let you. You can also rename any of these without worrying about breaking code, Construct automatically updates all references to reflect the name change (again, as long as they are not mentioned in JS/TS code). If you're using the paid version, the editor can also find all usages of variables, constants, objects and family members. It's an amazing tool and I use it countless times during development.</p>
<p>There are some things you can still mistype, since they are not structured as identifiers, but strings. Layer names, animation names, effect names, various tags (for tweens, timers, sounds, et cetera) can be entered as string literals. Construct tries to suggest them, but you can still make a typo and you don't get usage finding. And if you decide to rename a layer, animation, effect or any sort of tag, you'll have to manually search for it and change it manually by hand which is tedious and error prone.</p>
<p>Rather than doing that, you can create global constants (which are identifiers) and use them instead of string literals. This way you get typo protection, usage lookups and renaming things is a lot easier once you resist the urge to use string literals in those cases. Granted, there's an extra step (creating a global constant), but I think it's worth the effort.</p>
<p>In my projects I put all "global name" constants in an event sheet called <code>vNames</code>. Since it only contains global constants, it's automatically "included" in all events sheets, so you don't have to worry about importing it. (the same goes for functions and custom actions too; only sheets containing events have to be included to run.)</p>
<p>You can also apply a naming convention on the global "name" constants to signify their "type", eg:</p>
<ul>
<li><code>LAYER_Main = "Main"</code> (value matches the layer name)</li>
<li><code>TIMER_Invincibility = "Invincibility"</code> (timer tag)</li>
<li><code>TWEEN_FadeIn = "FadeIn"</code> (tween tag)</li>
<li><code>EFFECT_Brightness = "Brightness"</code> (value matches an effect name)</li>
<li><code>ANIM_Idle = "Idle"</code> (value matches an animation name)</li>
</ul>
<p>...or you can even add the names of the related family or object type, so there's no reuse between different types:</p>
<ul>
<li><code>TIMER_Player_Invincibility = "Invincibility"</code></li>
<li><code>TWEEN_Enemy_Opacity_FadeIn = "Opacity_FadeIn"</code> (also includes the "type" of tween - in this case, opacity)</li>
<li><code>EFFECT_Item_Brightness = "Brightness"</code></li>
<li><code>ANIM_Enemy_Idle = "Idle"</code> (matches an animation name in the</li>
<li><code>ANIM_Player_Idle = "Idle"</code></li>
</ul>
<p>Lately I've been doing the latter which has two additional benefits:</p>
<ul>
<li>Less confusion when finding references, since every name is specific to an object type or a family</li>
<li>Less typing / better autocompletion: eg. I can type ANIM_ to get a list of all animation names, continuing typing the object/family name filters the list even further so it's easy to choose one with the arrow keys</li>
<li>Tidier vNames sheet: alphabetically sorting global names means they are grouped by type and object / family.</li>
</ul>
            ]]>
        </content>
    </entry>
    <entry>
        <title>Project organization</title>
        <author>
            <name>Fodi</name>
        </author>
        <link href="https://advancedconstruct.net/project-organization/"/>
        <id>https://advancedconstruct.net/project-organization/</id>
        <media:content url="https://advancedconstruct.net/media/posts/17/project-organization.png" medium="image" />
            <category term="Organization"/>

        <updated>2025-08-13T21:20:00+02:00</updated>
            <summary type="html">
                <![CDATA[
                        <img src="https://advancedconstruct.net/media/posts/17/project-organization.png" alt="Illustration: an octopus holding a bunch of books in its tentacles" />
                    <p>I'd like to cover many things on this topic, so here's a list showing which article's available and what's planned.</p>

                ]]>
            </summary>
        <content type="html">
            <![CDATA[
                    <p><img src="https://advancedconstruct.net/media/posts/17/project-organization.png" class="type:primaryImage" alt="Illustration: an octopus holding a bunch of books in its tentacles" /></p>
                <p>I'd like to cover many things on this topic, so here's a list showing which article's available and what's planned.</p>

<h2>Available</h2>
<ul>
<li><strong><a href="https://advancedconstruct.net/using-global-names/">Using "global names"</a></strong><br>Construct does not have enums and uses string literals in some places where an enum would be more convenient. Here's a way to get almost all benefits of enums.</li>
<li><strong><a href="https://advancedconstruct.net/sheet-management/">Sheet management</a></strong><br>A system composed of top level or "main" sheets, action sheets, function sheets, value sheets and <span style="text-decoration: underline;">actual</span> event sheets.</li>
</ul>
<h2>Planned</h2>
<ul>
<li><strong>Object &amp; family conventions</strong><br>Naming and grouping, typical hierarchies, instance variable and custom action usage</li>
<li><strong>Global object(s)</strong><br>Also known as the level or game manager object, a singleton, or autoload in Godot-land. I use it to keep state between layouts, run timers and value tweens not related to objects and a few other minor things.</li>
<li><strong>Code reuse and structuring</strong><br>How and when I use functions, custom actions and event groups.</li>
</ul>
<p> </p>
            ]]>
        </content>
    </entry>
    <entry>
        <title>Finding things in Construct</title>
        <author>
            <name>Fodi</name>
        </author>
        <link href="https://advancedconstruct.net/finding-things-in-construct/"/>
        <id>https://advancedconstruct.net/finding-things-in-construct/</id>
        <media:content url="https://advancedconstruct.net/media/posts/13/finding-things.png" medium="image" />
            <category term="Productivity"/>

        <updated>2025-08-13T20:38:00+02:00</updated>
            <summary type="html">
                <![CDATA[
                        <img src="https://advancedconstruct.net/media/posts/13/finding-things.png" alt="Illustration: a cartoonish private inspector character with big eyes holding a magnifying glass" />
                    <p class="msg msg--highlight ">Let's take a look at the tools in Construct that let you find stuff.</p>

                ]]>
            </summary>
        <content type="html">
            <![CDATA[
                    <p><img src="https://advancedconstruct.net/media/posts/13/finding-things.png" class="type:primaryImage" alt="Illustration: a cartoonish private inspector character with big eyes holding a magnifying glass" /></p>
                <p class="msg msg--highlight ">Let's take a look at the tools in Construct that let you find stuff.</p>

<p>Like in most development environments you can <strong>perform a text search</strong> by pressing <em>Ctrl</em> + <em>F</em>. Construct allows you to specify the scope of your search, toggle case sensitivity and you can even perform a second search to further filter down search results, which is especially handy when you have a lot of them. You can also <strong>remove results</strong> by selecting them and pressing <em>Delete</em> (re-running the search will bring them back).</p>
<p>If you're editing a code block or a text file, <em>Ctrl</em> + <em>F</em> brings up a different toolbar that allows you to <strong>find (and even replace) text</strong>. The toolbar might look familiar if you're a VSCode user, since both are powered by the open source Monaco code editor which replaced the old CodeMirror 5 based one in Construct 3 r432. It also has nifty features like renaming identifiers by pressing <em>F2</em> and a bunch of other which you can find in the Command palette. Just note that the scope is always the current code block or tab.</p>
<p>As your project grows, you might end up scrolling a lot up and down the project bar to <strong>find event sheets, objects, files</strong>, et cetera; luckily there's a search field you can focus by pressing <em>Ctrl</em> + <em>Shift</em> + <em>F</em> and just start typing to find matches.</p>
<p>Since Construct is running in the browser you can still use the generic find tool, which can be especially useful for <strong>highlighting text on your screen</strong>. Press <em>Ctrl</em> + <em>G</em> to bring it up (since <em>Ctrl</em> + <em>F</em> is overridden to use Construct's own find feature).</p>
<p>A super useful feature (unfortunately missing from the free version) is that you can right click any object, family, function, custom action or variable and select "<strong>find all references</strong>". In all cases, Construct will compile a list of each "mention" in the event sheets. If you selected an object instance, object type or family, you'll also see the number of instances per layout. If you use the "Create object (by name)" system action anywhere, object &amp; family reference lists will also include those actions as well just to be on the safe side; you can hide those results by unchecking "Show ambiguous".</p>
<p>If you opt in to use <strong>"global names"</strong> instead of string literals to reference names of animations, layers, effects, various tags and such in your event sheets, you'll also be able to find all mentions of those using the "find all references" feature. Not to mention the added bonus of typo protection and easy renaming. <a href="#non-existing-post-with-id-7">Read more about "global names" here!</a></p>
<p>When making changes to a fairly complex project it's easy to get lost jumping between event sheets (especially if you have about 20 of them open). In such a scenario I like to use the often forgotten <strong>bookmarks feature</strong>. The <strong>Bookmarks bar</strong> is not open by default, but I usually have it open all the time docked in the bottom left corner, just taking a bit of space from the <strong>Properties bar</strong>. When you're in an event, you can press <em>F2</em> to bookmark it, which adds an easy to spot icon next to the event and adds it to the Bookmarks bar, where you can double click it to jump right to it. Just don't forget to remove old bookmarks you no longer need: the easiest way is to right-click the bar and select <strong>Remove All</strong>.</p>
            ]]>
        </content>
    </entry>
</feed>
