{
    "version": "https://jsonfeed.org/version/1",
    "title": "Barely Conscious Games — Devlog",
    "home_page_url": "https://www.barelyconscious.games/devlog",
    "feed_url": "https://www.barelyconscious.games/feed.json",
    "description": "Devlog from Barely Conscious Games, an indie game studio making retro-modern 2D games.",
    "author": {
        "name": "Matt Schwartz",
        "url": "https://www.barelyconscious.games"
    },
    "items": [
        {
            "id": "https://www.barelyconscious.games/devlog/bespoke-engines",
            "content_html": "<p><img src=\"https://www.barelyconscious.games/devlog/bespoke-engine/bespoke.png\" alt=\"\" /></p>\n<p>Last week I wrote about my new XGUI implementation that I had been working on for the last month. I had put together an Ability Training screen in a couple hours and it was a very smooth process overall and things seemed to be going well. So I took some time off, played some games, and then came back and saw the memory profile had climbed from about 155 MB to over 1 GB even though I was only rendering ~60 static elements on screen. XGUI was allocating about 300 KB of memory <strong>per second</strong> while doing nothing.</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/bespoke-engine/bad-sign.png\" alt=\"bad sign\"></p>\n<p>I was using smart pointers everywhere in C++, and I was able to correlate every constructor to a destructor call, so I started looking at Lua. Like most modern languages, Lua is garbage-collected, which just means for the most part it manages its own memory. You ask Lua for a new object and Lua takes care of creating and keeping track of it, including knowing when it&#39;s no longer needed and can be deleted (garbage collected). Garbage-collected languages make it seem like you never have to care about memory ever again. You can create as many objects as your heart desires and no one will stop you... until the garbage collector pauses your entire program to remove all the junk you made and now your game freezes every 4 seconds.</p>\n<p>Having come from a primarily Java background, I wasn&#39;t sure where to start so I brought in Claude and asked it to &quot;<em>review these C++, XML, and Lua files and find out why we&#39;re seeing 300 KB/sec in Lua allocations</em>&quot;. After it &quot;dug into the files instead of guessing&quot; and &quot;had the full picture&quot;, it managed to find a couple of optimizations that helped bring the allocations down all the way to 3 KB/sec. Pretty good, I told Claude, but there&#39;s still a leak. Claude then assured me that we had made great progress and 3 KB/sec is really not that bad so we can stop now. <em>The hell we can</em>, I said, and decided to press on and ultimately found out the cause of the allocations was a clever little bit of code.</p>\n<h4>The Clever Little Bit of Code</h4>\n<p>I&#39;m using <code>sol</code>, which is a C++ library that makes working with Lua simple, and one of the things it does really well is that it seamlessly integrates its type system with C++ types. It basically handles the conversions between an int, a string, and a table with a simple assignment (<code>=</code>) operation. Mainly, this is used for converting a known type from a Lua result into a known C++ type, like extracting the numerical result from a Lua function.</p>\n<pre><code class=\"language-cpp\">sol::function_result Result = lua.do_file(Filepath);\nint ResultInt = Result; // &lt;-- sol converts `sol::function_result` to `int` seamlessly\n</code></pre>\n<p>In Lua, everything is a table, and through <code>sol</code>, you can access keys in a table like a standard map:</p>\n<pre><code class=\"language-cpp\">sol::table Table = lua.do_file(Filepath);\nint Status = Table[&quot;status&quot;]; // &lt;-- retrieve the `status` field from the table\n</code></pre>\n<p>And I mean everything in Lua is a table. Dictionaries, of course, and arrays, and objects. And importantly for our story, <em>C++ defined types</em> are tables, too. If you had a Creature <code>class</code> with the <code>Name</code> field, you could access it like this with <code>sol</code>:</p>\n<pre><code class=\"language-cpp\">lua.new_usertype&lt;Creature&gt;(&quot;Creature&quot;, &quot;name&quot;, &amp;Creature::Name);\nsol::table MyCreature = new Creature(...);\nstd::cout &lt;&lt; &quot;Creature&#39;s name is &quot; &lt;&lt; MyCreature[&quot;name&quot;] &lt;&lt; std::endl;\n</code></pre>\n<p>So putting all this together, you can make pretty simple routing logic that seamlessly crosses between C++ and Lua objects in just a few lines:</p>\n<pre><code class=\"language-cpp\">// Lookup-&gt;Path is a vector of strings\nsol::object Res = RootTable;\nfor (; i &lt; Lookup-&gt;Path.size() &amp;&amp; Res.is&lt;sol::table&gt;(); ++i)\n{\n    const string&amp; P = Lookup-&gt;Path[i];\n    Res = Res.as&lt;sol::table&gt;()[P];\n}\n</code></pre>\n<p>This functionality was critical because of runtime bindings in XGUI, a capability which allows you to create, for example, a text element that always displays the health of a creature in a single line of XML:</p>\n<pre><code class=\"language-xml\">&lt;Text text=&quot;{$.creature.stats.health}&quot; /&gt;\n</code></pre>\n<p>And those bindings can be attached to Lua or C++ objects or even a mixture of the two. <code>{$.tooltipData.creature.name}</code> renders the <code>name</code> (string) of the <code>creature</code> (C++ pointer) field stored on <code>tooltipData</code> (Lua table). All of these types can be boxed into a <code>sol::object</code> and if it can also be boxed into a <code>sol::table</code>, we can access its fields dynamically at runtime.</p>\n<p>Anyway, this clever routing logic is what was causing the persistent 3 KB/sec memory leak. At this point in time, I was looking at a memory leak I didn&#39;t fully understand and it was impacting one of the core reasons XGUI even exists. If this feature wasn&#39;t there, XGUI really didn&#39;t make sense as a 4 week investment.</p>\n<h4>Making Your Own Game Engine</h4>\n<p>If you ask anyone in the indie gamedev community which game engine you should use to make a game, you&#39;ll get a bunch of different answers. Unity, Godot, Love2D, etc. But there&#39;s always one answer you&#39;ll get consistently: &quot;don&#39;t make your own game engine&quot;. It&#39;s good advice and when XGUI failed, I started to reconsider my decision to make my own game engine. I was spending all this time working on a framework for the game rather than the game itself. This was day 3 of debugging and it felt like I was genuinely stuck on this memory leak. If I couldn&#39;t solve it, I felt like I&#39;d have to abandon the engine.</p>\n<p>Then I remembered that I&#39;ve never <em>not</em> been able to solve a problem so why should this one be any different?</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/bespoke-engine/better.png\" alt=\"better\"></p>\n<p>So I just got back to work assuming I would figure it out.</p>\n<h4>The Answer is Always Caches</h4>\n<p>I pressed Claude some more to dig into this problem, focusing on that block of code in particular and it started searching the <code>sol</code> include files I had downloaded as well. It pointed out that when it comes to <em>userdata</em> specifically (ie, the C++ objects), <code>sol</code> boxes the C++ data into a freshly-allocated Lua object every time you create a new reference to that object (which in C++ looks like <code>sol::table Table = OtherTable</code>, where the <code>=</code> is invoking the copy constructor on <code>sol::table</code>). And I&#39;m doing that a <em>lot</em> since the runtime bindings are updated every frame. I wasn&#39;t completely convinced Claude was correct here; LLMs hallucinate constantly, after all. But, I proved it was right by adding a gate to prevent userdata from being dereferenced through <code>sol</code> and the Lua allocations immediately dropped.</p>\n<p>One of the most important skills for a software engineer is the ability to break down problems and abstract them. A lot of problems have already been solved and many unique problems are really just solved problems wearing a different hat. On the surface, my problem was &quot;how do I stop invoking the copy constructor?&quot;, but put a different way, the problem was really: &quot;I need a way to access data <em>without repeating unnecessary work</em>&quot;. A cache solves that problem by doing the work once and keeping the result for next time. So I implemented a cache. </p>\n<p>I would allocate the Lua reference once, store it in the cache, and the next time I need to find that reference I just return it from the cache instead without an additional allocation. For the cache key, I treat the runtime binding (eg, <code>$.tooltipData.creature.name</code>) as a route and each <em>hop</em> in the route is cached: so for our example, there would be an entry for <code>$</code>, <code>$.tooltipData</code>, <code>$.tooltipData.creature</code>, and <code>$.tooltipData.creature.name</code>. As a result, the Lua allocations finally dropped to 0 KB/sec while idling, and incidentally, the frame time was reduced by 50% (4ms -&gt; 2ms for 670 elements on screen).</p>\n<h4>Conclusion</h4>\n<p>Even though I managed to solve this particular problem, I know it won&#39;t be the last bug. I know that it takes a lot more time to work in a custom game engine because you have to reinvent features that are ready-to-use in commercial game engines. And I know that this is time taken away from making content for the game. So why do I persist? Honestly, because I choose to. </p>\n<p><img src=\"https://www.barelyconscious.games/devlog/bespoke-engine/persistence.png\" alt=\"persistence\"></p>\n<p>One piece of advice that&#39;s stuck with me for years is <em>write what you know</em>. Since I know programming a lot more than I know art and music, I&#39;m focusing on that for Script Kitties and a custom game engine is the perfect playground. I don&#39;t know how that will translate to success, but at this point the only one who can stop me is me.</p>\n",
            "url": "https://www.barelyconscious.games/devlog/bespoke-engines",
            "title": "Custom Game Engines",
            "summary": "Why You (Probably) Shouldn't Write Your Own Game Engine",
            "date_modified": "2026-07-16T15:30:00.000Z",
            "author": {
                "name": "Matt Schwartz",
                "url": "https://www.barelyconscious.games"
            }
        },
        {
            "id": "https://www.barelyconscious.games/devlog/xgui-source",
            "content_html": "<p><img src=\"https://www.barelyconscious.games/devlog/xgui-src/hero.png\" alt=\"\" /></p>\n<p>Four weeks ago I decided to invest what ended up being way more time than I anticipated in creating a new GUI engine for Script Kitties, XGUI. It was designed to support faster and easier development of all the GUI screens I&#39;m going to need, which is a lot.</p>\n<p>I started working on one of the new screens, an ability editor, to test it out. The ability editor will allow players to change which abilities a creature has available to use in combat from a library of unlocked abilities. The player unlocks new abilities by exploring and completing challenges in the game, such as defeating a number of enemies in combat with fire abilities to unlock Firestorm.</p>\n<p>I took XGUI out for a spin and I&#39;m thrilled to say the whole process was an absolute delight. Here&#39;s a demo of building that screen, with the editor on the right and the game itself running on the left with hot-reloading:</p>\n<p><video src=\"https://d32jwktcm7qojt.cloudfront.net/xgui-src-video.mp4\" controls></video></p>\n<h3>Design-Driven Development</h3>\n<p>In the software-buildin&#39; business, when you set out to make something that will take many weeks or months to build, that <em>something</em> is a risk because you don&#39;t <em>know</em> that it will work. You can manage the risk by clarifying the ambiguity, isolating unknowns, building proofs-of-concept, and, ultimately, trusting your gut a little. It takes time to do all of that, but it&#39;s good to know if it&#39;ll be worth it before you waste time.</p>\n<p>For XGUI, I did just that. I started by writing a design document, which is just a fancy name for a markdown file that describes what I want to build and how I&#39;m going to build it. I spent a couple days working it over, putting down examples of the interface and designing rules around what values are possible for each attribute and what those values would mean for the engine&#39;s responsibilities. If you&#39;ve ever read through the instruction manual for a board game, you&#39;ve read a form of a design document. Both the manual and design documents introduce new ideas and describe precisely how those ideas are supposed to work in practice.</p>\n<p>Now, I felt pretty good on day 3, and having a well-rounded design document helped maintain confidence for the next 20ish days. See, software gets built like a 3D printer, going layer-by-layer, setting up foundations before building on top of them. Sure, you test your code along the way so you know each piece is working as it&#39;s supposed to, but until that last piece gets built you still don&#39;t know the whole thing will work.</p>\n<p>Each piece along the way that worked would simultaneously boost my confidence while increasing my anxiety for the final flip when I would test it out end-to-end. Any small mistake nestled deep in the code early on may not be visible until everything&#39;s hooked up. And those small mistakes are the most difficult to find during an end-to-end test.</p>\n<h3>The Proof that was in the Pudding</h3>\n<p>With XGUI, since there already existed a functioning GUI engine, the question wasn&#39;t just, &quot;would it work?&quot; but &quot;would it work <em>better</em>?&quot; And as soon as I went to add a tooltip to an element, I was convinced the answer was yes, it will work better, because all it took was two little attributes on any element that needed to have a tooltip:</p>\n<pre><code class=\"language-xml\">&lt;Panel id=&quot;itemSlot&quot; tooltip=&quot;gui_item_slot_tooltip.xml&quot; tooltipData=&quot;{.}&quot; /&gt;\n</code></pre>\n<p><img src=\"https://www.barelyconscious.games/devlog/xgui-src/ability-editor.png\" alt=\"ability editor\"></p>\n<p>All the messy bits that come with detecting whether an element that supports a tooltip has a mouse over it or not and displaying another element depending on that all collapsed into these two beautiful attributes: <code>tooltip</code> and <code>tooltipData</code>. The backend logic orchestrating the messy bits <a href=\"https://github.com/mattschwartz/xgui/blob/main/src/XGUI.cpp#L98-L134\">migrated to C++</a>:</p>\n<pre><code class=\"language-cpp\">if (auto&amp; tt = Hit-&gt;Tooltip)\n{\n    auto View = Hit-&gt;GetView();\n    auto Model = View-&gt;FindInModel&lt;sol::table&gt;(tt-&gt;ModelIndex);\n    tt-&gt;GetView()-&gt;SetModel(Model);\n\n    // show only if it has data\n    if (Model.valid()) Tooltip = tt;\n    else Tooltip.reset();\n}\n</code></pre>\n<p>Runtime bindings were another material gain which allowed a text element to be set dynamically based on game data instead of static strings.</p>\n<pre><code class=\"language-xml\">&lt;Text id=&quot;levelText&quot; text=&quot;Lv. {$.selectedCreature.level}&quot; /&gt;\n</code></pre>\n<p><img src=\"https://www.barelyconscious.games/devlog/xgui-src/dynamic-bindings.png\" alt=\"bindings\"></p>\n<p>Again, <a href=\"https://github.com/mattschwartz/xgui/blob/main/src/XGUIRuntimeBinding.h#L328-L372\">C++ handles the finnicky part about all that</a>:</p>\n<pre><code class=\"language-cpp\">virtual void Apply(const ViewHandle::ScopeContext&amp; Context, FWidget&amp; Widget) const override\n{\n    if constexpr (std::is_same_v&lt;T, std::string&gt;)\n    {\n        if (StringTemplate.empty()) return;\n\n        string res;\n        bool bOpen = false;\n        size_t i = 0;\n        for (auto&amp; c : StringTemplate)\n        {\n            if (c == &#39;{&#39;)\n            {\n                bOpen = true;\n            }\n            else if (!bOpen)\n            {\n                res += c;\n            }\n            else if (bOpen &amp;&amp; c == &#39;}&#39;)\n            {\n                if (i &gt;= BindingResolvers.size())\n                {\n                    return;\n                }\n                res += BindingResolvers[i++]-&gt;Resolve(Context);\n                bOpen = false;\n            }\n        }\n        Widget.*Member = res;\n    }\n    else\n    {\n        Widget.*Member = BindingResolvers[0]-&gt;Resolve(Context);\n    }\n}\n</code></pre>\n<p>In the early days of my career, I worked with a few different web frameworks like Angular, jQuery, Razor, and React. There were things along the way that I liked and didn&#39;t like about each, and so I tried to carry forward just the elements I found enjoyable to work with. </p>\n<p><img src=\"https://www.barelyconscious.games/devlog/xgui-src/high-praise.png\" alt=\"high praise\"></p>\n<p>It&#39;s definitely a far cry from being a proper web framework but it does what I need for Script Kitties. I&#39;ve got the XGUI code hosted in <a href=\"https://github.com/mattschwartz/xgui\">GitHub</a> along with some example XML and Lua code. It&#39;s not currently runnable (it expects a simple renderer) but if there&#39;s any interest I can get a working demo going.</p>\n",
            "url": "https://www.barelyconscious.games/devlog/xgui-source",
            "title": "XGUI Source Code",
            "summary": "Hopefully they don't pay me per line of code",
            "date_modified": "2026-07-09T15:30:00.000Z",
            "author": {
                "name": "Matt Schwartz",
                "url": "https://www.barelyconscious.games"
            }
        },
        {
            "id": "https://www.barelyconscious.games/devlog/spotlight-battle",
            "content_html": "<p><img src=\"https://www.barelyconscious.games/devlog/spotlight-battle/battle_mode_v1.png\" alt=\"\" /></p>\n<p>In the beginning, before I had any real plans for Script Kitties, the battle mode was a simple 1v1 arena with some basic actions: fight, run, use item, and switch out cats. Since the game was called <strong><em>Script</em></strong> Kitties, I wanted there to be some kind of &quot;scripting&quot; with the abilities. The idea was there were these items called Biograms that you could find in the world which changed how an ability worked. For example, the <code>Claw</code> ability augmented with a <code>Sweeping</code> Biogram would turn into the <code>Swipe</code> ability that hit multiple targets simultaneously. If you&#39;ve ever played Path of Exile, Biograms are functionally Support Gems:</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/spotlight-battle/poe.png\" alt=\"poe\"></p>\n<p>As I was coming up with different kinds of Biograms, I realized that a 1v1 arena could not support my ideas. After all, what&#39;s the point of an ability that hits multiple targets when there is only ever 1 target to hit? So in order for Biograms to make any kind of sense, I <em>had</em> to have party-based combat:</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/spotlight-battle/battle_mode_v2.png\" alt=\"Party-time\"></p>\n<p>I spent too much time working on the new interface and was getting ready to start polishing it up when my nephew asked to play it. So he did a few rounds of combat and then said to me, &quot;All I&#39;m doing is pressing enter&quot;. He had meant that all he had to do was hit <em>Fight</em> (enter), select an ability (enter), select a target (enter), and then do it all over again the next turn. Without exaggeration, this was the most important bit of feedback I ever got.</p>\n<p>Now, I&#39;m in a lot of game dev spaces online (obviously), and I see this come up quite a bit where a developer gets feedback and their first reaction is defensive: &quot;Well the player just <em>didn&#39;t get it</em>&quot;. It&#39;s understandable, but ultimately it&#39;s detrimental. One person in particular stood out to me because when he received the feedback that his tutorial was difficult to understand, he made <em>an entire video</em> blasting the reviewer. I saw the tutorial; the reviewer was right and there were probably many more players who felt the same way.</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/spotlight-battle/player-feedback.png\" alt=\"Am I so out of touch?\"></p>\n<p>My nephew was right of course, which meant the combat system needed a rework. I knew it would be a huge investment and I wanted to see how it would look before committing too much time, so I put together a quick animation demonstrating the combat in full 2D as a proof-of-concept:</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/spotlight-battle/battlemap.gif\" alt=\"Combat v4 prototype gif\"></p>\n<p>The prototype ended up introducing a lot of concepts that I didn&#39;t have in the game yet like action points, visibility, and the terrain itself. I was inspired by games like Divinity: Original Sin 2 which has terrain mechanics that let you light up the ground with electricity and create explosions by mixing fire and poisonous gas. All of a sudden the combat was no longer about <em>just hitting enter</em>.</p>\n<p><video src=\"https://www.barelyconscious.games/devlog/spotlight-battle/v4-sample.mp4\" controls></video></p>\n<p>Abilities and Biograms gained a great deal of depth as a result because of how many different ways the player could interact with the combat system. Some mechanics that emerged:</p>\n<ol>\n<li>Positioning: line-of-sight, range, stealth, cover</li>\n<li>Terrain: movement, area of effects, overlapping terrain effects</li>\n<li>Action points: resource management, drains and gains</li>\n</ol>\n<h3>Scripting</h3>\n<p>With the increased complexity and unbounded ideas, I needed a way to express the logic more easily. I knew early on I wanted to integrate Lua with the game so I could support mods, and so I started by exposing the combat interface. I used the raw Lua headers to start with because I didn&#39;t realize there was a better way until I came across <a href=\"https://github.com/ThePhd/sol2\">sol2</a>. If you&#39;re ever looking to integrate Lua with C++, do yourself a favor and use sol2 unless you&#39;re a fan of managing the Lua stack by hand. Which I was not.</p>\n<p>Anyway, exposing Lua bindings in C++ is dummy easy in sol2. Here I&#39;m defining the <code>Ability</code> type:</p>\n<pre><code class=\"language-cpp\">lua.new_usertype&lt;Ability&gt;(&quot;Ability&quot;,\n\t&quot;id&quot;, sol::readonly_property(&amp;Ability::Id),\n\t&quot;name&quot;, &amp;Ability::Name,\n\t&quot;sprite&quot;, &amp;Ability::Sprite,\n\t&quot;description&quot;, &amp;Ability::Description,\n\t&quot;shape&quot;, &amp;Ability::Shape,\n\t&quot;tags&quot;, &amp;Ability::Tags,\n\t&quot;maxTargets&quot;, &amp;Ability::MaxNumTargets,\n\t&quot;range&quot;, &amp;Ability::Range,\n\t&quot;radius&quot;, &amp;Ability::Radius,\n\t&quot;cost&quot;, &amp;Ability::Cost,\n\t&quot;hasTag&quot;, &amp;Ability::HasTag);\n</code></pre>\n<p>which lets you operate on an ability natively in Lua:</p>\n<pre><code class=\"language-lua\">local isHarmful = false\nfor _, tag in ipairs(ability.tags) do\n    if tag == AbilityTag.HARMFUL then\n        isHarmful = true\n        break\n    end\nend\n\nif isHarmful then\n    local canAfford = creature.actionPoints &gt;= ability.cost\n    local inRange = closestDistance &lt;= ability.range\n\n    if canAfford and inRange then\n        battle:resolveCombat(creature, creature.position, {closestTarget}, attack)\n        creature.actionPoints = creature.actionPoints - ability.cost\n        return attack()\n    end\nend\n</code></pre>\n<p>My mental model for these bindings is: I don&#39;t care how the C++ needs to work as long as the Lua is easy and intuitive. I start backwards with Lua by writing how I would <em>want</em> it to work and then retrofit the C++ code to <em>make</em> it work. I call it customer-driven development: you start by writing code like the customer of your API and then figure out how to make it true.</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/spotlight-battle/my-hands.png\" alt=\"my hands\"></p>\n<p>Now, Biograms were especially tricky because of how I wanted <em>them</em> to work specifically. I wanted an interface that could be used intuitively for any possible combination of actions. I came up with a solution using native Lua tables.</p>\n<p>By the way, in case you didn&#39;t know, EVERYTHING in Lua is tables.</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/spotlight-battle/tables.png\" alt=\"tables\"></p>\n<p>In Lua, you might have: <code>action.actionType = &quot;DAMAGE&quot;</code> and using sol2, in C++ you can easily read it like a map: <code>action[&quot;actionType&quot;] -&gt; &quot;DAMAGE&quot;</code>. Because of this fact, creating arbitrarily-shaped object-looking text becomes trivial:</p>\n<pre><code class=\"language-lua\">local damageAction = {\n    target = v,\n    action = CombatAction.DAMAGE,\n    amount = 14,\n    damageType = DamageType.FIRE\n}\nlocal arenaEffectAction = {\n    action = &quot;SET_ARENA_EFFECT&quot;,\n    position = center,\n    shape = self.shape,\n    radius = self.radius,\n    effect = &quot;BURNING&quot;\n}\nreturn { damageAction, arenaEffectAction }\n</code></pre>\n<p>And if the ability has a Biogram, the different actions created by an ability&#39;s script are modifiable. Biograms act on top of abilities, allowing them to change, remove, and create new actions to be processed. The <code>Splitting</code> Biogram, which replicates an ability&#39;s damage across multiple targets can be expressed like so:</p>\n<pre><code class=\"language-lua\">return function(self, combat)\n    -- figure out how much damage we already did\n    local damageActions = combat:getActions(CombatAction.DAMAGE)\n    local amount = 0\n    for _, v in ipairs(damageActions) do\n        amount = amount + v.amount\n    end\n\n    -- replicate 66% of that damage to all extra targets\n    for _, target in ipairs(findExtraTargets(combat)) do\n        target:takeDamage(amount * 0.66, DamageType.TECHNICAL)\n    end\nend\n</code></pre>\n<p>Ultimately, the idea is: abilities describe how they function in terms of actions and Biograms have free rein to change those actions before the ability is resolved to create that feeling of <em>scripting</em> abilities in Script Kitties.</p>\n<h4>The Player is Always Mostly Right</h4>\n<p>So, in the end the takeaway is pretty simple: listen to your players. They may not always know how to fix problems but they&#39;re usually pretty good at spotting them. In my case, &quot;the game is boring&quot; was enough to send me on a journey to find the fun.</p>\n",
            "url": "https://www.barelyconscious.games/devlog/spotlight-battle",
            "title": "System Spotlight: Battle Mode",
            "summary": "A journey in constructive criticism",
            "date_modified": "2026-07-02T15:30:00.000Z",
            "author": {
                "name": "Matt Schwartz",
                "url": "https://www.barelyconscious.games"
            }
        },
        {
            "id": "https://www.barelyconscious.games/devlog/xgui",
            "content_html": "<p><img src=\"https://www.barelyconscious.games/devlog/xgui/gui_biogram_scripting2.png\" alt=\"\" /></p>\n<p>About two weeks ago, I began writing version 3 of my GUI engine, XGUI (as in <em>X</em>ML), because <a href=\"https://www.barelyconscious.games/devlog/gui-hell\">I hate GUI programming</a>. XGUI holds a lot of promise for me because of the visual editing capabilities that fall out organically from the use of XML:</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/xgui/wysiwyg.png\" alt=\"Editor\"></p>\n<p>LGUI (as in <em>L</em>ua), the previous version, had its entire presentation and controller logic defined in Lua code:</p>\n<pre><code class=\"language-lua\">local GUI = CreateGUI()\nlocal window = GUI:createPanel({ ... })\n\nwindow.okButton = GUI:createPanel({ ... })\nwindow.okButton.text = GUI:createText({\n    text = &quot;Ok&quot;\n})\n\n-- Register events\nwindow.okButton:registerEvent(&quot;OnMouseClicked&quot;, function(mouse) \n    -- handler\nend)\n</code></pre>\n<p>whereas XGUI, of course, is XML with Lua controllers:</p>\n<pre><code class=\"language-xml\">&lt;View controller=&quot;myController.lua&quot;&gt;\n    &lt;Panel id=&quot;window&quot;&gt;\n        &lt;Panel id=&quot;okButton&quot;&gt;\n            &lt;Text text=&quot;Ok&quot; /&gt;\n        &lt;/Panel&gt;\n    &lt;/Panel&gt;\n\n    &lt;!-- Register events --&gt;\n    &lt;Event name=&quot;OnMouseClicked&quot; handler=&quot;handleOnMouseClicked&quot; /&gt;\n&lt;/View&gt;\n</code></pre>\n<h3>Why is this better?</h3>\n<p>For two reasons: visual editing and strict separation of concerns. Obviously visual editing is going to be a smoother process than editing by hand, but how does having strict separation of concerns help? Two words, four syllables: <strong>spaghetti code</strong>.</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/xgui/spaghet.jpg\" alt=\"Spaghetti\"></p>\n<p>Setting clear boundaries between what <em>this</em> code does and what <em>that</em> code does is essential to maintaining a large codebase (and your sanity). Without it, you&#39;ll inevitably find yourself fork-deep in a mound of spaghetti code. XGUI follows a simple MVC (Model, View, Controller) pattern. XML defines the View (how the GUI should be displayed) and Lua defines the Controller (how the GUI should behave). The Model is the bridge that the Controller mutates and the View renders.</p>\n<p>GUIs are highly interactive, especially in video games. There are mouse events, key events, tooltips, sprites, drag-and-drop, visibility, modals... the list goes on. All the while, there&#39;s constant communication between the player and the game engine itself, and everything has to remain in sync. And it takes a <em>lot</em> of code to manage all that. At first, it&#39;s easy and convenient to do it all in one place but very quickly you&#39;ll find yourself in the middle of a 1,500 line Lua file trying to figure out how to render and control the GUI at the same time you&#39;re processing input from the player and handling events from the engine. XGUI - through the MVC pattern - helps <em>organize</em> all of that by forcing the pattern in practice. You simply <em>can&#39;t</em> implement View declarations and Controller business logic in the same place.</p>\n<h4>Runtime Bindings</h4>\n<p>The most common code I wrote in LGUI was updating widgets with data from the game, like a creature&#39;s name or sprite for the user to see.</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/xgui/profile.png\" alt=\"profile\"></p>\n<pre><code class=\"language-lua\">-- declare the visual layout\nlocal window = GUI:createPanel({ ... })\nwindow.creaturePanel = GUI:createPanel({ ... })\nwindow.creaturePanel.name = GUI:createText({ ... })\nwindow.creaturePanel.sprite = GUI:createPanel({ ... })\nwindow.creaturePanel.level = GUI:createText({ ... })\n\n-- bind data to those visual elements\nfunction refreshCreatureGUI(creature)\n    window.creaturePanel.name:setText(creature.name)\n    window.creaturePanel.sprite:setTexture(creature.sprite)\n    window.creaturePanel.level:setText(&quot;Lv. &quot; .. creature.level)\nend\n\n-- later, when the user selects a different creature:\nfunction onCreatureSelected(newCreature)\n    refreshCreatureGUI(newCreature)\nend\n</code></pre>\n<p>Just look at how much code that requires and this is for <em>every</em> dynamic element across <em>every</em> screen. And not only do you need logic to set the values, you also need logic to know when to update those values. This is <em>everywhere</em>. It&#39;s far more likely that an element needs runtime evaluation rather than a simple static string or sprite. </p>\n<p>It&#39;s repetitive, tedious, and as it turns out, completely unnecessary. XGUI&#39;s other superpower: <em>runtime bindings</em>.</p>\n<p>Instead of implementing custom runtime evaluations and update logic, XGUI lets you bind properties (like <code>text</code>) to a runtime value (like <code>name</code>). No Lua code required.</p>\n<pre><code class=\"language-xml\">&lt;Panel id=&quot;creaturePanel&quot;&gt;\n    &lt;Text id=&quot;name&quot; text=&quot;{$.name}&quot; /&gt;\n    &lt;Panel id=&quot;sprite&quot; texture=&quot;{$.sprite}&quot; /&gt;\n    &lt;Text id=&quot;level&quot; text=&quot;{$.level}&quot; /&gt;\n&lt;/Panel&gt;\n</code></pre>\n<h4>Show me the C++</h4>\n<p>So everything we&#39;ve talked about so far is great in theory, but how does it <em>actually work</em>? Let&#39;s get more technical here.</p>\n<p>The XML parsing itself is simple enough. I&#39;m using <a href=\"https://pugixml.org/\">pugixml</a>, which seems to be the de facto C++ XML library, to do the actual parsing and I created simple facade objects for a more readable interface.</p>\n<p>Widgets are the visual building blocks of XGUI:</p>\n<pre><code class=\"language-cpp\">struct Widget \n{\n    string Texture;\n    string Text;\n    SDL_Color BackgroundColor;\n    // other properties...\n};\n</code></pre>\n<p>The GUILoader is a helper class to do the heavy XML parsing into a C++ handle (&quot;GUI&quot;) that the engine knows how to update and render.</p>\n<pre><code class=\"language-cpp\">class GUILoader\n{\npublic:\n    GUILoader(const string&amp; Filepath);\n    unique_ptr&lt;GUI&gt; Load() const;\n};\n</code></pre>\n<p>The Widget facade (XWidget) exposes a simple converter to make cosntruction easier. Note the <code>Bindable</code> template type.</p>\n<pre><code class=\"language-cpp\">class XWidget\n{\npublic:\n    XWidget(pugi::xml_node Node) : Node(Node) {}\n\n    // Handles XML -&gt; Widget conversion\n    unique_ptr&lt;Widget&gt; GetWidget() const;\n\nprivate:\n    pugi::xml_node Node;\n\n    // These are all the properties that can appear on an\n    // element in the XML doc.\n    Bindable&lt;string&gt; Texture() const;\n    Bindable&lt;string&gt; Text() const;\n    Bindable&lt;SDL_Color&gt; BackgroundColor() const;\n    // others...\n};\n</code></pre>\n<p>A <code>Bindable</code> is how we express the nuance between static and runtime values:</p>\n<pre><code class=\"language-cpp\">template &lt;typename T&gt;\nclass Bindable\n{\npublic:\n    string Expression;\n    T Value;\n};\n</code></pre>\n<p>During the <code>update</code> call, XGUI evaluates runtime-bound values and updates Widget values so that during the <code>render</code> call, the computed values are drawn to the screen.</p>\n<pre><code class=\"language-cpp\">void GUI::RenderNode(const Renderer&amp; Renderer, const Widget&amp; Node) const\n{\n\tif (!Child.Texture.Value.empty())\n\t{\n\t\tRenderer.DrawTexture(\n\t\t\tChild.Texture.Value,\n\t\t\tBounds.x, Bounds.y, Bounds.w, Bounds.h);\n\t}\n    // other render calls...\n\n\tfor (auto&amp; ChildNode : Node.GetChildren())\n\t{\n\t\tRenderNode(Renderer, *ChildNode);\n\t}\n}\n</code></pre>\n<p>The runtime bindings have proven to be the most fun challenge I&#39;ve worked on in quite some time. I love implementing ergonomic APIs and interfaces and in general just making code <em>easy</em> to use. This especially is one of those areas where AI just falls flat on its face, but I&#39;ll save that rant for another week.</p>\n<h4>So was it worth it?</h4>\n<p>XGUI came with tradeoffs. It took 2 weeks to make and during that time I wasn&#39;t able to work on any of the game&#39;s content or core mechanics. XGUI <em>will</em> make it faster and easier to implement GUI screens, but how much time it will save is still theoretical. If the only benefit was faster development, it would be a risky bet.</p>\n<p>Something that often gets discounted is the <em>developer experience</em> or DX. When something is easier to use, I&#39;ve noticed that I&#39;m able to do <em>more</em> with it. When I evolved to LGUI, my screens were able to become much more complex and polished because it was <em>easier</em> to write and reason about. <strong>This</strong> is the real payoff I&#39;m looking for. With MVC, I get clear separation and organization. With the visual editor, I get a simplified interface for designing screens. And with runtime bindings, I avoid 90% of the boilerplate I&#39;m overburdened with. All of that reduces the mental load required to implement GUI screens and allows me to focus better on improving the player experience.</p>\n<p>So was it worth it? I think so.</p>\n",
            "url": "https://www.barelyconscious.games/devlog/xgui",
            "title": "XGUI",
            "summary": "And how I girl-mathed the cost of writing it",
            "date_modified": "2026-06-25T15:30:00.000Z",
            "author": {
                "name": "Matt Schwartz",
                "url": "https://www.barelyconscious.games"
            }
        },
        {
            "id": "https://www.barelyconscious.games/devlog/gui-hell",
            "content_html": "<p><img src=\"https://www.barelyconscious.games/devlog/gui-hell/hero.png\" alt=\"\" /></p>\n<p>I really hate GUI programming. In Script Kitties, I&#39;ve rewritten the GUI engine twice. The first time was when I went from text and boxes to sprites:</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/gui-hell/gui-rewrite-1.png\" alt=\"Rewrite #1\"></p>\n<p>And the second was when I realized you shouldn&#39;t design GUIs in pure C++.</p>\n<pre><code class=\"language-cpp\">// This was a simple example\nWindow-&gt;AddWidget(RootGUI-&gt;NewPanel()\n    .Layout(WindowContents)\n    .Trim(WidgetTrim::None)\n    .AddWidget(RootGUI-&gt;NewPanel()\n        .Position({ 1, 0, 4, 0 })\n        .Size({ 0, 0, 275, 48 })\n        .BorderSize(1)\n        .BorderColor(FocusedFrameColor)\n        .Background({ 0, 0, 0, 255 })\n        .AddWidget(RootGUI-&gt;NewImage(&quot;gui_kittycoin.png&quot;)\n            .Size({ 0, 0, 48, 48 })\n            .AddWidget(RootGUI-&gt;NewText()\n                .Position({ 1, 0, 5, 18 })\n                .Size({ 1, 1, 0, 0 })\n                .Update([](WText&lt;ShopState&gt;&amp; Widget, const ShopState&amp; State) {\n                    Widget.Text = GameManager::Only().Bag-&gt;Money;\n                    })\n                .Build())\n            .Build())\n        .Build())\n    .Build());\n</code></pre>\n<p><em>The above code rendered the following, by the way:</em></p>\n<p><img src=\"https://www.barelyconscious.games/devlog/gui-hell/cpp_gui.png\" alt=\"For this?\"></p>\n<p>It was a tedious process of writing code, compiling, validating the GUI, writing some more code, and compiling again. It took 40 hours to write the battle GUI and the main thing I learned was <strong>I did not want to do this again</strong>. </p>\n<p><img src=\"https://www.barelyconscious.games/devlog/gui-hell/battle-scene.png\" alt=\"40 Excruciating hours\"></p>\n<h3>LGUI</h3>\n<p>I didn&#39;t want to write GUIs in C++ anymore, so I created bindings in C++ to write GUIs in Lua instead (hence, <em><strong>L</strong></em>GUI). It was significantly faster, not just because the language itself was smoother to program in but also because with Lua I could finally do <em>hot reloading</em>. I&#39;d make a change and see it reflected in-game within 50ms, no need to recompile.</p>\n<p><video src=\"https://www.barelyconscious.games/devlog/gui-hell/hot_reloading_example.mp4\" controls></video></p>\n<pre><code class=\"language-lua\">-- Same as the C++ code above\nlocal window = GUI:createPanel({\n    parent = root,\n    position = {1, 0, 4, 0},\n    size = {0, 0, 275, 48},\n    borderSize = 1,\n    borderColor = Theme.FocusedFrameColor,\n    backgroundColor = {0, 0, 0, 255}\n})\nwindow.sprite = GUI:createPanel({\n    parent = window,\n    size = {0, 0, 48, 48},\n    texture = &quot;gui_kittycoin.png&quot;\n})\nwindow.sprite.text = GUI:createText({\n    parent = window.sprite,\n    position = {1, 0, 5, 18},\n    size = {1, 1, 0, 0},\n    text = GetBag().money\n})\n</code></pre>\n<h3>XGUI</h3>\n<p>LGUI was a major step forward and made GUI programming a lot more tolerable but there were two main pain points that made me stop. The first was that it was still tedious: every element - even a text label - required ~6 lines of code. Less code than C++, but still code. And the second was the separation between the rendering logic (what elements to show, where) and the control logic (the player moved the mouse, now what?) was easy to blur, which resulted in unmaintainable spaghetti code.</p>\n<p>So this time I set out to build a full drag-and-drop WYSIWYG visual editor. I settled on XML for representing the view logic and Lua still for the control logic. The pattern I am following is MVC - Model-View-Controller, which is a pretty popular framework for managing complex GUIs. The XML defines a template, populated from a data model, with user-interactivity powered by a Lua controller.</p>\n<p>This was the result after vibe coding for a couple days:</p>\n<p><video src=\"https://www.barelyconscious.games/devlog/gui-hell/xgui_editor.mp4\" controls></video></p>\n<p>There&#39;s still a bit to do, namely the C++ XML parser, but I&#39;m very excited to try this out in Script Kitties.</p>\n",
            "url": "https://www.barelyconscious.games/devlog/gui-hell",
            "title": "I Hate GUI Programming",
            "summary": "Tolerable is about as good as it gets",
            "date_modified": "2026-06-18T15:30:00.000Z",
            "author": {
                "name": "Matt Schwartz",
                "url": "https://www.barelyconscious.games"
            }
        },
        {
            "id": "https://www.barelyconscious.games/devlog/next-steps",
            "content_html": "<p><img src=\"https://www.barelyconscious.games/og-image.png\" alt=\"\" /></p>\n<p>In 2012 (when the Mayans ended the world), I was in my dorm room thinking of a name for the hypothetical studio where I would publish all of my games. I had come to like &quot;Barely Conscious Games&quot; because it sort of had a double meaning to me. See, a couple years into college I really started paying attention to this foggy feeling in my mind that made it difficult to concentrate; it felt like I was <em>barely</em> conscious all the time. Turns out it was ADHD, but it took another decade for me to piece that mystery together.</p>\n<p>So anyway, the next 14 years were spent making games (mostly <a href=\"https://www.barelyconscious.games/stonequest\">Stonequest</a>) off and on in my spare time, between college, then internships, then a career. At some point, the career took over everything and I stopped considering myself someone who makes games. </p>\n<p>And then one day in spring 2024, everything changed.</p>\n<h3>That one day in spring 2024 when everything changed</h3>\n<p>It was the week after spring break, my niece and nephew went back to school, and I had taken an extra week off work to do whatever I wanted. So I decided to do a two-day <a href=\"https://en.wikipedia.org/wiki/Game_jam\">game jam</a>. The theme was &quot;technology &amp; cats&quot;, and by the end of those two days, I actually had a playable game in the style of a very simple creature collector.</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/next-steps/script-kitties-battle-mode.png\" alt=\"Script Kitties Battle mode\">\n<img src=\"https://www.barelyconscious.games/devlog/next-steps/script-kitties-game-jam.png\" alt=\"Script Kitties Game Jam\">\n<img src=\"https://www.barelyconscious.games/devlog/next-steps/script-kitties-kittydex.png\" alt=\"Script Kitties Kittydex\"></p>\n<p>(<em>And it&#39;s still going! You can see the latest updates on Script Kitties <a href=\"https://www.barelyconscious.games/script-kitties\">here</a>!</em>)</p>\n<p>I learned a lot from this experience, technically speaking, but the main thing I learned was that <em>I could do it</em>. It had been years since I made anything meaningful and I thought I had lost the ability along the way - that corporate SWE had drained me of any passion. This bit of inspiration was the spark that ultimately led to me quitting my job after 8 years. </p>\n<hr>\n<h3>What&#39;s Next?</h3>\n<p>At my last job, there was this thing called a <em>DFAD</em>, or a <em>date-for-a-date</em>. If someone asked when you were going to be done with something, you could instead say &quot;<em>I don&#39;t know, ask me again next week</em>&quot; and that was a perfectly valid thing to say.</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/next-steps/guess.png\" alt=\"Not for another 2 hours\"></p>\n<p>Sometimes a DFAD would turn into a DFADFAD  (date-for-a-date-for-a-date). Hypothetically, this can be repeated forever, or until they finally stop asking. In practice, you really only get max 2 or 3 before your manager asks you why they&#39;re being asked why you&#39;re not giving a date. So now you have <em>two</em> different people bugging you about this thing. The way I solved this was with a <em>roadmap</em>: a glorious spreadsheet filled with dates and action items. </p>\n<p>Now, the punchline - I&#39;m giving you a DFAD for making the roadmap: June 18. Give me a week and I&#39;ll have a roadmap for you. </p>\n<p>In the meantime, here&#39;s basically where we&#39;re headed:</p>\n<h3>The Road to Next Fest</h3>\n<p>4 days from now, <a href=\"https://store.steampowered.com/sale/nextfest\">Steam Next Fest</a> is starting, which is a great and terrifying opportunity for an indie developer to showcase their game, get some visibility, and gather feedback from players. A successful Next Fest can really put you on the map, but a bad demo - or worse, one that doesn&#39;t work - would be a significant setback. There&#39;s a whole lot left to do in Script Kitties and 4 days isn&#39;t a lot of time. </p>\n<p>I&#39;m gonna be honest buds, it ain&#39;t lookin good. It&#39;s not gonna happen in 4 days.</p>\n<p>Alright, so 2026 is out of the question, what about 2027? Theoretically, Steam will still exist and if they continue hosting Next Fest, then that means I have about 369 days to write the story, hire an artist, build out a steam page, and test the heck out of it to make sure it doesn&#39;t crash. </p>\n<p>That&#39;s doable, right?</p>\n",
            "url": "https://www.barelyconscious.games/devlog/next-steps",
            "title": "new BarelyConsciousGames()",
            "summary": "14 years later",
            "date_modified": "2026-06-11T15:30:00.000Z",
            "author": {
                "name": "Matt Schwartz",
                "url": "https://www.barelyconscious.games"
            }
        },
        {
            "id": "https://www.barelyconscious.games/devlog/script-kitties-retrospective",
            "content_html": "<p><img src=\"https://www.barelyconscious.games/devlog/script-kitties-retrospective/hero.png\" alt=\"\" /></p>\n<p>What do people who have nothing to say write about? Lorem ipsum springs to mind, but\nthat&#39;s hardly worth your time to read let alone my time to copy-paste. Let&#39;s start with\nintroductions and see where that gets us.</p>\n<p>Among other things, I&#39;m the sole developer of <strong>Script Kitties</strong>, the action strategy\ncreature collector with deep turn-based combat. Script Kitties started in March 2024, when\nI decided to kick off a 2-day game jam with everyone I knew. Only one person showed up, but\nother people might have if I&#39;d told them about it.</p>\n<p>This is how it turned out:</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/script-kitties-retrospective/gamejam.png\" alt=\"The result of the first game jam\"></p>\n<p>Completing what I set out to do initially, I decided to turn it into something actually worth playing. Mostly, I was just enjoying programming again but after a few months, I started seeing a real game. I expanded existing systems, like rendering sprites flush with color, and added party-based combat to make things a bit more interesting.</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/script-kitties-retrospective/combat.png\" alt=\"Party-based combat\"></p>\n<p>The world was originally randomly generated across seven biomes.</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/script-kitties-retrospective/rng-world.png\" alt=\"Randomly generated world\"></p>\n<p>It turned out okay, and it was a lot of fun to implement, but I knew it would be difficult to\nget right and chose to pivot to a hand-crafted world that felt more connected.</p>\n<p><img src=\"https://www.barelyconscious.games/devlog/script-kitties-retrospective/dialog.png\" alt=\"Dialog and a more connected world\"></p>\n<p>More to come.</p>\n",
            "url": "https://www.barelyconscious.games/devlog/script-kitties-retrospective",
            "title": "Script Kitties: A Brief Retrospective",
            "summary": "How it started and how it's goin",
            "date_modified": "2025-07-19T15:30:00.000Z",
            "author": {
                "name": "Matt Schwartz",
                "url": "https://www.barelyconscious.games"
            }
        }
    ]
}