4 Hugues Ross - Blog: 2017
Hugues Ross

9/24/17

Update: Thinking About the Future, and Looking to the Past

Thanks to my shoulder, I've had a lot of time to think lately. I'm not very happy with the work that I've produced over the years, and I think that something fundamental needs to change. If you don't care too much about the specifics, you can scroll to the last heading for a quick summary of what I plan to do.

...Still here? Alright. Let's look back over the past 5 years.


In the beginning...

In late 2012, I was an eager and bright-eyed lad who was ready to try out this whole blogging thing. I was primarily inspired by the work of Shamus Young, whose blog I'd been following for a few years. To some degree, I think it shows:

"Shamus wrote some really great D&D stories, I should document the D&D campaign that I'm playing now!"
"Shamus wrote about some cool programming projects. I should do cool programming projects and write about them!"
"Shamus has a webcomic. I should do art stuff!"

He wasn't the only influence, but certainly the strongest. I also remember seeing video creators on Youtube and webcomic artists putting out work several times a week. For that reason, I created this ridiculous daily posting schedule. One thing that I failed to consider was that these individuals did nothing but make what they were posting. Indeed, for many of them this was their job, and I've heard that many such creators work well over 40 hours a week to keep such schedules. This plan of mine was doomed from the start, because I chose to try and mimic people who were quite different from me.

Alas, looking at work made by someone else and thinking that it's cool doesn't always help your own work. I couldn't simply copy Shamus's work, so the blog spent a long time being updated intermittently, with occasional apologies and failed promises.


Good projects, and AMAZE-ingly bad decisions

Around early to mid 2013, I started one of the projects that would last throughout this blog's life: Singularity. I started it with no plan, merely creating it out of necessity. Despite that, I could argue that it's also my most successful project: I created something just for myself, with no expectations, and ended up with something nice. Keep these italicized sentences in mind, they'll be important later.

Singularity is not all that I started then, either. During the summer, I also started AMAZE and the "Games I Play" series. The latter was about as doomed as my first schedule, and here's why:

I still remember how the concept of "Games I Play" was conceived. I had the problem of having too many untouched games in my Steam library, and no time to actually play them. Why was there no time? Well, I had to work on projects and post about them online! In other words...
  1. The Problem: No time to play games, because I had to work and blog.
  2. The Solution: Make games part of the work and blogging.
Seems pretty damn stupid in hindsight, huh? But hey, "Shamus Young writes about the games he plays, I should do that!" Here we have a time commitment issue, and a response that worsens the true problem in an effort to be someone else.

Now, let's talk about my darling AMAZE. Despite how much I hate the final product, AMAZE was ok as a subject. I posted screenshots, and wrote regularly about the things I was interested in! However, there's an interesting trend hidden in the AMAZE posts. As I became less interested and more "serious" to hit deadlines that I'd set, my blog posts went from this to this. Excitement and screenshots gave way to changelogs and walls of text. Once again, these two projects demonstrate a simple fact: I produce the best content when I'm excited and engaged with it, not when I feel obliged to make it. Obvious, I know. But let's move on, there's more to cover.


Total overkill

I'm skipping Space Douchebag because the same conclusions can be drawn from it as from AMAZE. Instead, we now fast-forward to 2014, DFEngine, and Akradion. Technically, DFEngine began with AMAZE, but this point is when I really got serious about it. As I've elaborated before, the concept of DFEngine was flawed. Trying to make a full-blown game engine because I'm too slow to iterate is like trying to build the LHC because there's a mosquito in your room: Not only is it a glorious waste of time, it also makes absolutely no sense. I still believe that DFGame will be a better bet in the long run, as it's mostly just a way to skip writing boilerplate code.

So, what about Akradion and Cloudy Climb? Besides being the first projects made after a DFGame version, they have one other thing in common. Rather than being games that I dreamed of and was excited for, they were instead an attempt to prove something. Ultimately, both games suffered dearly because of that. My line of reasoning when making these games went a little like this:
  1. If I'm making a game engine, it obviously needs a physics engine. That's a thing that game engines have.
  2. I need to make a game to prove that this game engine idea works
  3. My game engine has physics, so I need to make a game with physics to prove that the physics engine works.
 That set of thoughts above has many problems. Let's dissect them a little:
  1. My games have always been simple and 2D. Obviously I didn't need a physics engine, I had never used one before!
  2. As it turns out, making a full-length game just to be sure that some tech works is a huge waste of time. I keep doing it too, it's a bad habit. This is why I forced myself to keep the demos I'm making for dfgame as small and simple as possible.
  3. Neither Akradion nor Cloudy Climb are actually good choices for testing a physics engine! Seriously! Akradion is a game that relies on an object that retains constant velocity at all times, a worst-case scenario for physics! Cloudy Climb only really makes use of gravity, so a big physics engine is totally unnecessary.
In other words, a project that started as a supposed time-saving measure wandered off course in an attempt to make a fancy game engine. It then split into more projects, which were doomed from the start because I'm a bad planner. Ultimately, DFEngine was about a one and a half year-long diversion from what I cared about. I'm actually ok with most of that, since trying out things that interest me is fun. However, looking at the posts you can see the usual changelog post structure from AMAZE take over after a while.


Why teach?

Next, let's discuss tutorials. The roguelike tutorial series that has been in progress for years has never really reached a point where I was happy with it. So why did I start it? For that matter, why am I still writing it? Let's discuss.

I spent many years learning to program and make games. I actually started all of this back in middle school with Game Maker, only transitioning to more "professional" tools once I started college. Throughout my life (even now, in fact), I've regularly referred to guides and tutorials in order to learn various tricks and techniques. For much of that time, I felt a desire to give back with tutorials of my own once I got good at my craft.

Unlike the many of the blog-related decisions I've made, the decision to write tutorials in general had decent reasoning behind it. Furthermore, I think it'll work out eventually. So, why was the roguelike tutorial a failure for me?

At the time, I wanted to make an ASCII strategy game of sorts. When I returned to the project, I had a cool roguelike idea that I wanted to make. I don't think that's a coincidence. Rather than simply make the games that I wanted to, I found an excuse to try and work on something similar, via tutorials. Rather than just doing what I wanted, I invented a new series of posts to 'legitimize' my desire as an extension of my blog. It's no wonder then that the tutorial was never well thought-out or exciting to me. I wanted to do something else the whole time! Compare the forced and lackluster entries that I've been putting out lately to something like this post, and you'll see a world of differences.


Unfortunate truths

Ok, I think that's enough tiptoeing around the subject. What do all of these events point to? What's my point writing this? Well, it's really quite simple:

By forcing myself to only do "blog-worthy" things, and acting beholden to a theoretical reading audience, I'm harming both my blog's quality and my own life.
That's a conclusion that's taken about 2 months to reach. The one thread that ties many of my threads together is an attempt to emulate the content creators that I like. I envision myself as them, and imagine that I have an audience the same size that they do. Often, I make decisions based off of this. It's why I feel an urge to apologize at every delay and schedule change. It's the true reason why I just can't leave a series that I don't enjoy alone. To some degree, it also stops me from making progress. Every month, I spend:
  • ~1 week preparing, recording, and editing an update video
  • ~1-2 weeks writing a new segment of the roguelike tutorial
  • 2-4 days writing some other post
