4 Hugues Ross - Blog
Hugues Ross

6/17/18

Halberd: Finally, a Proper Demo!

Well, it has been 2 1/2 months in the making. But today, Halberd has reached its first milestone!



Video captions can't really convey how happy I am to see this happen. I've been thinking about Halberd for years now, and it's great seeing it take its first step.

Granted, I still have massive amounts of work to do, but this still feels special regardless.

MVP, or Not?

One thing that I've been struggling with is figuring out what an MVP actually looks like, in the context of an RPG engine. What features are required for such a tool to become 'viable'? Where do I draw the line between wants and needs? I've generally tried to stick to as minimal a definition as possible, but such a definition is probably not what a user would actually expect. It's a tough balance.

In the end, I've decided to go with a little cop-out: The next milestone is what I'm referring to as my 'AMVP' (Absolute Minimum Viable Product), and the next one is the 'True MVP', with additional features and polish that your average user would likely expect as their minimum. I'm still figuring out the details of the latter, but my current benchmark is Dragon Quest 1 (a.k.a. Dragon Warrior). If Halberd can do everything that game can (minus some polish and a few of the more specific features like torches), then I feel like I can more confidently proclaim Halberd to be a viable (if bare-bones) engine.

After that? Who knows! Once Halberd has reached a usable state, a lot of potential avenues will be open to me. I'm probably going to keep finding progressively more varied and complex games to compare against, and mix those features with quality of life updates.

Whatever happens, I'm excited to see where the project goes next!

5/29/18

Halberd: Let's Talk Architecture

I knew this day would come...

...a dark, fateful day...

...when I actually have to care about code architecture


Halberd's development is chugging along, and now that I've gotten a few systems together my codebase is starting to get a little bit cluttered. That means it's time to tidy it up.

Why the Wait?

Personally, I believe that a lot of independent devs overthink game architecture. There's a certain school of thought that dictates that your code should be a perfect, well-oiled machine that's designed to handle anything you throw at it. That's all well and good in theory, but I've always had my doubts that most indies starting a "from scratch" project actually need more than a quickly-assembled Rube Goldberg machine, held together with twine and masking tape.

There are two primary reasons behind this notion of mine:
  1. Your customer does not care about code quality - They really don't. You could have the most beautiful, well-structured code, and a terrible game that no-one wants. On the other hand, your code could be a tire fire and no-one would notice if you managed to keep the game bug-free. As such, polish and quality should be put where it matters the most.
  2. Good architecture is an investment - And of course, investments have an upfront cost. Designing and building solid game architecture takes time, and implementing new code to work with it can also take longer in some circumstances. In return, you make your code more readable and maintainable in the long-term. However, games are often short-term projects and smaller titles are unlikely to fully reap the benefits, while still paying the cost.
Ultimately, I think a lot of novice devs see various patterns being touted as "best practices", and don't consider whether they'll actually benefit from them in the end. Nowadays, my usual approach to architecture is "as little as possible, until it is necessary".

Why now?

Now that I've written 4 paragraphs about why I usually avoid over-engineering like the plague, let's talk about why I've chosen to begin restructuring my code.

Unlike an internal engine built to develop one or two games, Halberd is intended to be an all-in-one tool used by others. That alone isn't necessarily an argument for needing architecture, but it does highlight one important point: This project will require long-term development and support. Along with large teams, long-term projects are among the truly valid use-cases for sound architectural design in my opinion.

If this were the only factor, I wouldn't be too worried yet.The other issue is that my code is starting to get rather complex, another good sign that some straightening out is necessary. More specifically, I'm dealing with:
  • Language interop
  • Data that must be edited and tested non-destructively at runtime
  • Modal input/display (due to switching between PIE and editing)
  • An engine that links into two different front-ends, and must be able to immediately start in any state (menus, combat, map, etc)
Technically, I have all of that already. Problem is, the level of complexity is turning it into a mess. So, it's time to refactor.

What's the Plan?

When you have a clear need for architecture, the next step is to plan it all out. I've done that already, and I'm going to step you through my process in hopes that it'll be helpful.

First of all, we have to consider our requirements. To begin with, we know that the editor and game are going to be Vala and C, respectively. We also know that our exported game shouldn't include any Vala code, giving us the following high-level relationships:
That has already existed since the beginning of the project, so the next step is to look a bit deeper. Specifically, let's look at how the asset editors are laid out, since my impression is that this is the messiest part. Right now, your average editor looks a little like this:
First off, let's get rid of the doubled-up viewport. As a GTK widget, the viewport shouldn't be owned by anything on the C side, but is so that they can check for things like size changes. If we add an event to DFGame for handling window size changes (which is a good idea to begin with), we can at least remove one of the references.

