4 Hugues Ross - Blog: Updates
Hugues Ross
Showing posts with label Updates. Show all posts
Showing posts with label Updates. Show all posts

8/13/19

Back to the Maze - 4 - Hey, it Works!

Hello again!

I wasn't expecting it to go so smoothly, but I got AMAZE's rewrite to a point where it mostly works. At the very least, every level is fully playable at this point so I feel happy enough calling Stage 2 of my plan a success (and in just a month and a half, if you ignore how long it took me to sit down and write this)

But how did I do it? Let's talk strategy:

1 - Data

My original goal for this stage of the project was to get the games final data files loading and running in the new engine, but I very quickly abandoned that idea in favor of loading the source files instead.

The main benefit of this change was greatly simplifying the asset loading process. Instead of handling custom compressed binary files, I just had to deal with simple text and xml. Many of these files were similar to existing formats in DFGame, so loading them was pretty easy.

2 - The Critical Path

I thought a lot about how to approach the problem of recreating the game, but in the end I decided to simply play through it. By visiting every level, I could implement just the parts that were necessary to make the game function and ignore the rest, which was another good speed boost.

3 - Writing Bad Code

I think terrible code is underrated. No-one wants it in their codebase and it has a very high maintenance cost, but ignoring quality allows for lightning-fast initial development speeds. Even at work, I usually start by hacking together the "naive solution" to quickly get a prototype in place that I can then redesign to better fit with existing systems.

I applied the same concept here. Since I'm already planning months of cleanup, polish, and refactoring, I just wrote the cheapest possible recreation of the original I could. I'll be paying that debt back soon, but I'll be doing it with the luxury of a working copy.

Like a finely-aged...steak

Since I had to play through the game for testing, I can also give a verdict on the original content! I hadn't touched this thing in forever, so I came in totally fresh. And let me tell you, it sucks!

I remembered that the game was lacking in polish and some challenges were too tight, but but the latter was much worse than expected. Looking back, I think there are two even bigger problems:
  1. Minimal Checkpointing - AMAZE is sort of a hybrid action/puzzle game, but there are no in-level checkpoints. Replaying an action sequence isn't too bad, but following the same steps to complete a puzzle after dying feels pretty bad. (The fact that resetting a level when stuck costs a life is also bad)
    Additionally, running out of lives is very easy and a game over can push the player back pretty far.
  2. Blindness - A lot of puzzles suffer from not showing the player enough in-game. This becomes especially obvious in some later areas, especially with ice puzzles. There are multiple places where the player has to run into areas full of deathtraps, completely blind!
Naturally, the result is a really un-fun game. If I want to make the new game a success, I need to keep these points in mind.

Planning My Approach

As you may remember, the next two stages are about refactoring the new code into something solid, and building tools to produce the new data. Before I can do that, I need a better idea of what to do with this game.

With that in mind, I'm taking a break from the project for a little while. Now that I have it running with newer libraries I can worry a little less about compatibility (though I don't plan to stop long enough for that to be an issue), so I'm going to spend some time on a few other projects and come back to this with some fresh ideas later.

My next post be about one of those projects, which is already released!
Stay tuned.

6/11/19

Back to the Maze - 2 - Setting Our Sights

I had my fun in the last post, now it's time to get a little more serious. If I want this project to be successful, I need to plan a little in advance.

What Do I Want?

Before jumping deciding into this project, I think it's worth stepping back and deciding if I really want to do this. In this case, it's not actually a hard decision to back up. I was never really content with how the game wound up the first time around, that much is made clear by the release and postmortem. I've toyed with the idea of remaking the game for several years, but it never really felt like the right time. With Halberd shuttered, my slate is now pretty clean.

My drive here is pretty simple. I think AMAZE was a fun concept, but the execution was really lacking. With my vastly improved programming and art skills, I think I'm in a good position to do it justice. That informs my goal:

"Take the original concept of AMAZE, and turn it into a fun and polished result"

About the Project

