Tuesday, 24 October 2017

Never be ashamed of your process if the result is good

Over the years I've composed quite a few songs that include my cello, but I never dared actually record and release them. I did publish some recordings before, but I've always marked them as "unfinished" or "quick sketch" or some other excuse, planning to practice more and make a better recording later on. Today I finally have one that I consider "finished", but the process ended up quite different from what I expected back then. It's called Growl, and it's a loud cello duet. Have a listen!

I'd love for others to also play this composition, so I've made sheet music for it as well. Let me know if you end up playing this composition: I'd be honoured and would like to hear how it went!
I've also made a start with making a page that collects all my music and sheet music. It currently doesn't contain much yet, but I intend to record and release all my compositions. That means I have a lot of work ahead of me, as I need to record another duet, two solo cello pieces, two trios and a bunch of songs that combine cello with electronic instruments. I'll add songs to music.joostvandongen.com as soon as they're finished.

The reason I never finished recordings before is that playing cello well enough for a recording is incredibly difficult. This is difficult on any instrument and the particular challenge of cello is to play perfectly in tune. There are no frets like on a guitar, so place your fingers a millimeter too high or low and you're out of tune. Since most compositions require jumping around the fingerboard it's a huge challenge to always jump exactly the right amount.

I always figured I would solve this by practising more, and indeed I did practise quite a lot (for a hobby player, that is). However, by now I've played cello for over 25 years and I'm still not there. I'm not a professional cellist who can practice several hours every day for years, so I've finally concluded that I'm just not going to get good enough to live up to my own requirements. But I want to share my compositions! So I've reached a different conclusion: while I'm going to keep practising to get better, I'm henceforth also going to 'cheat' wherever needed to make recordings sound better.

I use two main cheats. One is that I play with a clicktrack: while recording I hear the ticks of a metronome on my headphones so that I play at a constant speed.

The other and bigger cheat is that I record the song a bunch of times. I then mix and match parts from each recording to get a complete recording that sounds acceptable. I tend to make different mistakes every time I play a song, so if I record it enough times I'm bound to get every note right at least once. Growl is a duet, so two cello parts, and each of the two cellos in Growl is a combination of six different recordings. Heck, if needed I can even use autotune to correct an individual note (this is used exactly once in Growl).

Mixing recordings together works a lot better than I had expected beforehand: if I mask the seams carefully then afterwards I can't even tell where they are. You might think you can hear them, but the lifting or shifting of the bow sounds so similar to a seam in the mix that you need to be a real specialist to be able to tell the difference.

Working like this makes me a bit cynical, since I wanted to be a good enough cellist to just record everything once and it's perfect, and clearly I'm not. However, if there's one thing game development has taught me, it's that it doesn't matter how you make something. The only thing that matters is the end result. If it's fun to play, then it doesn't matter whether the AI is truly intelligent or just pretending to be so. It's okay if everything is smoke and mirrors as long as the player doesn't notice it. The same goes for any creative endeavour: if it sounds/looks/feels good then it is good. There's no higher goal other then the end result and your creation isn't any worse or better depending on how you got there.

Sunday, 15 October 2017

Working with generic room-based matchmaking

When creating matchmaking for a game you can either build it all yourself, or use a generic system provided by the platform you're releasing on. Steam, Microsoft, Sony and Nintendo all offer similar room-based systems. The basic idea is that clients can create, search for and join game rooms, and the actual decision which room to join is entirely made by the client. There's very little actual logic happening in those matchmaking servers. Today I would like to discuss how they work and what benefits and limitations they come with.

As far as I know most smallish games build their matchmaking using these generic room-based systems. The big triple-A developers seem to usually build everything themselves from scratch, but that's too much work and too much server maintenance to be feasible for most smaller developers.

Our own game Awesomenauts initially launched using these basic room-based systems. We didn't develop our own matchmaking system Galactron until years later when we concluded that the requirements for a genre as demanding as a competitive MOBA don't sit well with the limitations of such generic room-based systems.

The specifics of the systems that Steam, Microsoft, Sony and Nintendo offer aren't public and thus can't be discussed here, so I'm not going into any detail on how they each differ from the generic ideas described here. However, they share enough that I feel this post is very relevant if you ever make matchmaking for any of these platforms, or another platform that's built on similar ideas.

The basic concept is that the platform holder runs servers that handle rooms. A room usually represents a single match with a bunch of players in it. For example, in Awesomenauts a room would have the 1 to 6 players in it that are playing together in a match. If a player wants to join a match then the game will ask the server for a list of all rooms that have a spot left for at least one more player. The game then chooses which room is the best fit and requests the server to join it. Upon joining the game receives a list of the other players in that match and can make a connection with them and start playing.