That leaves me with only a week or two to actually work on DFGame. It also keeps me from trying out new ideas and iterating. I've had a lot of really cool project ideas since I started work, and I've had no choice but to put them off until "after DFGame".

Except, that's not true at all. I have a choice to stop and do what I want, whenever I want. The only thing that stops me is my schedule. The only reason I have a schedule is to guarantee regular content on my blog. And why do I need to guarantee that? See Above.


The almighty power of boredom

Let me tell you a little story:

About a year ago, I had a cool game idea. The game in question would involve some fairly heavy adult content, so it wasn't "blog-worthy" at all. At the time, I was still adjusting to life in Montreal and figuring out post-immigration stuff. I also had a few issues in my life that put me in a bad position for a while, and I wasn't sure if I could keep writing the blog due to my job.

Since I didn't want to work on my blog, I worked on the game. In just a few scant months, I wrote an entire engine from scratch, complete with a data-driven dynamic UI system. I started writing down ideas, building roadmaps for development, drawing first-draft animated sprites for characters, etc. Then, I got the greenlight to blog again and I haven't touched the project since!

Flowcharts tracking development progress.
The bottom red circle was a public demo release.
So close, yet so far...


You see, I've written in the past about how blogging with a schedule keeps me productive and how vital it is, but at the end of the day you can lock me in a room for 3 months with no blog and I'll still write yet another game engine. Development is what I do. It comes naturally, and trying to keep to a rigid schedule or only focus on one thing for a long time doesn't help.


If you're scrolling past the wall of text, you can stop now

Ok! That's it! No more long-winded storytelling! It's time to talk about how I'm going to fix this problem. I'm going to keep this short and sweet, you just read the whole story so you don't need much more:

  • Effective immediately, I am cancelling the roguelike series. No hiatus. It's over, it was a bad idea, and I can always revisit the subject when I'm older and wiser. I'll leave the text around for now.
  • Starting next year, no more schedules and no more promises. I'll write when I feel the urge, and I'll develop whatever I damn well please. There will be fewer posts. I guarantee it. But every single one of them will be carefully written and edited for maximum quality.
  • When that happens, I'll finally redirect the huguesross.net domain to my site's landing page. That page and the about me page have been redesigned, and I'm working on the tutorials section. That section will hold both longer tutorial series and any informative posts that I think are useful and good enough to share.
If I change my mind about all of this, I may still keep the schedule. It's possible that I'm just in a rut, or mildly burnt-out. I'm giving myself 3 months to reconsider this decision, to ensure that it's really the right way to go. At the end of the day, I don't want to drop the blog. I think keeping a blog that shows your process of working and shares your knowledge is awesome, but I need to remember that blog posts should not be my biggest source of work.

This is a blog about programming, not time management. (except here, I guess)

9/10/17

Let's Make a Roguelike - Stats, Items and, Messages

Well, here's a new tutorial segment!

This one was pretty awful to write, mostly because I chose too broad of a topic. As a result, it's also quite a bit longer than most of the others (~14 pages, with a previous record of ~11). On the upside, I'm very nearly done here. Currently, I'm planning the remaining 3 segments to cover:
  1. AI and combat
  2. Generating artificial spaces (e.g. mazes, dungeons, buildings, etc.)
  3. Various remaining loose ends, like visibility and overall game structure
I didn't quite do item systems justice here, unfortunately. I seem to have missed dropping/equipping items in particular, although these actions should be fairly trivial to implement with the knowledge from the tutorial.
Since it looks like things are mostly on schedule despite last month's delays, I'm currently pegging the completion date as December 17th, 2017. This will be one full year after I restarted the series, minus a couple days to make it land on a Sunday.

Speaking of dates, this series will be 3 years old in a couple weeks. All I can say at this point is that I'm glad it's coming to a close. It's going to be a while before my next series, I have a few ideas but I want to put a lot of consideration into any future endeavors. However, I do have a one-off informative...thing that I'll be putting up on the tutorials page not too long after this series.

8/13/17

Update - Sorry Guys!

Hello everyone, I have some unfortunate news today:

For various political reasons, my shoulders have decided to let burn the fires of revolution, which would be entertaining if it wasn't so darn painful. It hurts in general, which makes it difficult to focus, and it also hurts extra-hard to type! As a result, I've decided to postpone everything by a full month to allow my body time to recover.

This means that dfgame is now slated to release at the end of September, the tutorial is likely to end in December, etc. I was planning on a little "looking back" post for this blog's 5th anniversary on the 20th, and I might still do that. It's a big date, and most of the work is reading, not writing. My right arm is ok, so I might also bust out my tablet and chance a few sketches. We'll see.

Ultimately, I'm extremely disappointed in myself. I took the first week off this month in an attempt to deal with the issue, but it's been over 2 weeks and I'm still out of commission. I apologize for the delays and such, and you'll probably hear from me again in 3-4 weeks or so.

7/30/17

Roundup, July 2017 - Rock & Roll

Another month has passed, and it's time for a new update video:

Additional Comments

In addition to these demos, I also made a few nice additions to DFGame's API. Since it's mostly a grab-bag of small additions, here's a list:
  • Predefined colors to use for rendering
  • Simplified main loop function
  • mesh_render can also bind mesh attributes, which had to be defined separately before
  • hashmaps can now be told to delete their contents when being destroyed
  • sprites can be told to delete their source when being destroyed
  • Window init now enables transparency and depth testing by default
  • Function to create a new 2D camera based on a window's dimensions
  • Added transformation macros for cameras, to simplify transform_FOO(camera_get_transform(c)) syntax to camera_FOO(c)
  • Added a simple version of "copyadd" to data structures, which measures and copies non-pointer values
  • Attempting to lerp int literals now uses float lerp, since that's what most reasonable people would expect
  • Added an "almost zero" macro for testing floats and doubles
Writing them all out as a list looks pretty impressive, but most of these additions are quick 5-minute changes. Still, it's good to add them in before release.

Goals

  • Time Left: 3-4 weeks
  • Logo Demo: Done
  • Comets Demo: 90%
  • Heightmap Demo: 60%
  • ??? Demo: Not Started
  • ??? Demo 2: Not Started
I have 2 more demos planned, and a little more work for the existing demos. This puts me at about halfway through, with a month or so remaining. This means I'll have to stay focused if I want to get all of that done, and possibly a game jam as well.

Some Code