Overall, AMAZE is actually on the smaller end. At almost 4kloc it's slightly bigger than Cloudy Climb, but dwarfed by Halberd and DFGame. Besides the antique rendering, it has a few odd quirks:
  • A custom scripting language, which looks like this:
    Component Physics yvel 0
    Component Physics xvel 2
    Wait 48
    Component Physics xvel 0
    Component Physics yvel 2
    Wait 48
    Component Physics yvel 0
    Component Physics xvel -2
    Wait 48
    Component Physics xvel 0
    Component Physics yvel -2
    Wait 48
    Repeat 
    • And yes, those times are measured in frames
  • A data-driven pseudo-ECS, but with (originally) no concept 'prefabs'. Besides some later parts of the project, every object in every level was made by hand.
    • And where prefabs were made, the files looked like this:
      Body
      0 4 0 0
      Collide
      ?P Kill . !c Info solid false = Destroy .
      Sprite
      Obstacle.spa:Cannonball
  • A sprite format that looks rather similar to DFGame's, but with separate images per-frame instead of spritesheets. This was the original prototype that eventually led to DFGame's (improved) sprite assets.
  • My first ever attempt at graphical development tools, in the form of a simple asset exporter. This was needed, because the asset format is compressed binary for some reason.

Baby Steps

Starting over completely from scratch doesn't seem like a great idea. Instead, my current plan is to handle this remake in stages:
  1. Mockups
  2. Recreate the engine, and get the original game's data working in it
  3. Upgrade the engine, adding features and replacing the godawful custom scripting language with something sane
  4. Build simple development tools, validate them by remastering the original game's content with new assets
  5. Build a better game with the result, and include the redone original levels as a fun little bit of side content
This is a fair bit of work, but I'm optimistic because it's broken up into concrete sub-projects with well-defined endpoints. If I ever get tired of the project, I can just wrap up the stage that I'm on and set it aside for a while.

Looking Deeper

Just making a list is all well and good, but I think it would be good practice to try and predict the future. My predictions are often wrong and I don't believe in ship dates, but it might be interesting to compare predictions with reality as I progress.

Mockups

As I mentioned in part 1, this all sprung from a desire for mockups. Since that was my original goal, it stands to reason that I should do that first. This is a simple art project, so there's no real risk here. I expect a couple weeks of work for a couple simple mockups, and judging by the original screenshots there's a solid guarantee of improvement regardless of what I do here.

Time estimate: 1-3 weeks

Recreate the Engine

This is an interesting one. Given that I'm changing language and underlying APIs, it's safe to say that I'm going to have to commit to a full rewrite. On the other hand, I don't have to worry about tools, exporters, or asset creation. In the old codebase, that's a modest 2.5kloc and I have a spec to build against.

On a third hand, there's one possible stumbling block: Asset loading. AMAZE had fully custom binary asset files (because of course it did), and I'll have to translate those into some DFGame equivalent when loading. This, combined with a custom scripting language and nonsense code, could create some problems. Just to be safe, I think it's worth padding this figure.

Time estimate: 3 1/2months

Beyond the initial engine rewrite, I'm not confident in any predictions. Stage 3 could last forever if I kept adding features, and beyond that requires more design and scope considerations. Still, what I've looked at here feels like enough to wrap up most of the year.

I haven't yet decided how I want to handle this project from a blogging standpoint. I know for certain that I'll be capping off each stage with a post, but I haven't yet worked out how much I want to do in-between. We'll see when we get there.

Next Time: Actual Real Progress

5/19/19

Halberd - Violently and Thoroughly Changing Directions

Hello all,

Today, I wanted to talk about a change of approach. Changing approaches is something I do a lot, probably because I'm not very good at project management. I've been taking a break from Halberd for a few weeks, and I'm starting to have some reservations about my current plans. The crux of my worries is the following question:

Why am I doing this?

In the original announcement, I gave two goals for Halberd:
  • An open-ended and vague "make a cool and polished engine"
  • Making some games
Goal #1 feels like a bit of a cop-out. Saying "I'm going to make an engine because I want to make an engine" doesn't really mean anything. Instead, let's focus on goal #2.

It's been nearly 14 months since I started Halberd. My longest-running finished game project, AMAZE, took roughly 9 months to build from scratch. It's safe to say that had I been focused on the goal of making games that I'd have finished, or gotten very far along with, one or two of them by now. Instead, I've been busy with Halberd. Why?

