4 Hugues Ross - Blog
Hugues Ross

12/16/17

Taking a Break

It's holiday season, so I've decided to take the rest of the month off from posting. I will have the usual end-of-year reflection post, so either that or the Singularity v0.3 update post will be next.

Happy Holidays!

12/3/17

"Art"

I've wanted to be good at art for a very long time. I spent countless hours trying to teach myself 3D modeling back in highschool, and I originally wanted to make art posts a regular event on this blog when I first started it. Obviously that never happened, but I haven't quite given up on art yet.

During my break in August, I decided to finally try to get good pixel art. Following through on that, I've been practicing almost every day. So far, I've made somewhere in the ballpark of 60 images. I wouldn't call myself competent yet, but I think I've improved enough to make a little "progress showcase".

Enough talking, let's get to the art

I went through my art folder and tried to find similar pieces that
  1. I had considered 'done' at the time (no WIP/unfinished pieces)
  2. Had a reasonable time difference between them
Then, I put them into groups and made some nice little comparison images:

Trees

 Rocky Walls


Sand


Foliage


Stone Bricks



So yeah, that's what I've been up to for the past 3-4 months. I'm going to keep practicing pixel art, and maybe do little gallery posts like this on once in a while. I'll also try to take my time making art for any future game projects, so hopefully my practice will start paying off once I'm back to game stuff.

11/26/17

Playing with Cairo

This week, I took a break from Singularity to mess around with my desktop a bit. In the process of that, I finally sat down and tried using the Cairo vector graphics library.

The Goal

Right now, I'm using a fork of the i3lock utility to lock my PC. Honestly, I'm not thrilled by how it looks. It basically just displays a simple indicator over an image you provide (or a blurred version of your desktop), and that's it. Here's an example from the Github page:
Lately, I've been thinking that the overall "circle with some text in it" design it looks kinda tacky. Unfortunately, I don't know of many other screen-locking options. So, I thought I'd make a small fork that provides a more interesting overlay. I have a lot of ideas for fun designs and overlays that I could use to replace the old design, but I decided to start with something basic:
Note: Colors and fonts aren't final. Just needed something to put in this mockup
I figured that a simple static design would would be pretty easy to swap in, and then I could look into some crazier ideas like dynamic overlays and procedural generation.

Current Progress

To get a new overlay working, the obvious first step is to figure out how the old overlay works. After some poking in the code, it looks like i3lock renders its overlay via Cairo, so I finally decided to finally learn the API.

Cairo is one of those things that I've known about for years, but never really had a good excuse to play with. This mini-project gave me the perfect opportunity, so I decided to make a little playground application where I could mess around. To make things extra-simple, I also did it in Vala. I'm still not sure if I want to try and hook vala-generated code up to the final product, but it's a big help in the short term. After a couple hours of playing around, I made a function to draw those colored parallelograms (which I called lozenges in code, because only a sadist would casually drop a word of that length into a function name):

   53     public void draw_lozenge(int x, int y, int width, int height, int spacing, float[] ratio)
   54         requires(ratio.length >= 3)
   55     {
   56         ctx.move_to(x, y);
   57         ctx.new_path();
   58         ctx.line_to(x + (width * ratio[0]), y);
   59         ctx.line_to(x + (width * ratio[0]) - (height), y + height);
   60         ctx.line_to(x, y + height);
   61         ctx.line_to(x, y);
   62         ctx.close_path();
   63         ctx.set_source_rgba (147.0f / 255, 87.0f / 255, 57.0f / 255, 1);
   64         ctx.fill ();
   65 
   66         ctx.new_path();
   67         ctx.move_to(x + (width * ratio[0]) + spacing, y);
   68         ctx.line_to(x + (width * ratio[0]) + spacing + (width * ratio[1]), y);
   69         ctx.line_to(x + (width * ratio[0]) + spacing - (height) + (width * ratio[1]), y + height);
   70         ctx.line_to(x + (width * ratio[0]) + spacing - (height), y + height);
   71         ctx.set_source_rgba (214.0f / 255, 165.0f / 255, 122.0f / 255, 1);
   72         ctx.fill ();
   73 
   74 
   75         ctx.new_path();
   76         ctx.move_to(x + (width * ratio[0]) + (width * ratio[1]) + (spacing * 2), y);
   77         ctx.line_to(x + (width * ratio[0]) + (width * ratio[1]) + (spacing * 2) + (width * ratio[2]), y);
   78         ctx.line_to(x + (width * ratio[0]) + (width * ratio[1]) + (spacing * 2) - (height) + (width * ratio[2]), y + height);
   79         ctx.line_to(x + (width * ratio[0]) + (width * ratio[1]) + (spacing * 2) - (height), y + height);
   80         ctx.set_source_rgba (161.0f / 255, 124.0f / 255, 91.0f / 255, 1);
   81         ctx.fill ();
   82     }

I am 100% certain that this code can be simplified further and made more generic, but for the moment I'm happy enough with the result.

Besides the missing text, this is almost exactly the same. The big difference is that whereas the previous image was painstakingly hand-made, this new version is the result of 2 simple function calls.

What's Next?

Naturally, the next steps are to add text and get the new design into i3lock. Cairo provides some text-rendering methods (i3lock uses these already), and I believe there's also a library called PangoCairo that adds rich text/formatting/markup via Pango. I haven't tried either of these approaches yet, but I will soon enough.

Once I have a working i3lock with a custom design, I'll post again and look at some of the interesting options that this opens up for me.

11/12/17

Singularity: It's the Little Things

