4 Hugues Ross - Blog
Hugues Ross

3/10/19

Halberd - Actors, Part 1

One of my goals for this month is to get myself back on the right track with Halberd's development. To recover from my little detour, I decided to implement one major new feature: NPCs. So far, I've had some good success!

Defining The Problem

Before starting, I decided to put together a to-do list of sorts. My overarching goal is to have placeable characters that the player can talk to, and in the following two issues I laid-out a general roadmap for the feature as lists of sub-tasks.

I broke my goal in two because I felt that I had a good strategy for separating dialogue from NPCs: By making dialogue part of Halberd's existing collection of triggers, I could design NPCs in a way that would make it pluggable later without any effort. The final design of NPCs (now called Actors) is very similar to Halberd's trigger volumes, but with different criteria for triggering actions.

The process of getting actors in place was uneventful, so much so that I apparently forgot to take any screenshots! Oh well, better luck next time.

Hitting A Snag

Once actors could be added to maps, the next problem was making them trigger actions when the player collided or interacted with them. This turned out to be much harder than anticipated, but not for the reason you might expect.

DFGame's property grid is still very young, and I've been trying to limit my work on it to features that I actually need. At the time that I started on actors, the property grid was completely static. That meant no triggers, because triggers have different fields depending on what they do. So, before I could finish my actors I had to revamp my property grid code accordingly.

In the end, I refactored the code and added support for the <choice> XSD element. This took a little over a week on its own, so I did take a few screenshots:

 Before

Click for full size

First Draft - Initial Support

Click for full size

Second Draft - Style Fixes

Click for full size

Third Draft - Changeable Element Types

Click for full size

Final Version - Slightly simplified UI

Click for full size

 

Wrapping Up

The new possibilities offered by <choice> gives me pretty much everything I need to convert the rest of Halberd's UI to use the property grid. With the new tech in hand, I finished adding actor triggers then merged the actor and trigger editors into a single 'Objects' tab. I also converted the encounter list while I was at it:
Click for full size

Let's Talk

The first step to adding dialogue is getting a trigger in place to do it:
Click for full size

That's the latest thing I've accomplished, so my next move will be to get that text on-screen. To that end, I'm looking into merging my UI work so I can get some pretty dialogue boxes in place.

Once that's done, I'll be making a proper editor for dialogue trees. In addition to letting devs add more text, I also want to add support for choices and triggers in dialogue. The latter in particular excites me: It'll let dialogue have a real effect on gameplay, while tying into future additions (such as items and plot flags) very well.

Watch this space for a follow-up!

2/24/19

Halberd Studio - Priorities and Time

Hello again! Despite 2 months of work, this is somehow my first post of the year. I've got an even deck of good and bad news, but nothing too major on either side.

Tilemap Upgrades

Let's start off with the good stuff. While the task splitting that I started late last year has been slowing down direct progress, it has also given me the opportunity to make some nice improvements elsewhere. During the past few months, I've put some effort into improving the tilemap editor. I'll go through the changes below, but let's see what you can spot first:

Click for a full-size version

Grids

The first thing I added to the tilemap editor this year was a tile grid. A grid overlay may seem like a humble addition, but it makes judging distances and lining up elements much easier. Pushing the feature even further, I also made it fully customizable:

Click for a full-size version
With several different line styles, and any color(s) you want, there's a good chance that you can find a grid that fits the maps it overlays. With that said, the grid can also be turned off if you prefer a clean-looking map.

New Tools

To complement the existing pencil and bucket tools, I added tools for placing lines, rectangles, and ovals. All of these tools can be modified with ctrl/shift as you'd expect coming from most art programs, so the result should be pretty straightforward when people pick it up.

I also took the opportunity to re-use the line code to add 'connected drawing' to the pencil tool, so quick strokes won't leave holes behind!

Previews

Of course, those tools wouldn't work well if you couldn't see what the results. To that end, I also made all of the tools preview their effects before placement. Before, you could only see the new tile directly under your cursor and it was deceptively easy to flood-fill a tile that you meant to place normally. Now, it's blindingly obvious what will happen so I expect fewer slip-ups.

Priority Issues

As I mentioned at the top, there is some bad news to go with the good. Progress on new features has been excruciatingly slow, mainly due to prioritizing the wrong tasks. I've been slowly realizing this for a few weeks, and I'm finally changing directions.

Right now, there are two main improvements that Halberd needs. First of all is NPCs/dialogue. Without characters and text, it's hard (though technically possible) to tell an engaging story. NPCs can also do a lot of other things in an RPG context, such as selling items or providing avoidable combat instead of random encounters. Second is adding depth to the available combat systems, through skills/items/etc. Such additions can give the player options beyond 'attack' and 'run', and allow for more interesting challenges.

What I think happened is that I looked at both of these possibilities, and saw a common thread: both of these require some UI work. So, instead making direct progress on these tasks, I started working on a fully customizable UI system. At the time, I figured that giving developers the tools to dictate how the UI looked and worked would allow for more possibilities with these features. However, this system turned into a time sink that blocked my progress for a few months.