I think this is a problem that I've had before. It's really easy to get distracted by dreams of being a cool dude with a big flashy product, and wind up on a wild goose chase. DFEngine suffered from a similar issue as well, and I think both have something in common: Rather than treating the game engine as a means to an end (the game), they exist as standalone projects.

There's also a question of audience, the way I'm designing Halberd's workflow isn't optimized for my needs. Despite that, I'm the only customer of the project that I know of. I really should be building tools for myself first and foremost, since I know myself best and don't have a focus-testing budget.

Thankfully, the solution is very easy! Like any good parent, I will cut down the disappointing child immediately, and without mercy. That's good parenting, right?

Wait, you're just--

Yup. Halberd's dead forever.

As for those games I wanted to make? I'll make them. I don't need a complete GUI-driven game engine to make games, and the remains of Halberd may provide a helpful initial boost. If I succeed in my projects, I'll obviously also have a viable RPG engine at the end.

Win-win, right?

4/26/19

Halberd - Actors, Part 2

At the end of last month, Halberd's current iteration had its first birthday. I think that makes this my longest and most successful attempt so far! As I mentioned in my original post about Halberd, this has been a recurring project, something that I wanted to do for years but never managed to complete. Seeing a milestone like this is pretty nice!

That's enough celebrating though, it's time for dialogue.

Dialogue

As you might guess by when this is coming out, I missed my mark by about a week. Between taxes, a birthday, and a pixel art collab, I put a few too many tasks on my plate and the date slipped. I finished the feature, but then some health problems kept me from actually posting for a while.

It's been done for a while though! Dialogue trees can be displayed via trigger, and can have test boxes, choices, and even call triggers mid-dialogue. This obviously helps a lot on the storytelling end of things, making a coherent plot that lacks dialogue isn't easy.

The Editor

Right now, the dialogue editor is pretty bare-bones. It's just a property grid wrapped around a dialogue tree, with no special checks or previewing. As always though, the important thing is that it just works. Like all of Halberd's editors, I'll be making multiple polish passes over time to improve usability.
She's a fixer-upper

I think this is a good moment to also remind everyone reading this: This is the gain I was expecting to get from the propertygrid. Being able to will functioning simple asset editors into existence with next to no effort is what made the months of work worth doing. From now on, these basic 'propertygrid editors' are probably going to show up a lot when adding new features due to how fast they are to produce.

Frame Job

Another thing that you probably noticed in that video is the UI. There are still a couple of bugs to work out, but the system's in place and it's now possible to make a much nicer-looking interface.

The main goal that I was working towards with the UI was full layout customization, but right now it's restricted to just skinning the frames around various elements. It's a pretty standard '9-slice' setup, without any fancy bells and whistles, but it works.

Next Up Is...

Something different. I'm going to be changing gears a little, so that will wait for its own post.

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.

11/25/18

Halberd: What's a roadmap?

Since my last update back in October, I haven't touched Halberd's roadmap. The reason for this is simple: With a new work strategy, I wasn't really sure how I wanted to show and track progress. In the end, I quietly settled on using regular issues on the project's GitLab repo.

For the time being, I'm still keeping the code private. I'll make it public long before the first proper release, but I want a couple more months to get things cleaned up a little before then.

Now that all that's figured out, I think it's time to get back to posting. I have a couple of posts that I'd like to make before the end of the year, so things should soon liven up a little around here!

10/16/18

Halberd Studio: No Sleeping, Just Scheming

I didn't sleep last night. The cause had nothing to do with my projects, but I ended up thinking about Halberd for a few hours. The more I thought, the more I became certain: Something has to change.

If you read my roundup for September, you'll know that I actually made some decent progress. Despite that, I still have a lot of doubts. After last night, I re-read all of my recent posts and decided that a new strategy was in order.

There's a wall of text about my motivations between you and this strategy. Click here if you'd prefer to skip it.

...But Why?

Obviously, this is coming off as indecisive. Still, I came to an interesting reason to change things up. I wrote about a similar feeling in August. At the time, I wasn't happy with the game. I looked back at my first post on it, decided that my reasoning was still correct, and kept going.

