March 27, 2023 ryanjuckett No comments

INVERSUS: Sixish Years of Sales

Back in fall of 2018 I posted a breakdown of the first two years of INVERSUS sales that you can see here. It’s now spring of 2023, and while at GDC last week I had a few discussions with people about indie game business that touched on INVERSUS. In my mind, it was still doing okay for the type of game it is, but I wasn’t actually sure what the numbers were. A sharper business person would be on top of all of that along with graphing out how sales perform and so on, but my time has been focused on the next game. 😅

Continue reading
July 12, 2020 ryanjuckett No comments

RJ_IMAGE (version 1)

While working on some new graphics features, I needed to store and load an intermediate image files with floating point pixel data. Up until this point any intermediate texture data generated by my build pipeline was stored as TGA files. This was useful if I needed to inspect the data because I could just load it up into Photoshop and see what was what.

However, it also meant I was limited to a very small set of pixel data formats. I needed a new solution so I started looking at image file formats that could handle floating point data. Immediately I encountered formats built for HDR images like RGBE and OpenEXR, but was not pleased.

Continue reading
October 18, 2018 ryanjuckett 5 comments

INVERSUS: Two Years Of Sales

I’ve always made time for reading postmortems about sales. They were useful when I first considered going indie and are still useful today with over two years of selling INVERSUS behind me. Whenever peers ask how the game did (or is still doing), I find it hard to frame the answer. INVERSUS is not an obvious runaway success nor is it a failure. It sort of “does well enough” given how my solo studio, Hypersect, is run. Hopefully sharing some specifics of how it has sold will in turn help you evaluate past and future decisions.

Continue reading

May 23, 2018 ryanjuckett One comment

Additional Thoughts on Skill Ratings

I suspect I’d get significant value from writing about systems earlier in their development because breaking a system down in words often leads to new insights. Over the past week I’ve been thinking about my recent post on how online skill ranking works in INVERSUS Deluxe. If you haven’t read it or aren’t deeply familiar with skill rating systems, you might want to click that link or the rest of this won’t make much sense.

One of the primary hurdles that I had integrating Glicko-2 (and that most games have from my understanding) was applying the rating periods. INVERSUS forces a rating period to pass with each completed match and then also runs a separate step forcing inactive rating periods to be evaluated for players that have been away from the game for a while. This has two downsides:

  • Depending on the frequency you play matches you will evaluate more or less rating periods than others.
  • Rating periods never get to evaluate more than one match at a time (which would be preferred by Glicko). That said, I haven’t run through the math to know how much that actually matters.

I now believe that you should be able to get the best of both worlds and let rating periods get a fixed time (e.g. a week) but still give players instant feedback after each match. The idea is to change the interface to process less than one rating period and take input representing the intermediate computations from any prior call. It would then update the intermediate state to be used by a future call and output what the players rating, deviation, and volatility would be as of right now (partially through the rating period). Internal to the system, it would continue to append match results to the intermediate state and reevaluate the current rating period from scratch with the additional supplied information. The resulting logic  would be something like:

  1. If the additional time step has advanced to a new rating period, commit the prior rating period’s variance estimate into a new rating, deviation and volatility.
  2. Apply any necessary inactive rating periods if the time step is greater than one rating period.
  3. Apply the new match results to the tracked intermediate values necessary for computing the current rating period’s variance estimate. Note that we shouldn’t actually need to track the full match history for this rating period, but just need to update the accumulated values.
  4. Output the player’s displayable rating and deviation by evaluating the current intermediate values for the partial rating period state. Note that these values are actually logically recomputed across the entire current rating period until step 1 commits them and starts a new rating period on a future call.

I’m pretty sure that would both work and not be too complicated implement. Maybe someday, I’ll go back and try it out, but for now I just want to put the idea out there for others!

May 15, 2018 ryanjuckett 6 comments

The Online Skill Ranking of INVERSUS Deluxe

Online skill ranking was one of the big features added to the Deluxe edition of INVERSUS and building it was uncharted territory on my part. It required a bunch of learning and is one of the systems players ask about the most so I’d like to share some behind the scenes details regarding how it works.

Rank Points and Skill Rating

From the player’s perspective, they earn and lose Rank Points (RP) while playing online. I wanted the Rank Points system to achieve two goals:

  • By inspecting a player’s RP, you can tell how challenging they are. Players with a higher RP are expected to defeat players with a lower RP.
  • You are awarded and deducted RP in a manner that matches your expectations. If you win, your RP should increase. If you lose your RP should decrease.

While those goals might not sound like anything special, they can actually conflict because computing a statistically accurate skill rating (the first goal) can produce results which are both confusing and do not match player expectations (the second goal).

  • There might be wild fluctuations as the system is first learning how you perform.
  • There might be counterintuitive ups and downs such as an increase in skill after an expected due the system’s confidence level in your skill increasing more than its penalty for the match.
  • You might not actually gain any skill after a win if you were expected to win.

To mitigate these issues, the actual skill rating of the player is decoupled from the player-facing representation of Rank Points. Before getting into how the Rank Points are calculated, let’s dig into the actual skill rating system they are built upon.

Continue reading

January 3, 2018 ryanjuckett One comment

Hyperbot: Making a Discord bot for INVERSUS

The official INVERSUS Discord server (found at discord.gg/inversus) has grown to house an active community of both veteran and new players. Creating the community was my first introduction to Discord and I quickly came to see the advantages of having a bot to help automate common questions and needs. I first searched for an existing bot to integrate with the INVERSUS server, but nothing was very focused on being build around the community for a competitive game. I wanted features such as players positing invitations to their private lobby by typing !invite or having the bot automatically let everything know when a new high score was reached on the leaderboards. Thus, once I got the time to learn a bit about node.js and the Discord API, I went ahead and build my own bot, named Hyperbot, that I could add to over time.

