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

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/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.

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.....

7/29/18

Making the first Halberd game: Were you sleeping in Algebra 1?

Where we last left off, I had gotten a pretty good idea of what the game would contain. Now that I've got an outline, The next step is to assemble it all into something playable. But first, let's do some algebra.

Math? In MY Level Design?

That's right! In the intro post, I mentioned wanted 8-10 minutes of gameplay. It's not much, but even this little can be tricky to reach if the levels aren't planned out with those figures in mind. (Unless the player is forced to grind, of course. Let's not do that!) The last time I tried making a similarly small game, I actually ended up short on content. This time, I thought it might be worth trying a more careful, numbers-based approach to avoid this problem.

The time that a player spends on this game can be summarized like so:
Time (total) = Time (walking) + Time (fighting)
-or-
Ttotal = Tmove + Tfight

We can break this equation down further. Movement time can be summarized as the distance traveled divided by the speed. Since this game has tile-based movement, we can get an estimated movement time like so:
Ttotal = (Tiles / Speed) + Tfight

Both of these variables can be controlled, one through settings and the other through level design. We can do the same for combat:
Ttotal = (Distance / Speed) + (Encounters * Turns * 2)

We can go further, and break down the encounter count too:
Ttotal = (Distance / Speed) + ((Distance * Encounter Chance) * Turns * 2)

In case you're wondering, your average turn lasts about 2 seconds. If we multiply the average number of turns by the average number of encounters, we can use that value to figure out roughly how much time will be spent in combat.

Bear in mind that these calculations won't be 100% accurate. They ignore a ton of variables, such as the player's level, how often they 'cut corners' by moving diagonally, how long they stop to think about things, and so on. Even so, I think it's a good method for guessing about how much the game needs.

Applying the Equation

Let's try solving the equation now. We want the game to last between 8-10 minutes, which we can replace with 540 seconds (9 minutes):
540 = (D / S) + ((D * C) * 2T)

This gives us a few variables that we can play with:
  • Distance
  • Movement Speed
  • Encounter Chance
  • Encounter Turn Count
Speed is the easiest value to test, so let's start there. In Halberd, speed is currently measured in pixels per second. I've already picked a tile resolution of 24x24, so I've set up some tests using multiples of that.
1 tile/s
2 tiles/s
3 tiles/s
4 tiles/s
3 tiles per second seems like a pretty good pace. 2 could also work, but I'm a bit worried that without a 'run' option it might feel just slightly too slow.
540 = D / 3 + (D * C * 2T)
1620 = D + (D * C * 2T * 3)
(1620 / D) - 1 = C * 2T * 3

With this addition, the easiest next step is to figure out how long the player should spend fighting. Given how simple fights are, I'd feel a little uncomfortable making them last more than 4-5 turns. So, I'm going to aim for around 4:
(1620 / D) - 1 = C * 8 * 3
(1620 / D) - 1 = C * 24
( (1620 / D) - 1) / 24 = C

Now, this only leaves the encounter chance and distance. Honestly, I'm not sure what I want to do for these two. However, we have simplified the equation enough to some real number-crunching. So, let's examine some possibilities with a spreadsheet:

Looking at these numbers, the distances in the 200-300 range look most appealing to me. For now, I'm going to start with an average of about 250 tiles of movement per area and a 2.5% encounter rate. For reference, 250 tiles is about 10 640-wide "screens" in size. It's on the bigger end, but considering the target time I'm going for it should fit rather well.

My next step would be building a test environment to try out these numbers for real, but my mouse is pretty much out of commission so that'll have to wait. I have a replacement coming in a few days, so I'll probably spend the downtime working on Halberd's code instead.

7/25/18

Making the first Halberd game: Story Time!

If you haven't read this post, do that now. I'll wait.

The first step to making a successful game is coming up with a good title, clearly. I spent a solid 10 minutes or so trying to think of a good legally-distinct title involving words like "dragon", "knight", and so on before remembering that I can just rename it later. So, let's just be lazy and call the game Henry for the time being.

Believe it or not, the second step to making a successful game is to make a new folder somewhere on your PC to put all the files in. Halberd can do that for me, or it could had I remembered to make it installable. Let's fix that now...

With that nonsense out of the way, we can start designing the game for real. Normally it helps to start a game with some prototyping, but that's not yet on the menu with Halberd. Instead, let's talk narrative.

Warning: Actual writers may want to skip this bit, to avoid the aneurysms my... process... will cause them.

Story

Even with a game as small and simplistic as the one I described before, it still helps to put together a little timeline of what's going on and what the characters will do before we build any content. We start out with the obvious:
Incredible. 10/10 story.

Sarcasm aside, this foundation gives us a lot of room to expand, even without dialogue and cutscenes to work with. This pair of events alone raises some interesting questions:
  • Why is the knight slaying the dragon?
  • What must the knight do to slay the dragon (besides the obvious)?
  • What happens afterwards?
You'll notice that these questions fill gaps before, between, and after the 'story'. Let's tackle the 1st and 3rd.

Motivation - Why slay the dragon?

Fictitious knights usually go on quests for kings. Kings, not typically portrayed as stupid, usually have a reason to send their knights off on a quest. Perhaps...
  • The king had a vision of his kingdom's destruction at the dragon's hands
  • The king is a greedy man, who wants the dragon's treasure hoard
  • The dragon threatened the king directly, demanding tribute
We could go on, with more ideas and deeper motives and circumstances. Of course, we couldn't depict most of that well with Halberd as it is. Let me instead reach once more into Ye Olde Bag of Cliches, and The dragon kidnapped the king's princess.

I don't want a totally boring story, though. 'Princess' is also used as a dog's name on occasion, so that might be a pretty achievable twist.

Conclusion - How does it all end?

We now have a knight, a dog, and a dragon. The little twist we just set up will provide a decent ending as well, so that can go at there. We can push it even harder, too. Since the player will likely expect a human princess, we can imply certain (wrong) things by stacking up some bones and a crown just before the dragon, and make the surprise even bigger.

The Rest - To Find a Dragon

I'm not cocky enough to try recreating the entire Monomyth in 10 minutes of lukewarm gameplay. Still, it's a good reference for brainstorming an RPG plot. Look back at the existing story points, and you'll see a couple similarities already.

Next, let's consider the (in-game) journey through our constraints. Given how short the game will be, I think 4 distinct 'areas' is a sensible goal to aim for. Clearly the 4th must be the den/lair/2-story condo that the dragon lives in, so that leaves 3 unknowns. Looking back at the Monomyth, there are a few things that interest me:
  • Most examples involve some transition from the known/safe to the unknown, then back at the end. This seems doable through environments alone, by starting the player off somewhere 'happy', like some lively woods or plains, then moving on to more foreboding locales.
  • There's a lot of events involving 'trials' and hardship around the middle. I happen to know of a couple simple events that could be made possible in Halberd, so I'll probably use those in the middle two areas.
So, we now have the following:
With this, we now have enough story to begin the game for real.
 Next time, we'll begin making some content.