As a refresher, here are the reasons I had for starting:
  1. Making a game is a way to validate that the tool works, by forcing me to engage with all of its features. If there are any bugs or missing parts, I can fix them before release. It also lets me see which features need the most love and which are 'good enough' as-is.
  2. Having games made in an engine is also good for proving its capabilities. Anyone can make game development tools, but if no good games have ever been made with them then they'll be a tough sell for other devs.
  3. Finally, games can also serve as a useful reference for anyone who wants to try Halberd out. I don't think anyone will at this point in development, but when people do start using it they'll have something to help them.
  4. Additionally, the large scope of Halberd makes it a real marathon of a project. I need to break it up with smaller game projects if I want to keep my sanity! Not all of my 'filler' will be made with Halberd, but it's still a convenient excuse to give the engine a workout.
I still think these points are sound. However, my current project isn't actually the best way to address them. Let's go down the list again:
  1. The first reason is spot-on. Making a game is a pretty solid validation process. Making a demo of the engine's features could also work for this.
  2. This point disqualifies a demo as a complete solution, but there's an important word in there: Good. A bad game won't convince anyone to use an engine, it may even turn them away.
  3. See point 1.
  4. Here's the other problem: I replaced one drawn-out process with a drawn-out process and a diversion that I didn't personally enjoy. Demos won't fix that, but I have some other plans.
'Henry' is not a good game. It won't be a good game, and I'd even go as far as to say that it can't be one. As I work on this project, I can feel the time I'm wasting. That has an impact on my productivity, and it's exacerbated by the fact that I was never really that interested in it. I knew that my options would be limited, so I tried to go as simple as possible. I also used the game to try a new post format. That's pretty much all I have to say about it, because there was nothing else to hold my attention.

Despite my lack of interest, I still want to make RPGs in general. I have a few 'real' ideas on the backburner, but Halberd just isn't ready for them. The engine is technically in an 'MVP' state because you can make a game with it, but it's not viable for anything serious yet.

The Plan

That last section went long, but it felt good to get it out. Next, let's talk solutions. Back in August again, I listed some wants. After re-reading them, I can confidently say that they mostly hinge on being more patient and giving Halberd the time it needs. Working solely on Halberd brings up the issue of fatigue, but nothing is stopping me from keeping my current 'alternating weeks' strategy. Let's run with that concept.

Halberd is a huge project, and there are a lot of very different tasks needed for its success. I've split them into roughly four different categories:
  • Foundations
  • Progress
  • Polish
  • Content

Foundations

Halberd rests on top of DFGame, and I've regularly had to dive in to fix issues and add features for the engine's sake. One thing that bothers me is that I never have enough time to polish all of this internal code. With the pressure of getting a feature to work so that I can finish whatever I started on Halberd, it's hard to spend extra time on code clarity, tests, refactoring, and so on.

Long-term, these things are necessary for a healthy engine.

Progress

The 'critical path' to making my dream games, if you will. This category represents the features needed to make a powerful and flexible engine, things like custom equations, items, cutscene and dialogue tools, etc.

Polish

Just getting Halberd to work well is enough for me, but to really sell (figuratively) the engine to the public I need to make sure that it also feels good to use. That means taking time to fix minor gripes, improve workflows, write help docs, and work on unifying the engine's look and 'brand'.

Content

I've never brought it up, but I think a big factor in novice-oriented engines is the quality and variety of the assets they pack in. I'm convinced that this is partly why so many people are attracted to RPGMaker, and also why some people look down on games made with it. Assets matter in the market that I'm planning to enter, and they're also a good source of practice.

If I spend enough time building my art and audio skills before I start my RPGs, I can make them truly live up to my expectations.

Conclusion

With some diverse long-term tasks prepared, the remaining question is how to divvy them up. Conveniently, I found out last month that I can get a couple solid features done per week. For now, I'm going to try focusing on each of these categories for one week every month. I'll keep this up until the end of the year, then I'll re-evaluate if I'm still not happy.

Looking further ahead, I'm about 5 1/2 months away from the first anniversary of Halberd's announcement. I don't think it'll be ready for release at that point, but I'd like to at least have some convincing demo videos by then! I'll also make the code public some time in the next few months, so that I can point people there for more detailed progress.

10/2/18

Halberd: September Roundup