As I mentioned in the video above, the Logo Demo was designed to present a simplified example of the init, cleanup, and looping code. To demonstrate that, here's the code:
    1 #include "camera.h"
    2 #include "color.h"
    3 #include "interpolate.h"
    4 #include "mainloop.h"
    5 #include "mesh.h"
    6 #include "paths.h"
    7 #include "shader_init.h"
    8 #include "texture_loader.h"
    9 #include "vector.h"
   10 #include "window.h"
   11 
   12 GLFWwindow* win;
   13 camera c_main;
   14 shader s_default;
   15 float  timer;
   16 gltex  t_logo;
   17 vec4   color;
   18 
   19 bool loop(mainloop l, float dt) {
   20     timer += dt;
   21     color.a = lerp(0.0f, 1.0f, timer) + lerp(0.0f, -1.0f, timer - 2.5);
   22 
   23     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   24 
   25     glUseProgram(s_default.id);
   26     shader_bind_uniform_name(s_default, "u_transform", mat4_mul(camera_get_vp(c_main), mat4_scale(mat4_ident, 400)));
   27     shader_bind_uniform_name(s_default, "u_color", color);
   28     shader_bind_uniform_texture_name(s_default, "u_texture", t_logo, GL_TEXTURE0);
   29     mesh_render(s_default, mesh_quad(), GL_TRIANGLES, "i_pos", VT_POSITION, "i_uv", VT_TEXTURE);
   30 
   31     glfwSwapBuffers(win);
   32     return !glfwWindowShouldClose(win) && timer < 4.0f;
   33 }
   34 
   35 int main() {
   36     win = window_new_default(1280, 720, "Logo Demo");
   37     init_base_resource_path(NULL);
   38     shaders_init();
   39 
   40     s_default  = shader_basic_tex_get();
   41     color      = color_white;
   42     c_main     = window_create_2d_camera(win);
   43     char* path = assets_path("logo.png", NULL);
   44     t_logo     = load_texture_gl(path);
   45     sfree(path);
   46 
   47     mainloop_create_run(loop);
   48 
   49     glDeleteTextures(1, &t_logo.handle);
   50     camera_free(c_main);
   51     shaders_cleanup();
   52     resource_path_free();
   53     window_free_final(win);
   54 
   55     return 0;
   56 }
There are still a few things that could be simplified here, but this is still much less code than would be required without DFGame. That's the primary goal of the framework, so I'm pretty happy so far!
With DFGame's release now imminent, and the upcoming 5-year anniversary of this blog, next month ought to be pretty exciting. Until then, keep on reading!

7/23/17

Let's Make a Roguelike - Example: The Swamp Cave

EDIT - Tutorial link was dead yesterday, sorry about that! The page is up now.

Sometimes, when I'm working on my website late at night with the lights off, I hear a voice coming from the Tutorials page:
"Huey, you cantankerous crayfish! You claimed that the roguelike tutorial wasn't on hiatus, but it's been five months since your last post! Fess up!"
...Nope. Definitely not on hiatus. I had to, err....pickle the ASCII. To make it green. That's my story, and I'm sticking to it.

Anyway, there's a new segment of the roguelike tutorial. You can read it here!

Being ever-so-slightly serious for a moment, I didn't (and still don't) really want to work on the tutorial. But, I also want to get it done. That means that I have to write up tutorial segments eventually, even if I'm not really inclined to do so. I also have some other tutorials that I'd like to start, but I'm unwilling to do so before this series is over.

This part serves as a sort of culmination to the last few. It shows how to take the techniques shown so far, and combine them to make a greater whole. My goal now is to introduce the rest of the basic techniques and mechanics commonly found in roguelikes, tie it all back together into a simple package, and mark the series as complete. I've mapped out the remainder of the tutorial at this point, and it looks like it'll be another 5 parts, including the conclusion. My goal for this series is now to be done with it before this series becomes a year old. If I can manage that, then I think I can happily call this 3rd attempt a success. You may notice that the code is quite a bit messier and uncommented. That's also a result of my rush to finish this series up. Once the series is over, I may go back to clean it up and make it more readable, but for now I'm more concerned with speed than quality.

7/16/17

Getting Organized - 6 - Tick Tock

Hello again, dear readers. Once again, it's time to make my life a little more productive. In my previous post, I grappled with my computer a little bit in order to bring my to-do list up every morning. This month, I'm going to work on my time management a little.

When I mentioned that I wanted a timer back in May, I said that I wanted "I'd like something that fits with everything else". I'm not entirely sure how many purely hypothetical beers I drank before writing that thought, but looking back it sounds more like the mutterings of the local town loony than anything important. I assure you, however, that this strange little collection of words will make sense if you read the following two paragraphs. So, y'know, you can just skip them if you're up for a challenge.

So, if you've been reading these posts religiously then you'll know that I use Awesome to manage my desktop. This gives me lots of control and customization options, but also makes using "traditional" desktop apps cumbersome at times. In this case, a quick Google search will find you endless pages of linux timer apps, coming in exactly two flavors:
  1. Pretty (useless) dialog windows that take up half your screen with fancy Large Text
  2. Icons in your system tray
Option 1 is unappealing in general, but also breaks with my window-management preferences. I could let one of these apps ignore Awesome's tiling rules, but then it would also block me from interacting with whatever's underneath it. Oh, and it's definitely not getting its own special desktop, so that's out. Option 2 would work nicely...if I had a system tray. I could add one and watch it fill with useless incongruous icons, or I could not do that and sleep well at night. But, there's another solution. Let's take a look at my bar for a moment:
Pretty much all of those nice little UI bits are custom. So, I can make my own "Option 2" that fits with the visual style of my desktop and does exactly what I want.

If you're still following along with my little scheme to make a timer but you're not sure it's quick or feasible, then I have some good news: It's done. I secretly went and did it this morning. Normally, I write and code together, but I just wasn't in the mood for 6 AM blogging. What was in the mood for was Runescape (???), and I didn't want to miss any deadlines in the process. I suppose you could say I was motivated by laziness, but I'm not about to complain!

The Implementation

The result of my mad morning keyboard mashing was just under 100 lines of Lua code. Most of that is UI boilerplate, but there's about 40 lines of actual logic in there that might interest someone, so let's give that a look:
   52 local timer = gears.timer {
   53     timeout   = 1,
   54     autostart = false,
   55     callback  = function()
   56         seconds_left = seconds_left - 1
   57         if seconds_left == 0 then
   58             awful.spawn({"mplayer", "/home/df458/assets/se/Notify01.wav"});
   59 
   60             local message = string.format("Your timer of %02d:%02d has ended", math.floor(seconds_total/3600), math.floor(seconds_total%3600/60))
   61             if seconds_total < 3600 then
   62                 message = string.format("Your timer of %02d:%02d has ended", math.floor(seconds_total/60), seconds_total%60)
   63             end
   64             naughty.notify {
   65                 title = "Time's up!",
   66                 text = message,
   67                 timeout = 300
   68             }
   69         elseif seconds_left < 0 then
   70             widget:set_visible(false)
   71             timer:stop()
   72         end
   73         progress:set_value(1 - (seconds_left / seconds_total))
   74         if seconds_left < 3600 then
   75             label:set_markup(string.format("%02d:%02d", math.floor(seconds_left/60), seconds_left%60))
   76         else
   77             label:set_markup(string.format("%02d:%02d", math.floor(seconds_left/3600), math.floor(seconds_left%3600/60)))
   78         end
   79     end
   80 }
   81 
   82 function activate_timer(seconds)
   83     seconds_left = seconds
   84     seconds_total = seconds
   85     widget:set_visible(true)
   86     progress:set_value(0)
   87     if seconds_left < 3600 then
   88         label:set_markup(string.format("%02d:%02d", math.floor(seconds_left/60), seconds_left%60))
   89     else
   90         label:set_markup(string.format("%02d:%02d", math.floor(seconds_left/3600), math.floor(seconds_left%3600/60)))
   91     end
   92     timer:start()
   93 end
As you can see, this little code block could probably use some cleaning. With that said, it works pretty well and demonstrates just how easy it is to make a timer. All I really do is set two numbers to how many seconds I want to wait, then subtract one from the 1st number every second. The second number isn't even necessary at all, but I use it to add a progress indicator. Beyond that, the rest is just making a nice text representation that switches between hour:minute to minute:second as necessary. When the timer's running, my little info are looks like this:
It's simple, sure, but it works quite well! Next time, I'll be wrapping up this series with some final touches to task management.