Putting Hyperbot on your Discord server

If you are in a similar position and want a reference bot to start from or just want to boot up Hyperbot as is, you can find the latest code and documentation on the full feature set on GitHub at https://github.com/hypersect/hyperbot

December 19, 2017 ryanjuckett No comments

Improving the Font Pipeline

This post will be a bit different than my normal technical posts. Rather than covering a successful finished system, this will be a glimpse into the process of (hopefully) getting to that point in the future.

With INVERSUS finally out on all platforms, I can clean up some of the engine’s rough edges, and one of the bigger pain points has been the font pipeline. When it comes to refactoring workflows and engine architecture, I think it’s important to find tractable small steps you can take on the path towards your desired goal. I have a fuzzy picture of how I’d like things to be, and I make small improvements while at the same time getting a better focus on the destination.

Problems Everywhere

In my experience, the complexity of properly rendering text is an underappreciated problem by engineers that have never worked on it. It seems so simple! There are really only three steps:

  • Choose the next glyph to draw
  • Choose where to draw the glyph
  • Draw the glyph

So which of those steps is the hard one? Unfortunately, if you want to render crisp text in multiple languages across the world, all of them are the hard one.

Continue reading

October 5, 2017 ryanjuckett No comments

The Complexity of Simplicity: Rendering INVERSUS Deluxe

When discussing the visual style of INVERSUS, there has always been an amusing contrast between the random YouTube comment saying that “this could run on an Atari” and the periodic questions asking how I’m actually managing to draw what is happening on screen. We’re going to take a detailed walk through how INVERSUS Deluxe composes a frame, but for fun let’s start off by looking at an actual demake of INVERSUS for Atari that Ed Fries was toying around with (believe it or not, just finding a way to render the obstructions on the map was non-trivial).

Can you spot the difference?

Continue reading

September 21, 2017 ryanjuckett No comments

INVERSUS Newsletter – September 20, 2017

More news means it’s time for a new edition of the INVERSUS Newsletter!

Launch Schedule

Let’s get straight to it. INVERSUS Deluxe is launching on Nintendo Switch™ on September 28th and Xbox One on October 4th!

As you may recall, all of the current players on PlayStation 4 and Steam will be getting access to INVERSUS Deluxe as a free downloadable expansion. But when? The plan is to publish the Steam update alongside the Nintendo Switch launch on the 28th. The PS4 patch doesn’t have an exact date yet, but it will be in early November. I’ll be sure to send out a reminder once I have it locked in.

Feel free to share the news on twitter and anywhere else people pay attention to!

Community Tournaments

Have you checked out the official INVERSUS Discord server yet? It’s a great place to meet others for setting up matches or just getting tips to improve your game. It’s also now the central location for setting up community tournaments!

Starting this Friday we will be running a double elimination tournament for Steam players. Click here to sign up and enter the bracket! We are managing the tournament through a service called Challonge that automatically emails you and your opponent when you have a match available. After you sync up and play, you can log in, enter your results and then the tournament will progress. Head over to the #tournaments channel on Discord to meet your competitors, ask any questions or just follow along!

August 9, 2017 ryanjuckett No comments

INVERSUS Newsletter – August 9, 2017

It’s time for another edition of the INVERSUS Newsletter!

INVERSUS just got a whole lot bigger and it’s headed to Nintendo Switch™ this fall!

INVERSUS Deluxe

Last time we talked, I was working away on the 1.5 update. Then I started adding more content. Then I decided to add some more new features. I certainly wasn’t done adding more unlocks. And then I went and gave the whole thing a big visual upgrade. Looking back at the current game and what I had been building, I realized that it had become this giant beast of an update and just bumping the version number wasn’t enough. This needed a name!

INVERSUS Deluxe is still going to be a free update for all existing players and it will be the version of the game launching on Xbox One and Nintendo Switch (more on the below!). Click play to check out the trailer!

Let’s talk details:

  • 12 new versus maps and 4 new arcade maps create a total of 50 unique maps for players to enjoy.
  • Test your skills in the new single-player versus mode by facing off against AI Bots that scale in difficulty from beginner to world-class player.
  • The addition of ranked online multiplayer rewards skill in both 1v1 and 2v2 games.
  • New real-time soft shadows and high definition materials add a depth and richness to the screen.
  • With the new split-shot ammo, players can fork bullets and shoot around corners.
  • Equipping new unlockable motion trails allow players to show off personality in the arena.

Nintendo Switch

Ever since the Nintendo Switch was announced, I’ve had people telling me how perfect INVERSUS would be on it. Today, I’m happy to officially announce that INVERSUS Deluxe is launching on Nintendo Switch and to officially confirm that it fits like a glove. The game controls great on everything from a single Joy-Con to a Pro Controller.

I was pleasantly surprised to find how well the game works for a portable console. Playing a round in arcade mode or challenging the AI in versus mode both hit that sweet spot for filling some time while you are out and about. On top of that, the game looks fantastic running at 1080p 60fps undocked.

The online experience works great on Nintendo Switch as well with full support for public matchmaking and private games with people on your friend list. I can’t wait to start competing for the top spot in the new ranked online multiplayer!

Demo Demo Demo

PAX West is coming up at the end of the month in Seattle. I’ll be there showing the game so come find me! I might even get some shirts printed up (if I can magically find the time to make that happen).

I also want to say thanks to everyone that’s come by at all the shows I’ve been at recently! INVERSUS made it’s way back to EVO this year and also got to make it’s first appearance at San Diego Comic-Con thanks to the Behemoth! It’s a privilege to get to meet all the players out there and it’s well worth getting sick almost every time despite how much hand sanitizer I try to use 🙂