It's been a pretty long month. A lot of general life issues cropped up, and I honestly feel like I didn't accomplish enough overall. I also didn't find the time to write any blog posts either, so I thought I'd try and go over the current state of things now.

Where we last left off, I was trying to find a balance between engine and game progress. For the time being, I've settled on alternating weeks. A single week comes out to be enough time to get one or two notable things done, so that seems to get me slow but steady progress on both projects.

Given that the aforementioned life issues probably cost me a week or two, it's hard to tell if the resulting development speed is actually acceptable. I'll probably have a better idea after next month.

State of the Game: Audible frustration

With all that said, I've actually made very little progress on the game. The main culprit is, as with Cloudy Climb, my complete lack of musical skill. I'm slowly improving but making music is still a difficult process for me. I think this problem will eventually go away, but in the meantime it's still a major roadblock.

I've made some progress on the art front, with a finished player sprite and the beginnings of the second area's tileset. Once the music problem is resolved, I should be able to keep going at a steady pace.


State of the Editor: Polish!

One of the things that concerns me about working on Halberd while making a game with it is how to resolve the potential for feature creep. Let's imagine for a moment that I decided to focus on adding NPCs to Halberd. If I succeeded, there would be a pretty strong temptation to add NPCs to the game as well. They would certainly make the game better, but they would also increase the scope of the final product. With enough features, I might find myself overextending the game way too far. Thankfully, I have a long todo list and many items on it have no effect on project scope. This month, most of my focus has been on UX and 'branding'.

UX

Improving the general workflow and looks of an engine is pretty much always useful, especially since Halberd is still so unpolished. So, I spent a couple weeks on making it look and feel better to use. I've been posting occasional screenshots to my Twitter account, here are a few for those who don't want to bother looking for them:
New landing page with a list of recent projects

Asset icons, and a new quick asset selection button

Settings split into sections, and a new vector editing widget with custom icons

There's more than this, but that covers most of the juicy bits. When the time to release this thing comes, I'll probably make another video in the 'walkthrough' style like I did last time.

Branding?

I've never liked branding, advertising, community building, and other 'tangential' aspects of development. This is probably because I'm not a social type, I prefer to sit in a dark room and create. However, reality dictates that if I ever want Halberd to be successful, I need to 'sell' it to its target audience.

Halberd will always be free (in every sense of the word), but in this day in age that's just not enough. I need to convince others that my work is worth using, and one part of that is building a consistent presentation and messaging. To that end, I decided to start thinking about this problem early.

"What should Halberd offer?"

This is an important question, one that I believe is core to making the engine more than just a technical success. A common question that I see whenever a new engine is announced is:

"Why use this instead of insert established competitor(s) here?"

I know that this question will come for me too, and I want to have a real answer ready ahead of time. I already discussed some of my motivations in my original announcement post, but I now have a pretty specific idea of where I want to take Halberd in the future.

Right now, I think there's still a divide between engines that are immediately accessible to newcomers and engines with modern and efficient development pipelines suitable for serious commercial work. Engines like Unreal and Unity have tried to style themselves as welcoming, but the fact of the matter remains that developers must learn to program to make much with them (yes, UE4 blueprints are programming). On the other side of the spectrum, some engines like GameMaker: Studio have tried to modernize and improve. This development is more interesting to me, but curiously a lot of more targeted engines (such as RPG Maker, SRPG Studio, Wolf RPG Editor, etc.) don't seem to have kept up as well.

Not that this has stopped developers, of course. I believe that good games can be made with any engine, but games are best made with a good engine. My hope is that Halberd can someday offer itself to RPG devs as an engine that's dead-simple to start, but offers enough power and depth to be ideal for professional-grade work. It can't live up to that dream yet, but I think having a strong vision from the outset will help ease people's fears.

Thinking about names

I like Halberd. It makes for a simple and memorable name. On the other hand, it's a noun that doesn't really describe anything. That's not uncommon in game engines, but I decided to try and find some other possible names.

To that end, I threw together a bunch of words that I could fit together to try and find something better. I mostly stuck to descriptive words like 'builder', 'editor', 'engine', 'game', 'rpg', etc. Most of the results didn't really impress me, but I do like the ring of Halberd Studio. It's not really any more descriptive or SEO-friendly, but it has a more official tone to me.