7/2/17

Roundup, June 2017 - Lost in another dimension

It's that time of the month again, and I've made great progress!

Additional Comments

In addition to what was mentioned in the video, I also went back and re-added joystick emulation to the input code, as well as adding a few minor features and fixes all around. Besides the lackluster demo, this has been one of the best months for development this year.

Goals

  • Time left: about 1 1/2 months
  • Application Module: Done 
  • Audio Module: Done
  • Core Module: Done
  • Gameplay Module: Done
  • Graphics Module: Done
  • Math Module: Done
  • Resource Module: Done
As I said in the video, and as is apparent from the list above, I'm just about finished with dfgame for the time being. If you've been following along, you've probably noticed that I quietly removed particles from the goal list. This is because particles are a bit of an unknown for me.

"But wait!" I hear you cry. "Didn't DFEngine have particles?" This is correct, but DFEngine's implementation was super basic and not very good. My standards for features, while not amazing, are definitely higher than they used to be. If I were to make particles now, I'd want to use the GPU or at least some form of SIMD to get good performance. I played around with GPU particles last summer, but I ultimately ran into a few issues that halted progress and moved on to other things. A decent particle implementation will take some research and effort, but I don't know how much so I'm putting it off for the sake of polish.

Some Bad News

The main goal of my "End of August" timeline was to use dfgame for an actual game jam entry. Unfortunately, I just found out that for the first time in 15 years, Ludum Dare is being held at the end of July. Why? I have absolutely no idea. I could theoretically still enter, since dfgame's release is now feature-complete. However, I would be sacrificing about 50% of my polish time to do so.

Instead, I'll just keep an eye on the itch.io game jams page and select one in the right general time period.

As for next month's posts...beats me, I forgot to plan anything. Whoops!

6/26/17

Happy birthday to Me!

First off, let me apologize quickly for missing my post deadline last weekend. I decided to take a second break this month in order to celebrate my birthday without the stress of writing another post. As much as I love working on this blog, it takes enough time and effort for me to want breaks here and there!

Anyhow, you can expect this month's roundup to land on Sunday at the usual time. I've made great progress, so I think it'll be a pretty good update.

6/11/17

Getting Organized - 5 - Some Awesome Work

When we last left off on my quest for good time management, I decided to share my pizza recipe instead of being productive. Clearly, I'm making good progress. Now then, it's time to do some actual programming.

Awesome!

No, that's not your cries of joy. Awesome is the Window Manager that I use on all of my machines nowadays. In addition to laying out my windows in a pleasing fashion, it also exposes a powerful lua API for customizing and scripting, well, everything. This includes the UI, allowing for some very in-depth customizations!

Last time, I made a list of tasks to complete:
  1. Automatically opening my wiki every morning
  2. A simple timer that fits with my workflow
  3. A way to create tasks remotely while at work
Today, I'm going to finish off the first task. Furthermore, Awesome is going to help me with that.

Hello, Wiki!

Originally, I said that opening my wiki in the morning would be "super-easy to do". I lied! I lied to everyone, even myself! And what a lie it was.

An Unexpected Snag

The easiest way for me to make programs start on launch is to add them to my xinitrc file. In this case, I actually can't do that. Because the terminal that I run vim in won't have its settings ready before my xinitrc finishes running. That means that if I use my xinitrc to bring up my wiki, the colors and fonts will be wrong and it'll have a horrifying scrollbar that looks like it crawled out of Windows 3.1.

Obviously, I don't want that. Awesome gives me the ability to run applications, so I can have it launch my wiki. Perfect, right? Wrong! To help debug scripts and configuration, Awesome provides a mechanism to restart it without closing anything. This is also great! However, this means that every time I restart Awesome it'll also open the wiki again. So, we have a conundrum.

The Solution

The second problem can be solved, but it'll take a few small additions. The goal here is to have Awesome run certain programs on startup, but only if it isn't restarting. To do that, I need to store some information across runs.

Conveniently, Awesome has an event that runs when it exits. Even better, that event tells you whether the exit is part of a restart or not! So, I simply write a value to a file based on whether Awesome is restarting or not. Then, Awesome can read the value when it starts and use it to make decisions. The result looks like this:
awesome.connect_signal("exit", function(restart)
    local lastrun = io.open("~/.config/awesome/lastrun", "w")
    if lastrun ~= nil then
        if restart then
            lastrun:write(0)
        else
            lastrun:write(1)
        end
        lastrun:close()
    end
end)

...

local lastrun = io.open("~/.config/awesome/lastrun", "r")
if lastrun ~= nil then
    local was_quit = lastrun:read("*n")
    if was_quit == 1 then
        for i,e in pairs(autostart_once) do
            awful.spawn(e)
        end
    end
    lastrun:close()
else
    for i,e in pairs(autostart_once) do
        awful.spawn(e)
    end
end

for i,e in pairs(autostart_each) do
    awful.spawn(e)
end

As you can see, it's actually pretty simple. Anything that I add to the autostart_once list will only start if Awesome shut down properly last time it ran. On the other hand, anything in the autostart_each list will run every time Awesome runs. This makes for a convenient solution that I can use as much as I want going forward.

So, that was a semi-complicated solution to a relatively simple problem. Come back next time for some tougher-but-more-straightforward scripting.

6/4/17

Roundup, May 2017 - Oh man I sure do hope the mosquitoes don't--

It took great courage and perseverance, but I finally drove back the mosquitoes that definitely ate all of last week's update. So, here it is:


Additional Comments

I had some difficulty capturing/rendering this video. Last time, I used glc for the video capture. However, glc's audio recorder is really buggy and doesn't work on my machine. It's also quite old, so I'm worried about relying on it too much. This time I made a recording with FFmpeg, but it's just a normal desktop capture so it's a bit slower than I'd like. Next time, I'll probably try to capture the video and audio separately. It might be annoying to line the two up in editing, but it will probably result in a higher-quality video.

The big gain from rewriting the audio system is that multiple audio players should now be able to play audio from the same source at the same time. This means that I don't have to reload a sound effect every time I want to use it, and instead I can easily load once and play hundreds of times. As you can guess, this is really useful for games where you could easily have a couple dozen objects that can make the same sound.

Goals

  • Time left: about 2 1/2 months
  • Application Module: Done 
  • Audio Module: 95%
  • Core Module: Done
  • Editor Module: Not Started
  • Gameplay Module: 80%
    • Missing joystick emulation for input
  • Graphics Module: 65%
    • Missing sprites
    • Missing text
    • Missing framebuffers
    • Missing particles
  • Math Module: Done
  • Resource Module: 65%
    • Missing sprite loading
    • Missing font loading
This month went a little slower than I'd hoped, and some of the code that I wrote feels a bit rushed. As a result, I'm going to need to do another quick pass on the audio and resource modules at some point, just to tighten them up a bit. That's not what I'm doing for June, however. I want to get the last couple essential features, sprites and text, done. This will happen as part of a greater attempt to finish off the graphics module as a whole. I don't expect to finish all of it this month, but it wouldn't surprise me too much if I could sneak framebuffer support in.

