4 Hugues Ross - Blog
Hugues Ross

12/29/20

Moving Day

Hi everyone, just a quick blog post to give advance notice.

On January 1st, this blog (and the associated site) will be completely replaced! I've rebuilt the site on a new hosting platform, and I'll be throwing the switch to turn it on. There might be some brief confusion after that, and everything will look very different, but hopefully it will be a quick and painless process.

In the meantime, here's a little heads-up:

  • The domain hasn't changed, but 'blog.huguesross.net' will become 'huguesross.net/blog'. I might try to set up a redirect if I don't forget, but bear that in mind.
  • RSS is being discontinued, but Atom will still be supported. The new atom feed will be at 'huguesross.net/feed.xml' once the transition is complete. Some of the other forms of content on the site will get their own feeds as well, so be sure to check the new site for those.
  • Aside from the subdomain, blog post permalinks should be the same as before. I won't be importing most of this blog's content initially though, please contact me if you want something back.
  • Most of the other pages on this site will change URLs, so if you had them bookmarked you'll have to go back and change them. Sorry!
  • This blog will still be up at 'df458.blogspot.com'. I might delete it eventually, but there's no ETA and it won't happen for at least several months.

12/20/20

Royale Finale

We're finally here at the end of the experiment. Nearly 3 months after the original announcement, I've tried 9 different open-source engines and frameworks and written my thoughts on each. Now it's time to step back, do some comparisons on the group, and work out what I want to do going forward.

First, just to jog your memory I've assembled the complete list of posts:

  1. DFGame
  2. Godot
  3. HaxeFlixel 
  4. LÖVE
  5. Monogame
  6. PyGame (immediately and unceremoniously disqualified)
  7. Raylib
  8. SFML
  9. Heaps.io

 

The Predictions

In my first post, I talked a little about each lap and what I was expecting out of them (except Heaps.io, which was added to the list later on). Let's look back and see how they bore out.
 
DFGame fared about how I expected it to. This is no surprise, it's the one item on this list that I made myself so naturally it wouldn't really deviate from my expectations. Still, of note is the 'wordiness' that I mentioned in my write-up. DFGame's lap is the largest codebase by far, with the other (completed) games  ranging from ~400-600LoC, 25-50% smaller. It's not entirely C's fault either--raylib's demo is only 547LoC. If I was planning to keep it, I think a high-level API would be a must to remain agile.

Godot was probably the biggest upset of the bunch. I had only really heard praise for the engine, and several people I know and trust recommended it... but in the end I found it kinda awful.
On thing I feel obliged to note is that I've spoken to some Godot users after writing this article--for the most part, they don't really seem bothered by the issues I brought up. As a professional Tools Programmer with a (mild) UX background, it could be that I'm extra-sensitive to these sorts of issues. If you're unsure about Godot after reading my post, consider giving it a whirl to decide for yourself. It's free, so you have only time to lose.

HaxeFlixel is an odd one, because despite a very positive review I've since soured on it a little. I think as the first "good" lap, I overreacted to it a bit. The iteration times are really annoying, particularly paired with the logo that pops up at every launch, and there's something to be said for being the only engine on the list with physics issues that aren't clearly traceable to my code. Still, it's not a bad engine and it had easily the best documentation of the lot!
I think the other projects could improve a lot by copying HaxeFlixel's example site.

LÖVE is pretty clearly the "winner" of the bunch, hands-down. I was hoping that it would be good, since I remembered liking it, and it was. I have very few negative things that I could say, so here's a link to a post from 2012 where you can envision current me shouting "NO! YOU FOOL!" over an over.

Monogame was another big surprise for me. I was expecting to like it a lot more, but I bounced off of it pretty hard. For the record, it does seem to be a decent framework. Rather, I think it doesn't work well in the conditions I tested and doesn't really offer what I'm looking for. More on that in a later section.