Given my end goal, it might be worth sticking to. My only concern is that there are already several 'studio' game engines hanging around, and throwing another one on the pile might not be a good move. I've keeping that name for now, but it's still not a final decision.

Next up

Looking back on this post now, I suppose September was actually rather productive! I'll probably try to focus a little more on the example game next month, since that hasn't seen as much progress lately. I still don't know how long it'll take to finish, but I'm hoping for some sort of official release before the end of the year. We'll see how that works out over the course of the next month or two!

8/20/18

Changing gears on Halberd

Right now, I'm in a bit of a difficult situation. My current game project has been taking much longer than I'd hoped, and I still haven't made a first release of Halberd. I don't make release dates anymore, but I'm still not happy with my current progress.

When I originally announced the game project, I acknowledged the risks and gave a few reasons why I felt the project was a good idea. Unfortunately, my arguments are still sound. The game has a reason to exist, and dropping it to speed up development doesn't strike me as a good option. So, I need to rethink my overall strategy.

What do I want?

When coming up with a new approach, figuring out I think it helps to consider what you want and why don't have it. The former helps you shape a goal, and the latter indicates the obstacles that you need to deal with to attain it.

In my case, there are a few things that I want:
  • I want Halberd to become a useful, successful game engine - That much should be pretty obvious, most people don't set out to fail.
  • I want to make good games - And, hopefully, have people play and enjoy them.
  • I want to make tutorials - To give back to the internet, of course!
On the surface, these goals seem pretty simple. However, I think the biggest reason why I keep running into problems is that these goals are in conflict with each other. And where does the conflict stem from? That's right, it's time! All of these goals are achievable for me on their own, but they're time-consuming enough that juggling them all is difficult.

Fixing the problem

Like with any other resource, the only ways to resolve a lack of time is to make more, or to use less. Making time isn't an option for me (besides quitting my job, which would be a terrible idea), so instead I need to find ways to balance time and quality.

I can start by striking tutorials from the list. I don't spend time on them now, and it's unlikely that I'll suddenly start later. That leaves me with just my programming projects, which are currently the main problem.

Another common option for reducing the time spent working is to collaborate with others. This is how most people cope with a lack of time, since dividing work isn't too difficult. However, freelancers are expensive (they need to live too, after all) and volunteers are typically less reliable. I don't want to shelve the idea entirely, but I think I'll at least need to save money or produce work that's more exciting before I can take advantage of this option.

Making Changes

In the end, I don't have any strong solutions to this problem. Working on one item to the exclusion of the other (as I have been recently) doesn't work well, so I need to find a way to reasonably balance out 'engine time' and 'game time' so that they can coexist. Here's my current plan:
  1. Go back to my regular posting non-schedule. I was using this game project as an experiment, but I'm not impressed by the results. I don't think I produced much interesting content, and I ended up spending a ton of time writing posts.
  2. Resume work on Halberd. I'm going to get started on the next release while this game project continues on the side, so that Halberd doesn't get bogged-down too much by side work.
  3. If I finish the next release of Halberd before the game, then I'll try to devote more time to finishing the game with that release. Otherwise (more likely) I'll wrap up the engine when the game finishes and release both together.
Future releases of Halberd will probably work the same way, with one game on the side dictating the engine releases. This lets me make plenty of games, but doesn't stop the engine dead in its tracks if the process gets bogged-down. In the long run, I'll probably also see if I can split things up in a more decisive manner with scheduling. That seems like overkill for the time being, so I won't try anything like that yet.

What this means for you as a reader is that I've split up the Halberd roadmap into two pages, one for the game and one for the editor. The blog will be getting occasional updates about both, and hopefully things will work out nicely!

8/16/18

Making the first Halberd game: Is this still a mountain?

Last time, I started building the actual first map for my game. A bit of messing around later, and...

I'm not really sure how to feel about this. It feels a bit noisy and chaotic, and it's clearly not very mountain-like anymore. Even running at my target resolution, the result is a little too confusing:

Clearly, I've over-corrected a bit. After simplifying the terrain a bit, I end up with this:

It's alright. I'm not thrilled with my results, but I think they look good enough. There's a line to be drawn in terms of polish and I've already spent a week on this map alone, so it's probably better to keep moving for now. If I feel a strong urge to do so, I can do another polish pass on the maps later.