The other obvious problem here is that the C side is clearly doing two things, editing and testing. As a result, there are multiple copies of each child. The simple solution is to split off any test-related data into its own struct, ensuring a proper separation of responsibilities:
So, what about this new "Game Context" that just popped up? Right now, I'm in a position where I haven't had to think too much about how to put the different game elements together. Since I'm rapidly approaching the point where I will need to do that, let's talk about structuring the game state. Right now things are split:
So, what can we do about this? Clearly, the data here needs to be known to the two "states", but we need a way to manage them and make some data (such as the player) available across all of them. We also need to be able to handle things one at a time (We shouldn't be able to run around the map during a fight, after all) without losing information about other parts of the game. To me, this demands a certain structure:
I think a stack makes a lot of sense for this sort of interaction, because there's a lot of "layering" that can happen in an RPG.

Imagine you're walking through the woods, when a bunch of bandits appear to tell the party that they have a bounty on their heads. The bandits attack, then halfway through the fight some allies join in to help even the odds.

This feels pretty typical by the standards of scripted battles, and it fits this structure perfectly: Map, with a Cutscene within it, which initiates an Encounter, during which another Cutscene plays. And of course, most of these states clearly return to the previous state when they conclude. That's perfect territory for a stack-based solution. Since a stack needs something to manage it anyway, we can also make the manager handle our 'global' information, such as the player's stats and inventory.

Back to the editor, this means that we can use our test context to take the edited data in memory, convert it into a game state, and pass it to the game context to push it onto the stack. If we make an event for when the stack empties, we can also return to the edit mode automatically when something like an encounter in test mode finishes. I can also reuse this feature later to know when the final game needs to exit.

Ultimately, we get something that looks like this at a higher level:

Pretty close! There's a little bit more to figure out, but I think I've covered the important parts here.

So that's all?

Nope, not by a long shot. Iteration is key in software development, so I'm sure to return to the drawing board sooner or later. In the meantime though, this design will help make my code easier to maintain. This little diversion has slowed me down for a bit, but I think it'll be worth it regardless. Since I'm still making pretty good time right now, I can also afford to spend time on these sorts of things. As the Roadmap page shows, I'm getting pretty close to my first milestone!

4/15/18

Halberd: Questions and Answers

If I had to pin a core theme on the first two weeks of Halberd's production, it would probably be "Raising Questions". As I expected, the nature of the project has forced me to think a lot about how to use DFGame properly. Because this project is both very different and much larger than previous any work I've made using the framework, many unknowns in DFGame are being brought to light for the first time. Let's discuss a couple of them!

Modules

With DFGame, it was always my goal to add less 'core' features as optional modules. I had a pretty good general idea of how this was going to work, but I'd never actually tried doing it until recently. I needed a new DFGame module for handling tilesets and tilemaps in Halberd, so I finally gave it a shot.

I'm happy to report that it worked pretty smoothly! Everything mostly worked out of the box, even the OpenGL shader embedding Just Worked™ how I wanted it to with basically no modifications. The only thing that I had to figure out was how to properly use relative filepaths in Meson subprojects, and that only took about 5 minutes.

This good first impression was very reassuring, and has me excited to expand DFGame even more in the future.

Lost & Found

In less positive news, working on Halberd has also exposed a massive flaw in DFGame's design: None of the assets have any idea where they came from. In normal circumstances, this doesn't really matter. Who cares if that sprite doesn't know where it loaded its textures from? As long as they're correct, the game will work fine regardless. Even in a level editor, it doesn't matter too much (since you ought to be using the same backend as the game anyway).

Unfortunately, this information is vital when building something like Halberd. After all, how could you possibly update a tileset, when you have no idea where to save it? Even if you track the path you passed to the load function, that won't help much when you realize that you also need to write the texture's filepath in the same file.

Clearly, this is a pretty major roadblock. There are a few ways to solve this problem, but I'm still considering my options. I want to be sure that the choice I make here won't screw me over later.

Conclusion

It may seem negative to see new problems crop up, but I see it as a positive. The sooner I'm faced with unknowns in DFGame, the sooner I can test them (and fix them if needed). I don't expect anyone else to ever find and use DFGame, but on the off-chance it happens someday I'd rather have all the big questions ironed out ahead of time. In the more immediate future, having the answers to questions like these will also simplify any future projects with similar needs.

Besides the occasional trip-up, progress on Halberd's MVP has been going smoothly so far. Since I'm writing this update, I may as well post a progress screenshot while I'm at it. Here's the current state of the tileset editor:
Click the image to view a larger version
It's not the prettiest, but I think it's a pretty solid MVP-level feature. Now, I just need to keep going and finish the rest!

3/31/18

Halberd, and the Roadmap

I've spent the first three months of this year making a new game and doing bits of research. Now, I think it's time to start working on something a little more long-term again. The Halberd project was put on hold back in college, and the DFGame rewrite prevented me from picking it back up last year. With a fairly clean to-do list in front of me, now's the perfect time to get back to it!

Halberd What?

It has been a couple years since I did or wrote anything substantial about Halberd, and the original attempt began nearly 5 years ago. With that in mind, here's a quick refresher on what the project is.

Halberd originally started as an attempt to make an old-school JRPG in LÖVE, then rapidly ballooned into an attempt to make a more general JRPG engine and tools, still in LÖVE. The project was put on indefinite hold, and I eventually picked it back up as a sort of open-source RPG Maker alternative developed in C and Vala.

That final design has held. My goal with Halberd is to produce a complete and polished open-source RPG engine, with an editor and all other associated tools. I want to produce something simple enough to enable someone with no previous programming or gamedev experience to make RPGs, but flexible and feature-rich enough to be a serious consideration for a more experienced developer.

Of course, I also want to make some games of my own with it!

Scoping Up

One thing that I want to do with this new attempt at Halberd is an increase to the project's scope. This may seem rather foolish, but there is a reason. I've played a lot of games made with various engines and tools, and I've noticed that many games made with engines that are too restrictive often end up either feeling generic, or fighting with the engine to produce a unique but half-baked result. This is not to say that all engines should support all types of games, but I think there's some value to be had in supporting a collection of related genres, rather than a single narrow game type.

Ultimately, I want Halberd to provide good support for 4 types of games:
  1. Old-school turn based JRPGs. The obvious example here is any Final Fantasy game prior to 7 (and much of Square's old catalog in general), but this genre covers a wide swathe of games. This is what Halberd was always meant to support, as a theoretical alternative to RPGMaker.
  2. Old-school action RPGs, like the Mana and Ys franchises. I would also place the Legend of Zelda franchise here due to its mechanical similarities, although many people have differing opinions on that one.
  3. Turn-based strategy games, specifically in the vein of the Fire Emblem and Advance Wars franchises.
  4. Graphical Roguelikes such as Dungeons of Dredmor, Nethack (in some variants), ToME, and the Pokemon Mystery Dungeon games.
I selected these four genres because I believe they have many overlapping features. In my mind, it seems reasonable for a less experienced developer making RPGs to want to add more action-oriented gameplay, strategy aspects, or even procedural dungeons. By supporting several genres, I can help this theoretical dev implement their desired mechanics in a less janky fashion.

To back up my choice of genres, I've also produced a Venn Diagram to try and show where I see overlap between the listed genres. I know that there are plenty of exceptions, but I think it still does a good job highlighting some common shared aspects and mechanics:
Click the image to view a larger version

A Change of Strategy

In theory, I've convinced you to accept my rationale for this major scope increase. Now, here's my plan to pull it off. I have enough experience to know that an overly large scope can easily bog down or kill a project, so I'm going to break up this task into smaller parts to improve the overall chance of success.

In the past, I've typically had a "release when it's done" attitude, which results in long periods of development followed by either complete releases or major updates. Case in point, the period between when I announced that I was working on DFGame and when I finally made the first release was 22 months. This time around, I'm going to start with a Minimum Viable Product, and follow that up with numerous smaller updates to give myself regular milestones to hit and stay on track.

In the short term, the MVP release will be enough to make a map the player can walk around and fight monsters in. No skills, levels, items, or dialogue, and only the bare essentials of UI will be present. Once that's done, I'll produce a small demo with all the features, and expand from there until I have a fairly flexible and robust featureset for turn-based RPGs only (in other words, the original scope of the project). In order to ensure that the engine and tools work in practice, I'll be working on a full-length JRPG at the same time. Once both of these things are done, I'll slap a 1.0 on the project and begin work on supporting additional genres and mechanics in largely the same way.

With this method the scope increase isn't going to impact development in the short term, instead existing as a reminder to keep features flexible and open for further expansion.

The Roadmap

With this post, I've also made a new addition to the site! I'm trying to only post when I have something interesting to write about, but I still want there to be an indication that I'm working on something when I'm busy (such as the period of relative silence when I was busy with Cloudy Climb). To that end, I've rolled out the new Roadmap page to show progress on larger projects.

Every project tracked on the Roadmap page will have:
  1. A graph showing the status and relationships between tasks
  2. A changelog of task updates, blog posts, and releases
  3. Various associated links
  4. No official release dates or promises. These pages will track my progress and general plans, but nothing on them will be truly set in stone.
For the time being, Halberd is the only tracked project. As I pick other larger projects back up, they will also be added.

I already use graphs to map out some of my projects in private, so I thought it'd be nice to use them to show progress in public as well. It also lets me keep a public log of my work. I'll be updating the Roadmap page once a week, provided anything on it needs to be updated.

3/10/18

Cloudy Climb -- The Announcement and Postmortem Double-Feature!

Hello again, readers. It's been quiet around here lately, but that changes today. For the first time in quite a while, I'm releasing a brand-new game! The game is called Cloudy Climb, and it's--wait a second, we've done this before!


Not Quite a Remake

Yes, that's right. I've made a second Cloudy Climb. Like most of my projects, I was never really happy with the original. More importantly, I was in the mood to make a game. I've been working on this version for about 2 months, and I think it's finally reached a point where I can call it 'done' and not feel bad about it.

You can get the game via the widget below, or take a look at the git repo here.



A Postmortem for Our Dear Prince

While I still have your attention, I'm going to do a write a quick postmortem for Cloudy Climb. Postmortems are a very useful tool that I don't use nearly often enough. So, let's get to it!

The Story

I started Cloudy Climb during the last week of December, mostly because I was bored. After DFGame and Singularity taking most of last year, I was in the mood for some simple game development. I also wanted to see how well DFGame would fare under Game Jam-esque constraints, so I set myself a time limit of 1 week.

As we're all well aware, it took a little bit longer than a week. I got the basic mechanic and some of the graphics done in a couple days, but I got sick around the 4 day mark. Since I wanted to make something decent (and this wasn't really a game jam anyway), I decided to spend a few more weeks taking the game to a more finished state. Then, I just decided to take "as long as I need" to get the game into a relatively solid finished state.

In late January, when the game was really starting to come together I finally revealed its existence to some of my friends. Besides being friendly, I primarily did this to gather feedback. I started with this video:

...And slowly polished things over the course of a few more:


With the feedback gathered from my work, I completed the remaining assets and now we're here!

What Went Right?

  • Feedback! I'll be gathering more of that in the future. My friends caught a lot of little things that I was able to fix ahead of release. For a good example of that, listen to the stage end jingle in the last feedback video. One of my good buddies pointed out that it was too drawn-out, and I ended up cutting the final note out. I think it sounds a fair bit better as a result.

    There's also the really nice spike animation, which involved a bunch of critique passes in a pixel art community I found. I think the difference of quality there is very clear compared to the rest of the game's art.
  • Field Testing! One thing that I got out of this that I find really valuable is the experience of using DFGame on a non-trivial project. It's been really enlightening, and I'll be making (and in some cases, have already made) several changes to the API as a result.
  • Requirements! Because of this project, I was finally forced to get off my butt and learn audio. I'm still very bad at music, but I still think much of the game's audio is a good step up from previous games. I've taken the first step, now I just need to keep practicing.

What Went Wrong?

  • Rushing! A number of the assets could be much better, but after spending the better part of a weekend just making that spike ball I decided to try and make things "good enough" and move on. Frankly, it shows! Most of the art is pretty ho-hum, and it could've been much better if I'd taken the time to flesh it out and get critique. This was supposed to be a quick filler project, so I'm not too upset at the quality, but it's still a clear weakness.
  • Procrastination! I spent a long time finding tasks that didn't involve audio to do. This resulted in my last few weeks being almost nothing but music and sound, which got old pretty fast. It also means that the part that was my weakest skill also got the least amount of dev time! If my old drafts are any indication, the music would probably have been significantly better had I been iterating on it from early in the production.
  • The Core Design of Your Game, You Numbskull! So this is kind of a big one: Cloudy Climb's concept is pretty awful. The game works pretty well as an "infinite runner"-style game like the original, but the value doesn't translate well to a level-based platformer (in my opinion) for a few reasons:
    1. There's very little room for 'soft' failure states. For obvious reasons, messing up your movement always means death.
    2. Your character's only means of interaction with the world are 'bounce' and 'bounce, but moreso'. One could envision a game with one or two additional player actions, but the base concept pretty much requires one of the primary actions in the game to also be the basic movement.
    3. The game is extremely vertical, but the platform (PC) uses a horizontal aspect ratio. What's more, you move up and down pretty quickly thanks to gravity. A metroid-style camera would've helped, but I don't think it could've magically fixed the problem.

Takeaways

So the game didn't come out great, but at least most of my sins are pretty fixable, and a quick gander at this ancient postmortem indicates to me that I'm capable of learning from my mistakes. I put off much less of the content this time around, my code was perfectly fine, and I had a tight scope that grew organically to fit my needs and capabilities. Much like the game, the development process was distinctly not terrible! So here's my big lesson:

Iterate and get feedback on your big mechanic from the start, and make sure that your game is always presentable. That means taking the time to make assets (or at least decent placeholders), to ensure that you're always engaging with every aspect of the work and not leaving anything for the end.

There's More!

Even though this project is finished, I'm not moving on just yet. During the project, I found a few bits of technology that I want to explore, and this seems like a good opportunity to do just that. I'll be using this game as a testbed to get a feel for them, then I'll move on to something new. I also got an idea for a short tutorial/informative article based on some of my work on Cloudy Climb, so I'll be working on that as well.