Raylib was not what I expected at all. I was expecting something a little like DFGame (but, y'know, better), instead it was much closer to LÖVE. In the end, I think it mainly suffered from the language it was based on and the lack of a proper API. It could be interesting to check out the language bindings it has sometime in the future...

SFML was kind of a filler option when I put it on the list. I didn't remember it being all that great (something that you can see from the fact that I didn't bother using it when I was raving about C++, despite having tried it), and it turned out to not be all that great. I think there are better low-level options and better high-level options out there, so I don't plan to ever revisit this one.


Overall, there were a lot of surprises. I think this speaks to the value of trying out software, rather than relying on just word-of-mouth.


A Note on Language

One thing that I noticed during this whole process was that the language being used does matter quite a bit. On average, it seems like the full-blown OO languages under-performed a lot in this 6-day test. This doesn't surprise me much, since building up those kinds of structures adds overhead to the development process. I'm curious to find out how true the reverse is... will a larger script-based project break over the weight of its complexity? Time will tell, but I think this is avoidable with good design.


Another big deciding factor was compile times. Stopping to rebuild files really becomes annoying when trying to tweak gameplay, and I think the noticeably-slow compile times of Haxe make it a lot less suitable for games than it first seemed.

 

Eliminations

One last thing to look at before we wrap up is what options will do what I really want. Some time after starting this project, I hit upon a couple of requirements that I really wanted out of an engine/framework:
  1. Easy multiplatform support -- One thing that's held me back a bit with DFGame is the pain of porting to other platforms (like Windows. This is a real issue). It means that my audience is very restricted, and it's hard to stay motivated about a project no-one will play.
  2. Ease of Design/Iteration -- I don't think game-building tech needs a graphical editor, but it does need a way to quickly tweak assets and values with an 'in-game' view. That can be through hot-reloading or tools integration, but I think it's legitimately important for getting work done quickly.

Starting with the first requirement, we can eliminate everything based in C/C++. That leaves Godot, HaxeFlixel, LÖVE, Monogame, and Heaps.io

The second requirement is a lot more wishy-washy, since it's about how easily some things can be done. As a graphical engine, Godot definitely makes it in. Due to how it handles assets, Monogame definitely doesn't. The others are a little more up in the air... so for now, I'll leave them in. That leaves me with a final list of 4:

  • Godot
  • HaxeFlixel
  • LÖVE
  • Heaps.io

Setting aside preferences for a moment, I think these 4 engines are the most suitable for my requirements. Unless someone can find a way to bring Monogame back in or I find new engines to try, these are the engines most likely to show up on this blog again.


Coming Up...

At this point, I think it's clear that LÖVE is the engine that jives with me the most. Before I launch into anything big though, I have another project that needs some attention: this blog!

I have the next couple of weeks off, and my hope is to finally sit down and set up a unified site and blog on a new host. It's going to start out very simple, but hopefully having everything working off the same base will make updates easier later on. Once that's done, I think I'll try to spend at least a few months experimenting, doing game jams, etc. before I start on any larger projects. I think it's important to take time getting to know a new engine, and jumping directly into the deep end won't get good results.

12/13/20

Royale Week 9: Heaps.io

I didn't finish this week's lap, and frankly I don't have the motivation to do it. I'm in a bit of a weird position--I feel like I haven't delved deep enough to really give this engine a fair shake, and yet what I have seen so far doesn't inspire the confidence I need to keep going... all of this is to say that I don't like Heaps.io, but I'm not confident enough to say that it's entirely the engine's fault.

Regardless, let's talk about that experience a little.


My initial impression of Heaps.io was actually pretty good. The basic introductory text seemed to imply a pretty sane modern structure based on a scene graph, and the setup seemed simple enough. I didn't really like the focus on specific applications, but I figured that was mostly just to help out beginners.


My problems began immediately after that. The next major section of the documentation goes over 2D rendering, and shows a simple example of resource loading (here, scroll down to the Image section for that). What it doesn't mention is that you need to initialize a resource loader. Indeed, it doesn't mention those loaders at all! The first reference I found was a 1-line comment in a code sample several pages later.