...But Wait!

Unfortunately, we're not out of the foothills yet. After all, there's no music and no enemies! Given the fact that is is supposed to be a fairly short project and I'd like to avoid holding up Halberd's development for too long, I'm going to try sticking to more of a 'sketch' quality level, something like this:

This will be the combat background for the first area. It's rough and not really that detailed/attractive, but it's god enough to work as-is. If I can match this level of detail in the rest of my assets, it should be easy to complete the project quickly.

Moving on to the actual enemies, I need to keep the designs reasonably simple to draw as well. After all, some subjects are much harder to depict than others. To that end, I've made a couple simple designs for the first area:

They're not the most exciting creatures you've ever seen, but I think they'll work well as cute little monsters to deal with early on. Now I just need to add them in and take a crack at music, but that can wait for a future post. For now, I rest.

8/8/18

Making the first Halberd game: There's no math in this blog post, I promise!

In the last two posts I did a ton of math, all to make a squiggly line. That's peak efficiency right there, nowhere to go but down!

Anyhow, today will be a little more hands-on than that. To that end, I've produced a gorgeous tileset:

Being serious for a moment, this tileset should cover all of my basic needs for laying out a path. It has 3 colors, representing floor, stairs, and wall. For a  little winding path in the foothills of a mountain, that should be all I need to start with. Next up is the map itself:

This is the first time I've really been able to appreciate the scale of what I'm building. It's big, bigger than I'd really pictured in my head! And of course, I'll be building several areas of similar scale. It shouldn't be a problem, but man. That's a lot of map.

Well there's no time to spend crying over map dimensions, so let's dig in. First of all, I can cut out the margins...

...3 minutes in, I feel the sweet embrace of Carpal Tunnel Syndrome approach and hastily add a 'paintbucket' tool. Some limitations are just too harsh.

With that roadblock out of the way, putting together a path that mostly matches the calculations from earlier is child's play:

...it's not the most awesome map I've ever seen, but it'll serve as a good template to work with. Next, I abuse the properties of Manhattan Distance to make the path much more interesting with little change to its actual length:

After measuring, this path is pretty close to my 250 tile goal. Finally, I widen it out a little bit:

I can fix any errors and smooth things out as I go, so this feels like a pretty good base to work with. Next up, we need some art!

Art, and problems

Over the weekend, I assembled the start of a tileset for this mountain path:

One thing probably stands out here--There's a lot of brick, but not much natural stone or dirt. I tried a few rockier walls at first, but I had trouble getting them to look good with the rest of the tiles. In the end, I decided to go with retaining walls, as you might see in a couple spots on a well-maintained trail. I'll probably keep looking for a good rough stone wall for some of the higher parts of the trial, though.

Once that was done, I put the new tiles into the map and came to a terrible realization:

The walls have inconsistent heights, royally screwing up the perspective. It's blindingly obvious in retrospect, of course the edges of the terrain need to line up!

Unfortunately, this means that I have some fixing to do.....

8/6/18

Making the first Halberd game: Measuring foothills

In my last post, we did some simple calculations to estimate the amount of walking and combat to put into the game. Now, I'm going to use that data to do some real testing and level-building. But first, let's do a little more math.

Right now, Halberd's ability to resize maps is rather clunky. To make up for that fact, I want to get an idea of how big any given map should be before I make it. We can do this because we have the final length of the path the player has to follow: 250 tiles.

When in Manhattan...

The player won't have free movement in-game. Instead they'll be locked to the tile grid, with only north/south/east/west and diagonals available to them. Since position is locked, They're probably not going to take diagonals too often. So, we can get an estimate of our length using Manhattan Distance.

Unlike direct distance, Manhattan distance is just the sum of the distance on each axis. For instance, let's say your friend lived in a house 10 blocks north and 20 blocks west of you. With the Pythagorean Theorem, you could determine the distance "as the crow flies" to be ~17.3 blocks. But for the Manhattan Distance, you can just add the numbers together and get a distance of 30 blocks (the distance you're likely to walk to get there).

This can also work in reverse. Given a final length, we can subtract numbers from it to form a path, then add the segments on each axis together to get the dimensions of the map. It's hard to explain, so let me show you instead. Let's say we wanted to make a path that was 10 tiles in length. There are many ways to do this:

