2019 in review

I was randomly asked whether I was going to write a summary-of-the-year post or anything, and I thought "sure, why not", and proceeded to spend a day doing that.

Work

This year seemed pretty productive in terms of projects,

Rivals of Aether

This year my involvement with RoA expanded to cover Steam Workshop features, for which I provided a custom scripting language (alike to what is seen in Nuclear Throne Together). With update released, the game have been seeing an impressive amount of user-created content - from well-balanced original characters to content adaptations from various games to hilarious/absurd ideas and joke characters.

There remain to be issues to overcome in terms of netcode updates and console features, but I'm confident that we'll get these ironed out soon.

Forager

Although I was originally introduced to Forager team to aid with networking, this year I was mostly helping with the modding update. As of writing this post, the update is not yet released, but a lot of work had gone into it, and I expect it to do at least as well as Rivals' modding support did.

Next year I'll be more involved on actual netcode.

Nuclear Throne

This year Nuclear Throne came out on Switch, and, more recently, on Epic Game Store, with "free game week" finally offering a chance for those who didn't want to buy the game at full price.

Since Nintendo do not commonly send devkits to Ukraine (in fact, I wasn't even able to get my developer registration form approved), my involvement was limited to consultation on how everything works.

EGS version went much smoother - since the game already had DRM-free builds set up, no additional effort was required, and I remained pleasantly unaware of the port's development up until it was suddenly established that a 64-bit OSX build is required, prompting me to hastily re-assemble a GMS2 desktop version of the game.

Fromto

During 2019 I was on and off working on netcode, menus, and mod.io integration for a game called Fromto. The game is essentially a platform racer that alternates between rounds of trying to reach the finish line and adding more parts to the level to increase your chances / decrease other players' chances to reach the finish line. With max of 4 players, the game gets incredibly chaotic.

I couldn't say that the game had any special requirements, but I used an opportunity to further refine cmnRPC and cmnMenu extensions while working on the game.

Links: website

Unannounced

Aside of these, I also did initial netcode pass for a few projects that have not been publicly announced as of writing this post. There's not much more to say as of now.

Tools

The following are the tools that I have worked on this year:

catch_error

In February I had this wild idea that, since you can rewrite DLL function addresses on Windows, I could make a DLL that would suppress the built-in error boxes - perhaps the most telling thing that you've used GameMaker for your game.

Then I had an even wilder idea that I could make the game not crash at all, so I spent about a few days staring at disassembly in Visual Studio's debugger to get that done.

While an admirable result, I probably wouldn't do this to myself again.

Links: itch.io · blog post

Pixelart scaling tool

While temporarily using a 43" 4K TV as a monitor, I made an important discovery: you can't trust Windows to upscale pixelart wallpapers.

So I made a small tool that can upscale/rescale pixelart images, meaning that you can shrink a 3x wallpaper back to 1x scale, and then scale it to the target resolution for perfectly crisp pixels.

Combined with simple alignment options, this can be used to quickly fit large libraries of pixelart images to the desired size.

Links: website

Tiny Expression Runtime

Thanks to support of a party that preferred to remain anonymous, I was able to take time to write the second part of my "small guide on writing interpreters", and subsequently publish a sample project.

Links: Documentation · itch.io · marketplace · source code

Quality Structures

This year I made a few more extensions that fix various GameMaker inconveniences, the most noteworthy one being this - the extension takes a lot of frustration out of data structure debugging and offers to show descriptive errors before something goes horribly wrong

Links:: itch.io · marketplace · blog post

Pixel fonts

This year I finally got around to publishing a set of pixelart fonts (that I made over course of several years for various personal projects) on itch.io. Most of these have a clean look with emphasis on readability and localization (some have over 500 glyphs!).

I hope to add a handful more to this collection next year.

Links: itch.io

mod.io integration

I wrote the official GameMaker plugin for mod.io, which is a cross-platform mod API - a far better idea than tying your game to Steam Workshop and suffering for it when you decide to publish to more storefronts.

Although the plugin is perfectly functional and a few games use it (incl. Fromto), I'm yet to write a proper step-by-step setup and/or a video, so users are expected to look at the simple example attached.

Smaller tools & updates

Apollo rewrite
Early this year I pretty much completely rewrote my Lua wrapper extension, this time making good use of Lua specifics for performance boost.

Raw Input
Admittedly exotic, this extension lets your GM games distinguish inputs from different mouse/tablet/keyboard devices.

High-precision HTML5 get_timer
In short, GM's implementation of get_timer does not use the performance API that offers a high-precision timer. This extension fixes that oversight.

debug_get_callstack for HTML5
Akin to above, but fixes debug_get_callstack to work with scripts.
(by default it doesn't due to JS obfuscation)

Instance Flags
A small solution to a common problem.

function_get_address
I'm somewhat proud of this because of how elaborate the sequence of bugs that triggers this accidental revival of a GM8 feature is.

YY-YAML
Saves a lot of headache when dealing with branch merges (for version control) in GMS2.

Colored external debug log window
Having colored debug messages that you can properly select is a surprisingly nice thing to have.

Tools (unreleased)

The following are the tools that I worked on, but haven't released yet:

cmnRPC

A small, elegant system for remote procedure calls and managing network state.

Combined with GMEdit's inline functions or the ones coming officially in GMS 2.3 update, the extension removes a lot of friction from writing netcode - you write what you like to send and then how you want to process that information upon receiving, all in one spot.

cmnChat

An advanced chat system that has just about everything that you could expect - text cursor (and selection), clipboard operations, command history, even auto-completion for both commands and their arguments (see a larger GIF).

This year the extension made its way into Caveblazers, Forager, and a few unannounced projects.

cmnMenu

A backbone for your own menu systems, cmnMenu takes care of menu management, massively cutting the amount of code it takes to have a well-working menu, and also allowing menus to be written in a far more intuitive way (if (menu_thing()) { actions to trigger }).

GMS2->GMS1 converter

This is something that I have been thinking about, but did not expect to ever have a reason to actually make.

I was approached by Ratalaika Games about creating a converter very specifically for targeting PS Vita, as GMS2 lacks a Vita export, but all of the games have already been ported to GMS2 for sake of other platforms.

The tool converts majority of GMS2 resources back to GMS1 format (in possible extent), converts most GMS2-specific code structures to GMS1-compatible format, "un-converts" many compatibility scripts added upon importing a GMS1 project into GMS2, and even adds some custom scripts for GMS2-exclusive features (such as layers or animated tiles).

Although currently in development, the tool will be eventually publicly available and open for contributions - something that you can thank RG for.

GMHyper

GMHyper is a tool that can rewrite your YYC code right as it is compiling, allowing for a variety of tricks such as strictly typed variables (to much of a performance boost), tailored versions of various built-in functions (ditto), and usually impossible features like using C++ APIs directly or straight up injecting C++ code into your GML scripts.

Combined with a flexible system for defining custom rules, the tool greatly expands the horizons of what can be done with GM on high level.

GMTogether


A familiar-looking menu while using the tool with Hyper Light Drifter

You might have already seen me posting a small teaser of this on Twitter, but - basically I'm working on a tool that can "inject" online multiplayer into countless GameMaker games.

Although the result might not be as refined as game-specific mods (read: there is only so much you can do about generic lag compensation), the tool warrants equal conditions for players (making it a better choice for versus games than stream-based solutions like Parsec / Remote Play Together), and offers a large number of options that can be tweaked for quality of life and/or compatibility.

Tools (work)

The following are the things that I did but which are not going to see public availability due to being something people paid me to do and/or associated complications:

GML->C# converter

Due to unforeseen circumstances, a client wanted to port their existing (~5K LOC) codebase from GML to C# + Unity. I wrote a tool to perform project-wide analysis and type inference to generate C# code that a C# programmer could then write a custom "GML API" for. The nature of conversion process meant that the resulting code does not need to be edited, allowing the GML version to be updated until the C# version is fully functional.

(...there was supposed to be something else here but I forgot what)

Game mods

Boiling Hot

A small exploration of C# (IL) bytecode injection using Mono.Cecil to add a SUPERHOT-like mode to Unexplored, made in a few evenings in February.

Perhaps one of the best (added value):(lines of code) ratios among my work.

Developers of both Unexplored and SUPERHOT seemed happy with it, so I'd say it did well.

Links: itch.io

Caveblazers Together

After somewhat stretched-out development and some unexpected hickups, Caveblazers Together finally released in March, mostly to no media response.

Although an interesting experiment, I probably won't do another game-specific online multiplayer mod any time soon - the conditions in which it'd make sense to make an online multiplayer mod instead of an official integration are just way too specific, and CBT probably didn't even fit them.

Links: Steam · blog post

Personal life

For the most part, my personal life this year had not been very far off from the "a rock in a forest" absurdist humour account on Twitter (in Russian) - most of the year could be evenly described with "nothing particular happened today".

Due to constant project schedule overlap, I did not end up going on a vacation during summer this year, although I did move to a slightly nicer city around early autumn. As a bonus, I discovered that living in an apartment with adequate amount of sun/sky light coming into a bedroom does help to maintain a consistent sleeping schedule. [who would have thought]

I still walk around a bunch (2.5..5km every other day, with peaks of >10km), though at first I was caught off-guard by number of random staircases that you might take while cutting distance by foot - to the point where sometimes the phone gives up counting and gives you an equivalent of "I don't know, a lot". Being able to occasionally go for a walk and stare at the sea and/or the seagulls is pretty sweet though.

Also, since, apparently, the winter around here now just means "+1..8°C at 100% humidity for 3 months" (which, depending on wind, makes for suboptimal weather for a long walk), I bought a used XB1+Kinect off someone and been playing Just Dance on that.

2020 goals

Take it easy

...-er.

Although jumping between a number of different projects is fun in it's own way and keeps you occupied, the situation becomes a less entertaining as soon as more than one projects needs something done at short notice.

The light pain in a few of my fingers during prolonged work also suggests that it would be better to not have to mash the keyboard for too much at once.

Overall this entails wrapping up some of the existing projects and resisting the urge to take up new ones even if they look Really Cool (this had been a long-lasting problem for me).

Draw more

... and start publishing art more often.

As you might have seen, my recent posts have been spotting doodles here and there, and I've been doing these on a semi-regular basis, but as of yet they remain scattered across a number of Discord servers and other shared chats.

I intend to start publishing these, as many people find my work entertaining.

Make a videogame?

... maybe?

I don't think I've worked on any personal game projects at all this year!
Except for a short game for Meditations, which I successfully wasted because I decided to politely ask what day to pick if I have no strict preference, and, by the time I got a response, all days were taken, so - better luck next time, I guess!

Hopefully I'll get around to doing something, maybe finally play around with Godot.

Work goals

Most of these are pretty obvious, but here's a small list without specific order:

  • Rivals of Aether
    More netcode and Definitive Edition work
  • Forager
    Netcode (once it's time)
  • Nuclear Throne
    Minor fixes, NTT updates
  • Fromto
    Various additions and netcode updates as the game development goes on
  • Nidhogg
    64-bit Mac builds because it's 2019 2020 and Apple are sending you warm wishes as they demolish 3/4 of an average user's Steam library with that OS update.

In conclusion

This was a pretty exciting year, and there's a lot to look forward.

Thanks for reading!

Related posts:

2 thoughts on “2019 in review

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.