If you don't realize this because you're not psychic, you'll get this helpful exception when you try that code:

"Resource loader not initialized: call to hxd.Res.initXXX() required"

...ok, so clearly a loader needs to be initialized, and the functions are in the hxd.Res namespace. See? I'm not being sarcastic, it is helpful!

 

Well, except that if you check the API docs you'll notice that there are no init functions listed. I'm not really sure why that is, but it's a problem. I also checked a good half-dozen of the official samples and conveniently, none of them had any sort of resource loader initialization either. Nice. The time I spent setting up loading code and searching the API and samples is a waste, because what I really had to do was:

  1. Skip from the second section of the documentation (H2D) to the fourth section (HXD). And as an aside, what does HXD even stand for?????
  2. Go into "Resource Management"
  3. ...and read that instead of the example that was given in the first place.

This is enough to progress, but there's no simple way to work out what resource loaders even exist. 'Embed' is used as an example, but if you look at the API page for it... Weird, there's nothing at all. And by the way, don't bother checking hxd.res.Loader. I know it seems like the obvious next place to look, but it contains nothing relevant to this search. To this day, I still don't know if there's a list of resource loaders out there.


After all that hassle, we finally have textures onscreen. At this point, I was pretty miffed but not nearly ready to throw in the towel. The apparent lack of vector math (more on that later) also didn't deter me, since I saw that collision detection code was available. Most of the math I've been doing in these demos has been bouncing a ball off of rectangles, so a basic collision API would cover that pretty well.

I'm going to spoil the punchline now and tell you that it doesn't cover that at all. You might think it would after looking at this sample, where they use built-in API calls to get the normals of a rotating collision object from a point in space. Amazingly, this function is entirely exclusive to the capsule collider class, for...some reason? Beats me. All I really need is the closest point from a circle-to-rectangle collision check though, so let's see what we get from that...oh. We get a bool, and nothing else.

 

At this point, I was starting to question how Heaps.io games handle physics, seeing as the built-in collision detection code doesn't seem to give anything that's needed for collision resolution. On a whim, I decided to check the hxd.col.Point class. It has all the vector math you could want! I should've been happy, but the only thought racing through my head was: "Wait, if this exists then why do all the scene graph nodes exclusively take raw floats???????"


And then, I stopped. Throughout these past 2 1/2 months, I've seen and dealt with a lot of weird and arbitrary API design, broken or incomplete docs, and a handful of runtime bugs. I've pushed through it all to bring you my opinions, but now? Now, I'm tired of this. Heaps.io put the last dagger in the back of my desire to try new game engines. I just don't have it in me to keep wondering about these things, and I think it's time to settle down and change gears.

Thankfully, that's already what's next on the agenda! We have one more post to round up all of the past engines and frameworks, and to declare a "winner" that I'll be playing with further.

12/6/20

Royale Week 8: SFML

This was kind of a weird entry, and the next one will be as well... I timed the demo out to 6 days as usual, but had to break it up over two weeks--let's just say I've been working on 2 AAA games simultaneously and one of them is shipping SOON™.

This may have hurt the demo a bit, but I don't think extra time would change my conclusions here.


SFML is a framework in a very awkward position, in that it seems to advertise itself both as one of those lower-level 'OpenGL/Vulkan access' libraries and also a higher-level 2D multimedia library. Since the goal of this little experiment is not to reinvent the wheel, I can't speak to the former use-case... but I'm not really impressed with the latter.


One common issue, perhaps the main issue I have with SFML, is the problem of trying too hard with its features and making the API worse in the process. Consider these examples:

For each 'instance' of a texture you want to draw to a window, you need to make a corresponding sf::Sprite object. You have to set transforms on the sprite, draw it yourself, manage the lifetimes of both objects, etc. It offers no gameplay functionality like the Sprite class in HaxeFlixel, so you can't use it to replace your objects.