Even without drawing a box around these paths, we can still get their bounds by following them. Take the green one, for instance. It goes 5 units up, 4 to the right, then one more up:

Up 
  • 5
  • 1
Right
  • 4
If we add all of the numbers together, we predictably end up with 10. However, we can also add them in their respective groups to get 6 up and 4 across. Taking the first corner into account, that gives us a 5x6 area for this path.

So why are we doing this?

Let's get back to the spreadsheets. We already have a predetermined length, so we can get either of two things by picking the other:
  1. Map dimensions from the number/frequency of turns (as seen above)
  2. Ratio of up/down to left/right paths from a ratio of map dimensions.
For now though, we'll put this work aside. We can't make this decision before making some others first.

What is Area 1?

If we want to decide what our new path should look like, it would benefit greatly to know what the area should be like terrain-wise. I already know the answer, and so do you if you read the title of this post. However, I think the process is more useful than the solution.

Because Halberd is as limited as it is right now, a lot of my design decisions are derived from those limits. When I discussed narrative earlier, I brought up the transition from known/safe to the unknown, and used woods and plains as examples. In retrospect, I'm not fond of either solution:

Plains are generally very open and exploratory affairs. This can be great if exploration is the goal, but in a limited game with few mechanics on offer an open field isn't really that interesting. They also tend to be pretty sparse, which isn't a good first impression for a game that will mostly live or die on its environments.

Woods are fairly ideal in general. A forest offers a lot of opportunities for interesting environmental details, and trees are good for creating paths (and hiding little passages for keen eyes to find). However, such a solution won't work too well in Halberd's current state: With no layers in maps, we can't make tiles overlap anything. Not each other, and certainly not the player! As a result, an environment full of trees would be a nightmare scenario.

Clearly, I needed something else. I chose the foothills of a mountain for a few reasons:
  • On their own, the foothills of a mountain aren't as imposing or dangerous as the peaks. They also tend to have more greenery which helps lighten the atmosphere a bit.
  • Mountains seem to get used a lot as a symbol for a challenge or ordeal. So, starting in some foothills implies that the real danger is up ahead. To me, this fits well with the progression established earlier.
  • Mountain trails and the like are pretty restrictive. This presents the opportunity to add more interesting or complex scenery bits (translation: trees) where the player can't possibly reach and/or clip into them. Tile overlaps can be faked if you don't need tons of them, so it works for this situation.
Of course this isn't the only possible option, just the one I've chosen. Now that we know what the map will offer in terms of terrain, we can use this to get a general idea of the map's size. Since we're building a mountain trail, it stands to reason that we want our player to head up. This is especially true since making sloped tiles that work properly isn't yet possible in Halberd. However, most gentle trails have a lot of winding to them. If you look at any local mountains you'll probably see a long and circuitous 'easy trail' and a few more direct 'hard trails'. Since we want the first area to feel pretty non-threatening, I think it makes sense to have a winding path.

Whoops, more math!

Since the two ideas that I just outlined contradict each other, I think I'd like to see a fairly even map ratio. Unfortunately, getting the dimensions and path lengths will be difficult because the path winds back on itself. So, we need some more complicated calculations.

Lets say that we want a path that crosses the width of the map twice, like so:
Let's also assume that we know the path length (since in our real path, we'll know that too). In this case, we'll go with 100. Given that, the target map ratio (1:1) and the number of crosses, how do we determine the size of the map?

Since we have the width-height ratio, we can also determine the horizontal movement to vertical movement ratio by multiplying by the number of crosses. Better still, we can use this number with the total length to get the amount of horizontal/vertical movement and the width/height of the total map!

Let's try with a real example now. I want my 250-tile path to fit a map with a 2:3 ratio. So, I plug that information into this handy spreadsheet I just made:


Just like magic, I now have map dimensions! The 'pad' entries at the bottom represent the map dimensions with enough extra space to prevent the edges from scrolling onscreen. With this, everything is now in place to (finally) begin working on the map!

As a side-note: I think I'm starting to like spreadsheets a little too much. I suppose that's a fine quality for an RPG engine-builder, but still.....