If all goes to plan as it has so far, I'll have over a month left over to clean up any loose ends and improve my workflow in preparation.

Next month's posts will feature lots of Linux shell scripting. Much like in May, I'll be kicking off next week with some more organization work.

5/29/17

Mosquitoes ate my update video

Man, don't you hate it when small, buzzing insects devour files off of your hard drive? It's the worst. It's also something that definitely happens all the time, and our modern society is powerless to stop them. Remember when your favorite thing was cancelled or delayed for no apparent reason? Mosquitoes. Yup. Definitely 100% not telling any sort of fib or white lie right now, and frankly I'm a little wounded that you'd suggest that I might ever not tell the truth in a vain attempt to cover up my own shortcomings.

So, because a swarm of mosquitoes ate the update video for this week that I definitely made and didn't put off for too long, I'm making a little life post instead. You can expect me to have it finally finished remade in time for next Sunday's post.

Let's talk about my weekend

I had a really busy weekend, which is why I was unable to complete my video powerless to stop the horde of ravenous arthropods from devouring my video files.

On Saturday, I went on a hike in the Laurentides with a group from the office. For those who don't know, the Laurentides is a region of Quebec that's packed full of beautiful lakes and mountains. Just imagine every photo of the Canadian wilderness that you've ever seen.

This pretty lake is the perfect environment for breeding the harbingers of your hard drive's doom

The hike was 5 1/2 km, and circled a small lake. It was a good length, long enough to be enjoyable without overstaying its welcome. The weather was warm and sunny, but not so hot as to be uncomfortable. In many ways the conditions for this hike were ideal. They also happened to be ideal for the terrifying force of mosquitoes that hounded us and our video files, especially the latter. For every person, I'd say there were 10-20 mosquitoes buzzing around them. They didn't manage to ruin the experience though, and I'd definitely do it all over again. Oh, and uh....some of them, err, hid inside my backpack? Yeah, sure, we'll go with that. Then they emerged to feast upon my defenseless PC or something. It was awful.

Artist's rendition of the event

Unlike most activities that I engage in, I brought my camera with me and took a few photos. Several shots came out quite nicely, so I might do this more often:

(Click any image to view at full size)

On Sunday, my family came in for a visit. They brought my bike over, so once I buy a new helmet I should be able to travel much farther in the city! After that, we went out for pizza and ice cream, then took a little stroll around Parc La Fontaine. I'm not fond of spending lots of time with family, but I really enjoyed this little outing quite a bit! They seemed pretty happy too, so it was a good day all in all. Oh, and they were...yeah, they were totally devastated at the carnage caused by those darn mosquitoes. Yup!

So that was my eventful weekend! As you can see, I was quite busy and didn't find time to make this month's update video set up adequate anti-mosquito defenses. Anyhow, this week is mostly still May so I'm still keeping to the schedule to some degree. Expect the monthly dfgame update next Sunday at the regular time.

EDIT: According to Blogger, this is post #256, so if we were counting with one byte I'd have to stop here. Thankfully, that's no longer the case!

5/21/17

A post-graduation reflection

Last May, I got my Bachelor's Degree at Champlain College. Now that May has come again, I thought I'd give a quick recap on my first year out of school.

Getting a job

I started hunting for jobs on and off several months before graduation. Unlike many of my peers, I was in the interesting position of not wanting any sort of game development job at all. For years, I'd read stories about the horrors of game development and how it churns through the annual supply of bright-eyed college grads. So, I applied to software development gigs and got ignored a whole lot!
 
I suppose it's natural. Game Programming doesn't sound like the most reliable major to pick, even with the work I've done on my own. Ultimately, I got my current job through a mix luck and networking: My friend Vince (lead programmer on The Last Light) recommended me to a recruiter from Ubisoft Montreal during the end-of-year showcase of our game, and that led to an offer. (Seriously, networking is really good and you should do it) I wanted to stay close to my home in Vermont, so I decided to take the offer rather than keep looking.

Canada!

With the offer accepted and some necessary summer prep work complete, I found myself on the other side of the border just in time for Fall. Due to a scheduling mishap, I ended up arriving a month and a half before my start date, giving me plenty of time to settle in and explore the city. In order to best take advantage of this, I spent the majority of the time sitting in my room with a tiny specter of legal and financial uncertainty drifting lazily over my head.

Now that the weather is warm and I no longer fear for my checking account, I've been spending more time going out and looking around. Overall, I'm super happy to be here! Being half-French, I'm enjoying the mix of languages especially, even if I now have an irrational fear of peanuts.
Yup definitely not made of spiders no siree
...Moving briskly on, Montreal is a really nice spot to live. I've got a nice inexpensive apartment on the Plateau, and some streets are lined with enough trees to almost give the feeling of being in the woods! As someone who grew up in a reasonably small town village, the neighborhood makes me feel at home while still providing all of the bustle and convenience of a city close by. (And of course, there are some standard socialist benefits like free healthcare and unified public transportation systems)

Work life

Unfortunately, I won't be discussing too many details of my work. I'm not 100% sure what is/isn't covered under my NDA, so for now I'm playing it safe and speaking in very general terms. If I get that cleared up I might discuss some juicy details in a future post. So far, Ubisoft has been an incredibly pleasant surprise. Being a big publisher, I was expecting them to screw me over at every opportunity, but I have absolutely no complaints about them.

I've only truly been "on the job" for a scant few months (I was in a long-term training up until mid-January), but I feel like I'm trusted and relied upon regardless. I usually get handed a bunch of requests and long-term goals, and then I'm left to my own devices until they're finished. Not only have I not done any overtime, the senior devs that I work under have made a point of reminding me to take it easy on the hours and stay fresh. Some of this can be chalked up to the fact that the production I'm on is still at a very early stage, but even so I was expecting much more pressure.

Another fear that I had was about whether or not I'd be allowed to continue my personal work unrestricted. Ubisoft requires you to send in a 'request' for side-projects, but:
  1. The restrictions that come attached are mostly just obvious things that most sane people wouldn't do in the first place
  2. The responses get back to you in a reasonably timely manner
  3. I have pushed no fewer than 19 personal projects through the official channels, and to this date not one of them has been refused.
Point is, they're pretty nice about these sorts of things. It would be even better if they didn't ask for requests at all, but at least the process is simple and painless.

The work itself has been really fulfilling and exciting for me. I've been doing tools work since it's the closest I can get to normal software development, and it's been a lot of fun! It makes me a little disappointed that Champlain doesn't cover tools programming in their curriculum at all, given how crucial good tools are to large-scale production teams. I'm mostly working in C# and WPF, but my experience with Vala and GTK are still coming in handy regardless. Indeed, it feels like both my personal and professional work are fueling each others growth.

To sum it up, I've managed to land a fun and not-too-stressful job in a city where I feel at home right out of college. I can't help but feel lucky where I am right now, and I hope my current streak of good luck lasts quite some time to come!

5/7/17

Getting Organized - 4 - Gripes and progress

Another week has passed, and here I am, still using Taskwiki. I promise that this is the last time I bring it up for a while, but I wanted to discuss some of the good and bad that I've encountered before moving on to some actual code.