It's been a few weeks since I wrote about some of my old mistakes working on Singularity, and I think it's time for a little follow-up. I've implemented all of the changes that I mentioned (and they work), so I'll be discussing two "smaller" features that I've been working on and what I've learned by working on them.

Look, Ma, no Feedback!

One big problem that I've had in this new version of Singularity is how opaque it is about everything. Before I started working on it again, there was no way to see if any feeds failed to load, or where feeds pointed to. As a result, a feed could go down and silently fail for months while you were none the wiser! Since I'd identified this problem before I started work again, I was already planning to do something about it. To keep things simple, I'm just making the text in the feed sidebar stand out more for now.

So that's the first piece of this puzzle. However, there remains one big problem: What do you do when you know a feed doesn't load? I knew that I had a large number of broken feeds, but without somewhere to see the url it would be difficult to know if the feed had moved or been deleted, or if it was just a parser error.

I'm still mulling over the best solution to the problem. For the moment, I've created a properties page for feeds that contains info like the title and url. This works fine, although it could still use some polish. Another feature that I'm considering is an 'update status' indicator that could display detailed update progress and error messages. Either way, it's clear that Singularity needs to provide more feedback when things fail.

Lesson Learned: Detailed feedback can be very important, and not just as polish!

Getting Organi--Wait, Wrong Series

I'm nearly done with a new feature that, apparently, is one of the most important things to add. When I started rewriting Singularity a while back, I wanted to add folder-like entries to the sidebar so that users could organize their feeds. This seemed like more of a "would be nice" feature than an absolutely vital one, so it was left in a half-finished state.

Boy, was I wrong with this one. I decided to dedicate the weekend to finishing the feature, and it turns out to be a complete game-changer. I didn't expect it to be important, because I mostly just checked my feeds via the 'All Feeds' view. However, I had my logic backwards. I was checking the 'All Feeds' view because there was no other way, not out of preference. I figured this out after sorting all of my feeds into collections, and seeing a result like this:
In the left image, you know nothing other than the fact that there are 3 unread items of some description. What are they? How long will it take to read them? Do I care right now? The program has no answer for you, because the feeds with new items are hiding under 100 others. Even if they were at the top, you could have 30 feeds with one update each. Instead of hunting around, the most obvious solution is always just to click 'All Feeds' and read through everything.

The picture on the right gives much more info. Right off the bat, you know that 3 of the new updates are news articles. If you're about to head out then you probably don't want to check them yet, and you don't have to. It suddenly makes a lot of sense to check the categories that interest you, and leave the stuff you don't want to check for later. I'm glad to have this new feature, but I'm kicking myself over how many months I suffered without it.

Now that it actually makes sense to check things that aren't 'All Feeds', I've also added a small quality-of-life feature: Item views now display the feed/collection that they correspond to. It's a minor thing, but it's nice to have.

Lesson Learned: Just because the user always does something doesn't mean that it's the only way they ever will. Some habits may be a result of weak design.

Conclusion

For the first time in quite a while, I feel happy and optimistic regarding Singularity's future. My last rewrite ending halfway put me in a spot where I was unhappy with the result, but the polish and new features feel like a much-needed breath of fresh air. My goal of a new release by the year's end is starting to look much more realistic!

10/29/17

Roundup, October 2017: Demo Time!


As you can plainly see above, my little tussle with Glade has borne fruit in the form of a new DFGame demo! The editor module isn't completely finished, but I had enough to work with so I decided to make a video anyway. Now then, let's discuss how the demo (and by extension, the Editor Module) works.

Split Architecture

To understand the current architecture of DFGame, I think it's useful to first look at the original architecture of Halberd, my WIP RPG engine. Halberd's codebase spawned DFGame originally, so it's useful to see where things came from. As I explained back in 2015, Halberd (and later, DFGame) was split into 5 modules:
  • "Common" - Contained all code that worked in the editor and game
  • "Editor Backend" - Editor-specific code, without the UI
  • "Game Backend" - Game-specific code, without GLFW
  • "Editor Frontend" - The editor UI
  • "Game Frontend" - The game startup code, with stuff like window creation
When DFGame, I identified a couple weak points in this design. First of all, lumping nearly everything into a common module was a bit silly. Second, the backend/frontend concept felt somewhat unnecessary. To correct this, I created DFGame's current modules:
  • Core
  • Math
  • Audio
  • Graphics
  • Gameplay
  • Application
  • Editor
 The first 5 modules are fairly self-explanatory. The application module is the general equivalent to the "Game Frontend" module and the Editor module is the "Editor Frontend" and "Editor Backend" rolled into one. The idea is that both of these modules will implement a common API, allowing the game to run regardless of where it is. This is the most important part of setting up a robust set of development tools, ensuring that the game code and window/input code are seperated.

Vala Interop

Besides the architecture, there's a second detail needed to get DFGame's editor functionality working. Typically, the languages used to write software and the languages used to write games are different. This can lead to many issues getting games to embed nicely inside of their tools, especially if there are ABI incompatibilities between the languages.

This was one of my main reasons for picking Vala. The Vala compiler translates Vala code to C, so getting a Vala frontend to play nice with a C backend is quite simple. To make the triangle in the editor demo controllable from Vala, I only needed to write a simple binding treating it as a class.

Conclusion

To sum things up simply, building a good editor for your game requires two things:
  • An architecture that allows the game to run without the window/input code
  • A means of bridging the editor's language and the game's language (This could be as simple as using the same language for both)
Once you have both of these things handled, you can work on your editor without worrying much. Once I finish up the Editor module, I'll be able to do much more with DFGame. I'll still be focused on Singularity for the time being, but I'll still be working on this occasionally.