Don't get me wrong--custom UI is a real feature that Halberd will need. It just isn't the right task for the moment. On the upside, what I did make can still be used even if it doesn't offer much yet.

Next Steps

Whether or not I learn my lesson remains to be seen. With that said, I think the next feature that I'll work on is getting NPC support in. With my tilemap editor upgrades done, it feels like the natural path to take. Ideally, I'd also like to work NPC interactions and dialog into the existing triggers. I think doing so will greatly expand the possibilities that these new features add.

12/31/18

2018 End of Year Wrap-up

Here we are, at the end of a new year. It's crazy how quick these years go by nowadays, but at least I'm still getting plenty done! Let's jump right over to some accomplishments:

Cloudy Climb

DFGame had its first field test this year, with a little platformer called Cloudy Climb. The game was very short and not great, but I was able to get things done without too much trouble. I'm in the mood to make another small game this year, but I haven't decided when. I'm focused on bigger stuff right now, so it'll probably happen much later in the year.

DFGame

On that note, let's look at DFGame. Since last year, DFGame has received dozens of improvements and 2 new modules. Despite the progress, I haven't made a new version since May. At this point, DFGame feels like it has made enough changes to consider a 2.0 version release. For the sake of making it a good one, I want to polish a little longer.

Halberd

This year also marked a return to my longest-running project: The Halberd RPG engine! This attempt is shaping up better than the previous ones, so hopefully things will continue to go smoothly next year. I'm not ready for a source release just yet, but it'll probably happen within the first 6 months of 2019.

...What about Singularity?

I've been awfully quiet about other projects for a while, and Singularity hasn't seen much attention since the release back in January. I've grown quite a bit as a software dev since then, and I want to make a cleaner and more polished release. I've scheduled an v0.4 release for next June, though obviously that date isn't a guarantee. I'll be focusing on bugfixes and polish this time around, since most of the important big features are already working.

A Little More

I didn't just spend all of 2018 programming (though I'll admit that was most of it). I also made some art! Following up on last year's attempts to learn pixel art, I kept practicing and improving. I'm not a great artist, but I'm miles ahead of where I began at this point. I can't wait to see what the future brings in this regard, who knows how my games will look in a few years!

On that note, I drew a few more things to cap off the year:
I'm also planning to look into a few other styles of art, such as digital painting. I think expanding my view of art will help me grow my style in general, so there may be more than pixel art around here a year from now...

Next Year

Besides the obvious, I have a few extra plans for 2019. I'd like to take dflib and fold it into the dfgame ecosystem, probably as its own set of high-level modules. This will not only give me an excuse to update and fix up dflib, but it'll also let any of my existing dflib projects to pick up any dfgame features they want. Most won't be useful, but there are a few interesting possibilities like audio notifications.

I also have another little something that might happen with dfgame later. We'll see about that...

12/25/18

Halberd: That's my property!

To anyone reading this on the same day that I post, Merry Christmas! Here's a little present: This year's final Halberd-related blog post.

Of my current priorities on Halberd, one of the biggest is building and integrating a property grid. I think this is a very interesting endeavor, and hopefully you'll see it the same way!

So what's a Property Grid?

When I spoke to some (programmer) friends about this, I was surprised to find out that some of them didn't initially know what a property grid was. So, let's start with definitions.

As the name implies, a property grid is a ui widget that lets the user inspect and edit the properties of an object. It usually amounts to a list of named fields, and you can find one in just about any game engine. Here are a few examples:

UE4's 'details panel' is a form of property grid
As expected, Unity's inspector panel is another good example
The ActiPro Windows UI framework also features a property grid
The GTK UI builder, Glade, also features something in this vein

If you're a game developer, you've probably figured out by now that property grids are a really important game development tool. This is even more true in RPGs, due to the large amounts of 'database' assets which lend themselves well to this type of UI pattern.

Digging deeper: How does a property grid work?

Like any programming problem, there are many ways to implement property grid functionality. However, I'd put most methods into one of 3 groups: Inspected, Declared, and Fixed. These are just personal categories, not proper terms, but I think they showcase some real differences.

An Inspected property grid assembles itself by looking at real game data and converting it to ui. This is typically done through Reflection, either by looking at data in a scripting layer or with a language that natively supports this, such as C#. For languages that can't do this out of the box, a dynamic class/property system can be added on top of the normal code. Examples of such systems can be found in Unreal Engine 4 and the GObject framework.

A Declared property grid is also dynamic. However, instead of inspecting objects at runtime it queries their information from a predefined source, such as a schema or similar descriptive document. Then, it sends data back and forth via Serialization instead of reflection. The result is less flexible, but it's also simpler and the underlying game code may be more performant since dynamic properties aren't necessary.

Finally, there is the Fixed property grid. I call this a property grid, but that may be an overstatement--this grid is essentially just a hard-coded bit of ui for interfacing with an object. By its nature, it's quite simple and totally static. Of course, it's also difficult to maintain and requires constant updates as the underlying data changes.