This week, I haven't made too many additions to the wiki itself. My main addition was a project list, and the start of a dfgame wiki. The way the dfgame wiki is laid out, I have a task filter front-and-center. Rather than adding things to the list directly, it simply gathers all of my tasks for the project into one place. Inside the pages for each module, I can simply jot down relevant tasks, and they'll appear on the front page as a combined list.

I've also started using vimwiki (no taskwiki yet) at work! It has given me more time to get accustomed to the bindings and nuances of the plugin, so I'm pretty happy about that.

The Good

  • As it turns out, a number of annoying Taskwiki keybindings have normal Vimwiki equivalents that are much nicer! Of note is Control-Space, which creates/toggles a checkbox. Since Taskwiki runs off of checkboxes, you can use it to create new tasks or mark existing tasks as completed.

The Bad

  • Turning my first good point around: Why does Taskwiki bother making and teaching custom keybindings for Vimwiki features? They're much less convenient and harder to use in general.
  • Taskwiki doesn't seem to have any convenient ways of inputting projects and tags for your tasks. You can do it as part of a filter, but otherwise you need to edit the task after creating it.
  • I decided to give task dependencies in Taskwiki a shot, but there's one big problem that I realized: Because of my date filters, dependencies with different due dates can simply not show up sometimes. As a result, dependencies are pretty much useless outside of project pages.

Time to code!

Now that I've played around with Taskwiki long enough to make it a part of my workflow and see the uses (and flaws) of the tool, it's time to fill in the holes. I've come up with a few tasks:
  1. I don't want to open my wiki every morning. Instead, I'd like to have that happen automatically. Thankfully, this is super-easy to do.
  2. I need a timer. It's easy for me to take a five minute break, then wake up after several hours of doing something else. I could look for a timer program, but timers are pretty simple and I'd like something that fits with everything else.
  3. I need a simple way to create tasks while I'm at work. This is probably going to be a tricky one to pull off, but I have some ideas.
Now, because this post is secretly a horrifying bait-and-switch, I'm not actually going to write any code yet. Instead, I'll be teaching you the secret art of baking a delectable 12" thin-crust pizza from scratch on a weekday.


You'll need the following ingredients:
  • 1 1/4 cups of flour
  • 1/2 cup of lukewarm water
  • 1/2 tsp salt
  • 1/2 tsp instant yeast
  • 2 tbsp olive oil
  • 1/4 cup tomato sauce
  • Enough mozzarella, possibly more
  • A few pinches of thyme and oregano
  • 1 small clove of garlic (optional, but recommended)
  • 1 tbsp dry minced garlic (optional, but recommended)
  • Toppings of your choice (optional, but recommended)

A few notes

Before we begin, I want to give a quick shoutout to King Arthur Flour. They have a ton of great ingredients and recipes, and the dough for this pizza is adapted from one of their Ciabatta recipes.

Disclaimer: I'm not an expert on cheeses, this advice is based entirely on personal experience.

The night before...

  1. The night before you plan on baking, mix together 1/2 cup of flour, 1/3 cup of lukewarm water, and some yeast. The precise amount of yeast isn't too important, just keep it between a pinch and 1/4 tsp.
  2. Cover the bowl and put it somewhere warm overnight.