It's important to realise that the room doesn't actually run the game. It's not a gameplay server. Usually one of the players is the gameplay server. All that the room does is keep a list of who's in the match and allow players to search for matches to join. The room is only intended for finding and maintaining lists of matches and can do very little else.

Since the room doesn't handle the actual gameplay it can often be closed once the match has started and the players are connected. Only if you support drop-in do you really need to keep a room up once the match has already started. Whether closing the room once the match has started is actually how it works depends on the platform though.

The server that handles the room can do some basic logic, but generally not much. One of the most important things it does is limit how many people can be in the room. You usually set a limit and if two players try to join at the same time while there's only space for one, then the server will make sure only one actually succeeds. This solves one of the more hairy race conditions around matchmaking.

Rooms aren't just usable for matches: you can also use them for some other things. A simple example is a chatroom. This is simply a room that players use to exchange chat messages, for example if you have global chat somewhere in your game's menus. Whether rooms scale to large numbers of players for a true global chat varies per platform. This case also shows another use of rooms: often it's possible to send messages to other players in the same room through the rooms server, without actually connecting to other players.

Also, if the client is in a room it will get notifications of changes to the room and of messages being sent through the room. You shouldn't expect rooms to be able to handle high numbers of messages or send them quickly, but something like a chatroom where lag isn't really an issue might be suitable, depending on the platform.

A more common use of rooms outside gamerooms and chatrooms is setting up a party to play with: this is also usually a room. This kind of room starts out with just one player in it, and if that player invites friends to play together then they join her party. The party leader then does matchmaking to find a room with enough free spots for the entire party.

Joining a gameroom with a partyroom of several people is often a hairy thing to develop. If the platform holder didn't supply anything for this particular situation then there are a lot of things that can go wrong that you need to solve. For example, what if a party of 3 players starts joining a room that has 3 empty spots, but by the time two of the players in the party have joined someone from outside also joins that room, taking up the final spot? In that case you need to roll back the joining for the two players who already joined and go back to searching. The number of edge-cases that might occur here is pretty horrible and is just one example of why developing an online multiplayer game is so much more work than developing a single player game. (For some more reasons check this blogpost on why adding multiplayer makes game coding twice as much work.)

Another interesting challenge when using generic room-based matchmaking is what supposedly happened to one of the Gears of Wars games at launch. Rumour has it that their matchmaking broke down because lots of clients all decided that the same room was the best one to join. Only a few got in before it was full, and then the remaining players all tried joining the same next room. Since each time most would fail it often took so many tries to actually get into a room that the matchmaking took forever. This particular situation is difficult to test without a large playerbase and definitely something to consider during development.

Rooms allow for additional data to be stored in the room. This data can be used in any way the developer sees fit and will probably contain information on the game mode, the skill of the players in the match and the map on which the match takes place. This way when a player is searching for a specific game mode the game can look through the list of rooms for one that's the desired game mode. This also allows the game to check whether the other players in the room are at a similar skill level as the player. Rooms can hold arbitrary data as the developer sees fit, but they generally don't allow for a large amount of data, so only the essential stuff is stored here.

While it's often relatively easy and quick to use the matchmaking systems that platform holders provide, there are some downsides to this approach. One of the most important ones is that if you make a multiplatform game then you'll need to build this again for each platform. If you're doing simultaneous launch on 3 platforms then this is going to take a serious amount of programming work.

You might think you can reuse a lot of your code since the basic ideas behind these rooms are so similar, but in our experience the platforms have just enough differences that this approach quickly becomes a horror story. The old version of the Awesomenauts matchmaker supports 5 platforms: Steam, X1, X360, PS4 and PS3. We tried to abstract away the platform-specific details as much as possible, but adding code for all the weird edge cases each platform introduces has turned our old matchmaking codebase into one big tangled mess where any change might break any of the platforms. Designing a good architecture for handling the differences between these systems is a tough challenge, especially if you're doing it for the first time.

Note that the room systems on various platforms also can't connect to each other. So if you want to do cross-platform multiplayer then you basically need to write your own matchmaking servers.

Another problem of using these generic room systems is that they allow for very little server-side logic to be run. This is a huge limitation on how well you can match players. This is also the main reason we redid the entire Awesomenauts matchmaking code and built our own, called Galactron. This launched in 2016. The limitations on matchmaking imposed by a lack of server logic is a big enough topic that I'll write a separate blogpost about that soon.

The generic room-based matchmaking systems that platform holders provide make developing matchmaking a lot easier than without. They save you all the hassle of developing and maintaining your own servers, so unless you're doing a large production, chances are they are the best option to efficiently develop the matchmaking for your game.