The result is that any game object needs to copy its transforms over to this extra object on a regular basis, and you now have two objects to manage instead of one. Moreover, there's no simple 'just draw the damn texture' function. You can imagine a world where the sprite class never existed, and in that world it would be easier to draw textures onscreen...


SFML offers vector classes that you must use to represent positions. That's pretty standard... but what it doesn't offer is any of the corresponding vector math. There's no dot product, no cross product, and not even the humble length function. These vector math operations are the bread and butter of gameplay programming, but SFML expects you to provide them yourself. You now have a choice: write your own helper functions (which can't extend the API nicely, this ain't C#), or adopt a math library and convert types every time you make an SFML call.

Curiously, this situation is described in a very deliberate and matter-of-fact fashion in the docs. This proves that it wasn't an oversight, and it's almost as if the devs consider this missing critically-important functionality to be a positive.

In both instances the SFML devs thought of a useful feature, created the feature, but stopped short of the part that makes it useful. The result is baggage that the programmer must carry, but benefits little from.

 

Funny enough, this segues nicely into the next pain-point: C++ itself. I mostly swore off of C++ back in college, and have only used it in brief spurts since. I've grown a lot as a person since then, and I was interested to see how the language felt now... but no, it still sucks. Somehow, young and foolish me was completely right.

It has nothing to do with being lower-level, I've used C in two separate entries so far and been happy as a clam. It's not really about being higher-level either, I've used C#, Lua, and Haxe in this experiment as well. But something about C++ makes every new feature feel like an overdesigned mess that, get this, looks like the start of a useful feature but stops short of being useful. It makes me wonder how much of C++'s dominance in large-scale gamedev comes from inertia.


Well, I think that's enough ranting for one day. I'm tired, and the less time I spend thinking about this C++ and SFML tag-team the better.

Oh, and uh... the API docs are ok but they could really use a search bar.

11/23/20

Royale Week 7: Raylib

Ok, I'll admit it: I'm starting to get a little tired of Breakout. That won't stop me though, we're rapidly approaching the end of this comparison and I intend to see it through to the end!

Here's the customary gameplay video:


This one's pretty similar to some of the earlier options, but I mixed some of the paddle velocity when bouncing the ball and I think the 'mixed' version is an improvement. It gives the player a little more control on the ball, while still providing a more precise option.


I wasn't really sure what to expect from Raylib.It's a framework that I was aware of, but had never really heard of anyone using... I was very interested in this though, since I have my own little C framework (DFGame, from week 1) and I wanted to see how some of the problems I ran into were addressed. Being an old low-level language, C has a lot of limitations to think about in game development. I had to come up with my own solutions in DFGame, but many of them weren't ideal and I wanted to see how a more mature framework handled them.


Now that I've used Raylib for a bit, I have a pretty good answer: The framework seems to take a lot of cues from higher-level options like Monogame (but without the content pipeline), which relieves some of the wordiness with a simplified API. However, most of the other problems were 'solved' by being ignored outright.

The most egregious example of the bunch is asset paths. C doesn't offer a built-in way of finding the executable's location, so you have to use OS-specific system calls to find it instead. This is one of the factors locking DFGame to Linux, and it's one of the primary things I want to avoid in any new engine/framework. Raylib answers this problem by being completely unaware of it, and naively using the working directory to load assets. If you launch your game from anywhere it didn't expect, it will fail to locate your assets and crash.

This disqualifies Raylib for the purposes of the exercise, but I still wanted to play around with it. Let's look at the rest.

 

Now, you probably think you know where I'm going next: "He's going to moan about API documentation for a few paragraphs" You are wrong, of course, because Raylib doesn't really have any sort of formal API docs. It has this "cheatsheet" which covers only a subset of the API, and to my knowledge there's nothing more... not really much to say there.


Instead, talk about how Raylib feels to use. I think this is where Raylib shines, actually. Working in C made me feel at home like with DFGame, but since the API is much higher-level it felt a lot better to use. Honestly, I think if the dev can fix the lacking areas and put a good API doc in place Raylib could be a much more competitive option.