The next morning...

  1. In a medium/large mixing bowl, combine the the mixture that you prepared with 1/6 cup of lukewarm water, 1/2 tsp salt, and about 1/4 tsp instant yeast. Add the olive oil and dry minced garlic, and stir the mixture together until it's combined.
  2. Add 3/4 cup of flour and continue until the mixture starts to turn into a solid mass. At this point, you'll want to keep adding small amounts of flour and mix/knead with your hands until you have a ball of slightly sticky dough.
  3. Rub a little bit of olive oil into a clean bowl or rising bucket and add the dough, then cover it and stick it into the fridge. (If you're doing this step in the afternoon, skip the fridge and go directly to the next step)

That evening...

  1. After about 8 hours in the fridge, take out the dough container and let it continue to rise for an hour. If you just prepared the dough, let it rise for 3 hours instead. While you wait, prepare your toppings.
  2. After this final rise, sprinkle flour onto a clean work surface and roll out your dough into a rough circle. Don't overdo it, try to keep the circle around 10". sprinkle flour onto your pan/baking sheet, and carefully transfer the dough to it. Using your hands, spread the dough out to the desired size, pressing your fingers to leave a slight lip at the edge.
  3. Set the oven to 500F (or however high your oven goes), and immediately place your dough inside. Let it bake for a few minutes until it just barely begins to brown, then remove the dough and place it on the stove. This step will cook the dough ever-so-slightly, making for a crispier crust. If the center of the dough has begun to puff up, carefully press it back down (be careful here, you don't want to get burned).
  4. Quickly add the sauce, garlic, cheese, herbs, and toppings in that order, and put the finished pizza back in the oven to bake. There's no universal bake time for pizza, because ovens vary in temperature. Instead, I recommend watching for the cheese to melt and brown to know when the pizza is finished.
  5. Pull out your pizza, place it on a rack to cool, and enjoy! The number of steps may seem off-putting, but I assure you that this recipe can be done without too much effort. Good luck!

5/1/17

Announcement: A newer, better schedule

With a new month comes a new and shiny schedule! Up until now, I've been mostly winging it with regards to posting here. My goal was one post a week, but I had no other rules to go by. It was a lawless wasteland, here on this blog!
Pictured: A lawless wasteland of blogging
It's time to end all of that. The sheriff's back in town and he's getting organized! Apologies about that not showing up until last Thursday, by the way. It was scheduled for the Sunday before but Blogger decided not to post it for some reason???
Being just a tad more serious for a moment, now that I'm capable of reminding myself about long-term tasks I'm going to try my hand at a proper schedule again.


The schedule

New posts will appear on Sundays at 9:00 PM (EST).

The last post of every month will be a large update post about my current focus. Between now and August, that's dfgame. That post will come with higher production values than my normal posts, featuring images, videos, audio, or something else entirely.

Besides the big update, I will also make two smaller posts every month. These can be about anything I want, but will likely resemble the type of content that I've posted in the past.

On one week each month, I won't post anything. This break can be taken on any week besides the last, and it'll hopefully keep me from having to apologize about delays or throw together something uninspired at the last minute.

Announcement posts (such as this one) will not count towards the monthly post count.


Summary

Expect one fancy post at the end of each month, and two little posts in-between. Assuming they're on time, posts can be expected to arrive on Sunday evenings.

I might also try to make my posts funnier. I like to think that I'm a pretty amusing fellow in real life, but dear lord are my blog posts boring. Hopefully, that's about to change.

Expect the puns. Fear the puns. Become one with the puns.

4/30/17

Roundup, April 2017 - A hole new perspective on falling into bottomless pits

Today, I'm doing something a little bit different: I've created a video for this update!


Additional Comments

It has been a while since I last posted any videos, and this is my first attempt at making something more detailed than a simple playthrough. In my opinion, the result is ok. I think it was a pretty good decision, given that I mostly worked on graphical stuff this month.

The video contains an overview of the update, but I wanted to add a couple of details that didn't make it in:
  1. Axis inputs received a few changes that I didn't mention. First of all, they are no longer 2d. Each axis is independent. They're also missing the "joystick emulation" input smoothing at the moment. I'll be adding that back at a later point.
  2. I've made a ton of bugfixes this month. There were a lot of things (especially in the core module) that didn't quite work, but testing them didn't seem worth doing until I had an actual use for them. Now that I'm building demos, I'm running into the issues and fixing them naturally.
  3. Lastly, I've written a bunch of macros for printing out certain structs to logs. This makes debugging much easier, because I can quickly print out the value of a matrix/vector/quat with little effort.

Goals

Let's start with the current state of the project:
  • Time left: about 3 1/2 months
  • Application Module: Done 
  • Audio Module: Not Started
  • Core Module: Done
  • Editor Module: Not Started
  • Gameplay Module: 80%
    • Missing joystick emulation for input
  • Graphics Module: 40%
    • Missing sprites
    • Missing text
    • Missing framebuffers
    • Missing particles
  • Math Module: Done
  • Resource Module: Not started
I'm making pretty good time right now. My goal for May is to knock out the Audio and Resource modules, which will leave me a couple months to reimplement the more advanced graphical features and make API easier to use. I've decided not to bother with the editor module for now, because it won't be useful for game jams and concept work. Instead, I'm going to work on it after the deadline has passed.

Next week, I'll be unveiling a new schedule and discussing my forays into Taskwiki in more detail.

4/23/17

Getting Organized - 3 - Impressions on Taskwiki

It's been a week since I started playing around with taskwiki, and I'm going to share my thoughts on it so far. Two weeks isn't enough to get a truly complete view of the plugin, but I still have a few things that I can discuss.

At this point, I've set up a nice segmented todo list on the front page of my wiki. By carefully assembling some taskwarrior filters, I've created 3 main sections: Today, This Week, and This Month. The sections are pretty self-explanatory. I haven't played around with making tasks for my projects yet, so for now it's mostly a way to track chores and real life commitments. So far, it has been pretty helpful in that regard!

I gave my initial thoughts on taskwiki in my previous post, and now that I've had more time with it I've compiled a more detailed list of thoughts:

The good

  •  It takes out a lot of the tedium of using taskwarrior, and it's easier to commit to. Having an interactive interface lets me keep it open all the time, rather than forcing me to remember to pull it up regularly.
  • Using taskwarrior's filters with taskwiki makes them much easier to deal with. Without taskwiki, I'd need to type out (or tab-complete) several filters and call taskwarrior with each one. With taskwiki, I can use filters with more of a "set it and forget it" attitude.

The bad

  • I ran into an annoying bug today. Taskwiki updates the status of your tasks when you save the page. However, if a task is shown in several spots then these copies can conflict with each other. For instance, you could mark a task as done, then see it "un-mark" itself because another copy wasn't marked. I doubt it'll happen very often, but it's an inconsistency that will surely return to annoy me in the future.
  • To add a new task to a list, you can just add a new line at the end. This is good! However, adding a new line at the heading with the filter or in the middle of the list doesn't add a new task. This makes the feature much more vexing than it really ought to be.
  • Setting a specific date on a task feels pretty inflexible, because you need to write out the date (e.g. 2017-05-01 rather than 05-01 or May 1). To get around this, I've set up my lists to choose dates for me when I add tasks to them.
  • Even with my list in front of me, I still tend to ignore things outside of the "Today" category. If I set a task for something that I need to do this week, I probably won't pay it much attention until the date gets close. This isn't a taskwiki problem, but I definitely need to do something about it.

To sum up the above list, I like the convenience of taskwiki but it has several niggling issues that annoy me. For now, I think I can live with them.

Next week will be something different, but I'll be back with more thoughts once I start making wiki pages for my projects.

4/19/17

Taking a break this week

Just a quick update to say that the next 'Getting Organized' post will be arriving next week. Some may choose to find this delay ironic, but in this case I've realized that the week is going to keep me too busy to make a proper post.

4/10/17

Getting Organized - 2 - Looking at Options

Last week, I wrote about my plan to try and help myself get organized. After that, I spent the week trying out tools and planning.

What's available?

The taskwarrior site has a tools page, where a number of tools and scripts are listed. There weren't many that looked useful, but I was able to find a handful of relevant tools and tried them out.

Tasky

Doesn't work. It's a few years old, so I suppose that's to be expected.

Taskswamp

Taskswamp is a python script that creates a tmux session with predefined taskwarrior filters. Basically, it lets you create a window with several tabs, each displaying different views of your tasks.

Some thoughts

  1. Taskswamp doesn't update its view without user intervention. This means that you have to press a button to refresh whenever the window is resized or your tasks change.
  2. It also fails to start up properly unless you open another tmux session first. I could use a script to do that automatically, but it's still a little bit of extra effort.
  3. Lastly, it puts the new session inside of Xterm. It doesn't offer a choice of terminals, or check environment variables for your default terminal. That's unfortunate, although I could probably live with it.

Tasknc


(note: text redacted)
Tasknc is an interactive curses-based client for taskwarrior. It theoretically supports all of the basic features of taskwarrior, such as creating, editing, and deleting tasks.

Some thoughts

  1. Tasknc doesn't seem to be actively developed. This is unfortunate, because it has a few bugs.
  2. Unlike Taskswamp, the view will automatically refresh when the window is resized. You still have to refresh it when your tasks change, but that's ok because it supports all the basic editing actions from within its UI.
  3. Deleting a task seems to make the application hang indefinitely. In addition, the add task command seems to display the wrong information. Both of these issues seem to have a workaround, but basic features being broken without extra configuration isn't a good sign going forward.

Taskwiki

So taskwiki is actually pretty great! It acts as an extension to the 'vimwiki' vim plugin. Basically, vimwiki lets you make...wait for it...wikis in vim. Taskwiki takes the concept a step further, by adding the ability to just throw a little checklist into any wiki page which automagically becomes a set of tasks managed by taskwarrior. Basically, it gives you a text-based method of managing your tasks.

You might be wondering why I like taskwiki so much, despite the fact that it fulfills none of my stated goals. It took me some thinking to figure out why I was so attracted to it, but I think I've figured out the reason: It gives your tasks a greater context. Sure, you can add tags and projects in taskwarrior, but this lets you organize and annotate those tasks however you want. You can make a new page in your wiki, write down some general description of something you want to do, then add a checklist of actionable goals to it. Those goals can then show up in checklists elsewhere, where you can check on their status or update them, and in the main wiki page you can add notes and other details as you make progress. Personally, I find that very exciting.

Some thoughts

  1. Taskwiki is actively developed/maintained. This is good.
  2. Resizes nicely, but you have to manually refresh your tasks.
  3. It was a huge pain to set up (about an hour of work). This is no longer important, but I figured it was good to mention.

Constructing a plan

I didn't find anything that really fills the niche that I'm looking for. I think I can adopt taskwiki to handle some of my needs, but I'll also need to make something to fill some of the gaps. So, here's the plan:
  1. Try to use taskwiki seriously for a while. I want to see how well using a wiki for organization actually works in practice, and there's only one way to do that. Next week, I'm going to write up a more detailed overview of vimwiki and taskwiki.
  2. After that, I'm going to start building some scripts to cover the features that I want. While I can't precisely say what I'll need yet, I'm expecting that I'll want some way to be directly notified of upcoming tasks, and I'll probably also want a way to quickly pull up the wiki when I log in.
Ad before you get worried about dfgame, don't! I've been working on it behind the scenes, and you'll hear more about my progress in a few weeks.

4/3/17

Getting Organized - 1 - Selection

One problem that I've been dealing with these past few months is organization. As the past 4 1/2 years of blogging should have made clear, I am not very good at managing my time and priorities. Now that I'm working 40 hours a week, the problem has gotten bad enough to seriously annoy me. So, I've decided to try and solve this problem the only way I know how: With software.

Looking back

I've tried a few pieces of software for keeping track of important dates and tasks. None of them have really stuck so far, so my first instinct was to write my own solution. However, I'm not going to do that. After seriously considering the idea for a minute, I've reached the obvious conclusion that creating a new project to try and improve my time situation is only going to make things worse. Instead, I decided to try and look at the problems with previous approaches and solve them.

Something???

In the months before and just after starting this blog, I was using some kind of todo list software. I remember almost nothing about it, including the name, and I can't find it anymore.

Google Calendar

During my college career, I used Google Calendar to keep track of classes and events. Beyond that, I never really bothered with it. My main issue with Google Calendar is the fact that it's an online service. I prefer to keep most of my applications off the web, mostly because webapps:
  1. Take up a disproportionately large amount of system resources to run.
  2. Won't work without an internet connection (duh).
  3. Take up an extra tab in my web browser.
  4. Usually collect personal information to sell/profit from.
 I see the appeal for most "normal people", but I can't stand webapps. This disqualifies Google Calendar right off the bat.

Calcurse

 For a while, I used a terminal application called Calcurse. Calcurse is an interesting program, because it gives you a nice curses-based calendar UI in the terminal. However, I had a couple of big complaints:
  1. The way that Calcurse handles todo lists leaves a lot to be desired. Unlike regular appointments, the program doesn't let you add items to your todo list with any sort of time attached. If you want to do something by next week, you need to make an appointment, rendering the todo list useless. Worse still, Calcurse won't try to warn you about the appointment ahead of time besides tossing you a notification a few hours or minutes before.
  2. In practice, Calcurse is incredibly aggravating to use. When you start it up, you have to hit enter to pass a message saying that it has loaded up. You have to do the same thing when you exit, but then it also prompts you just to be sure you want to quit after that. So, you have to hit 3 different buttons in turn to exit, for no good reason. It might not seem too bad at first, but it's super annoying and I don't know of any method to disable it. On top of that, it splits everything into 3 different panes, and you have to cycle between them with the tab key. They couldn't give you a "go back" or "go next", or just 3 buttons to select the specific mode that you want. Nope, they decided that you'd have to press tab until you got where you wanted.
 This program is a usability nightmare. I'd like to avoid using it.

Taskwarrior

...This brings me to the last option, going by things that I've used previously. Taskwarrior is a task management program that works really well for keeping todo lists and does a good job of prioritizing tasks.

I really like Taskwarrior, but I can't ever seem to make it stick. The main reason for this is probably because it's a basic command-line tool. There's no interface, only commands. This makes using it pretty inconvenient, as you can't just keep a view open to glance at or see notifications when time-sensitive tasks are coming up. Taskwarrior is more of an interface than a user-friendly application, which makes using it without any extra tools pretty annoying.

Of the options I've looked at, I think Taskwarrior is a pretty clear choice. While I still have to do some work to get it working, most of the heavy lifting will be already done for me. Hopefully, this will keep the time investment for this solution low. Hopefully, I'll be posting updates on this soon after I make more progress. Stay tuned!

3/27/17

DFGame - Rendering Improvements

One of my main goals for DFGame is to make development fast and convenient. Some people might consider something like this to be impossible with a low-level language like C. However, there are a number of tricks that I've been using to improve the simplicity of DFGame. To see how this works, I'm going to compare and contrast the graphics code from before I started working to now.

Friendly warning: The contents of this post are going to get a bit technical. If you aren't fascinated by APIs, you may not be interested.

Shaders and Meshes

The first thing that we'll compare is how to create shaders and meshes.
The old method is simple, but not great. Both asset types can be loaded from files, but if you want to include any shaders in your code then you need to write them as strings. To help you visualize, here's an example from the old version of the code:

static const char* quad_fs[] =
{
    "#version 330\n"
    "uniform sampler2D texture;\n"
    "uniform vec4 color;\n"
    "in  vec2 v_uv;\n"
    "layout(location = 0) out vec4 f_color;\n"
    "void main() {\n"
    "f_color = texture2D(texture, v_uv) * color;\n"
    "}\n"
};
That's more or less how it looks. There's no syntax highlighting, and every line has to be quoted and end with a "\n".
To create a new mesh from code, you specify the number of vertices and the type of data that you intend to store. The result looks a little like this:
create_mesh(vertex_count, VT_POSITION | VT_TEXTURE);
Not too shabby, but we can do better.

Next, let's see how it's handled now!
The first big difference is that I no longer need to put shaders in my code in order to compile them in. After discovering a code generation feature in Meson, I wrote a small program to generate C headers from shaders. The resulting headers go to the trouble of embedding the code for me, and I can simply include them in the code wherever I wish. I also made the generator write macros so that I can make a single call to get the compiled shader, ready for use.
Mesh creation has changed a little as well. Instead of initializing a buffer with the components that I specify, I've made a simple generic macro (another very neat thing that I learned a few months ago) that can infer what components you want based on the data that you pass in. To extend this I'm planning on making it possible to add/replace data in the mesh even if the data is in the wrong format, since I can figure out what's inside at compile-time. As you can see below, the result is a little more readable.

mesh_new(vertex_count, data);
As you can see, I've taken some decent code and made it even quicker and easier to work with. Changes like these are happening all over the codebase, so I have high hopes for the resulting framework.

One unfortunate thing to mention is that the updated version of dfgame can't load resources from files yet. In many cases, I'd load my meshes and shaders from elsewhere, but I can't compare how that will look until I get to it later down the line...

Binding Data

Now that we've looked at how meshes and shaders are created, let's look at how binding data to shaders works. In order to render a mesh, we need to bind the mesh being rendered as well as any additional data (textures, transformations, etc). Generally, making binding simpler also simplifies drawing code in general.

In the old version, there was a bind function for each type. Aside from textures, every function was more or less the same-it just called a different OpenGL function to bind the data. To try and get around this, I wrote a bunch of rendering functions that would bind things for the user. These would always bind to the same variable names, however.

When deciding how to update this part of the code, I decided to try and give a decent balance of simplicity and control. The rendering functions are no longer present (for now) but I've wrapped the binding functions in another generic macro. Now, I can bind almost anything I want with the same call instead of having to specify the type.

There remains one problem with this approach, however: Since meshes can have multiple types of data in their vertices, they need to potentially be bound to multiple different shader inputs. This wasn't an issue before, since variable names were assumed when binding. To get around this, I made my mesh binding function variadic (that is, I allow a variable number of arguments). The user can simply pass all of the names and data types that they care about in a single function call, resulting in something like this:

shader_bind_attribute_mesh(shader, mesh, "position", VT_POSITION, "color", VT_COLOR);
This is pretty simple, and if I wanted to I could make a name-less version that used the old assumed names.

Conclusion

There are still many parts of dfgame to review, and I'm certain that there are many other places where the API could use a helping hand. The few parts that I've touched have already benefited immensely, and I'm excited to see where things go from here! These posts will hopefully be a little less dry once I get out of the graphics code, but until then hang in there!