Depending on your use-case, any of the above can be valid approaches. The fixed solution may seem bad, but sometimes it's the best option: You don't need a powerful and complex solution just to edit a couple of fields.

What have I got?

At the moment, Halberd is stuck with the fixed style. I went for this solution early on to avoid getting bogged down while developing my proof-of-concept, but the scaling problems of this approach are starting to appear.

The general process of adding a new property to an object right now is:
  1. Add the property
  2. Add serialization for saving/loading
  3. Add simple getters/setters for editing
  4. Add the property to a Vapi file for interop access
  5. Add the property's editing widget to the ui file
  6. Add the widget code to the editor's vala class, including the signals for changing the property
That's a lot of steps for one property. With a simple property grid, I could skip steps 3-6 entirely and greatly streamline my development process.

A new property grid

With all that in mind, I decided to try out something better. Since most of my code is C, the declared style is necessary. But how to prepare the meta-information about the properties? In my case, it was actually rather simple. Since I already serialize my data to XML, I decided to go with the obvious option: XSD.

For the uninitiated, XSD is an XML-based schema standard for describing other XML files. While intended for databases, with a few additions the result can work quite well for defining a property grid!

The result looks like this:
You might recognize this as DFGame's editor demo which I completed last year. The controls were hard-coded since it was just a viewport showcase at the time, but now the editable parts are totally data-driven!

The schema that the editor is based on is a bit wordy, but pretty straightforward:
    1 <xs:schema
    2     xmlns:df="/org/df458/dfgame"
    3     xmlns:xs="http://www.w3.org/2001/XMLSchema"
    4     elementFormDefault="qualified">
    5     <!-- Types -->
    6     <xs:simpleType name="fill_type">
    7         <xs:restriction base="xs:string">
    8             <xs:enumeration value="true" df:displayName="Filled"/>
    9             <xs:enumeration value="false" df:displayName="Wireframe"/>
   10         </xs:restriction>
   11     </xs:simpleType>
   12     <xs:simpleType name="size_type">
   13         <xs:restriction base="xs:float">
   14             <xs:minInclusive value="0"/>
   15             <xs:totalDigits value="6"/>
   16         </xs:restriction>
   17         <xs:annotation>
   18             <xs:documentation>A decimal value above 0</xs:documentation>
   19         </xs:annotation>
   20     </xs:simpleType>
   21     <xs:simpleType name="degree_type">
   22         <xs:restriction base="xs:float">
   23             <xs:minInclusive value="0"/>
   24             <xs:maxExclusive value="360"/>
   25         </xs:restriction>
   26         <xs:annotation>
   27             <xs:documentation>An angle in degrees</xs:documentation>
   28         </xs:annotation>
   29     </xs:simpleType>
   30 
   31     <!-- Triangle struct -->
   32     <xs:complexType name="triangle">
   33         <xs:attribute name="size" type="size_type">
   34             <xs:annotation>
   35                 <xs:documentation>The size of the triangle</xs:documentation>
   36             </xs:annotation>
   37         </xs:attribute>
   38         <xs:attribute name="angle" type="degree_type">
   39             <xs:annotation>
   40                 <xs:documentation>The angle of rotation</xs:documentation>
   41             </xs:annotation>
   42         </xs:attribute>
   43         <xs:attribute name="color" type="df:color4">
   44             <xs:annotation>
   45                 <xs:documentation>The color of the triangle</xs:documentation>
   46             </xs:annotation>
   47         </xs:attribute>
   48         <xs:attribute name="is_filled" type="fill_type" df:displayName="Style">
   49             <xs:annotation>
   50                 <xs:documentation>Toggles filled/wireframe rendering</xs:documentation>
   51             </xs:annotation>
   52         </xs:attribute>
   53     </xs:complexType>
   54 </xs:schema>
One way to reduce the workload even further would be to tie this into a code generation system, but that strikes me as overkill for the time being...

What now?

I've been working on this feature for a few weeks now, but I finally merged it into DFGame's master branch yesterday. The next step will be to try and integrate it into Halberd, I'm sure there'll be more to do but I think this feature is a good investment for future work! Once the property grid's in place, the work will hopefully start moving a bit quicker.

12/4/18

Art, Take 2

Exactly one year ago, I posted some images showing my progress practicing pixel art. I've continued practicing since then, and I think the results are quite solid!

Let's get started with a quick review of the past year. Unlike last year's mostly unstructured practice, I've tried to aim for a few weaknesses in my art fundamentals and improve them. The main core skills I focused on were light and perspective, though I've been tentatively playing with anatomy and proportion lately. I also joined a couple of pixel art communities, which have been a very helpful source of critique.


With the stage set, let's make a few direct comparisons to last year:

Trees


Rocks


Tilesets

Click the image for a full-size version

As you can see, I've made some pretty good progress! Of course, I did quite a bit more than this: Here's an album with some of this year's finished work.

If you're interested in seeing more as I continue practicing, I occasionally post work on Twitter and Pixeljoint.