Moments of Inertia by Rachel Crawford

About     Archive     Categories     Tags     Feed     Projects     Magewinds    

2017 in Gaming

The annual roundup of games I played this year, both physical and digital, and gaming-related things I did, most of which I didn’t get around to writing about. Let’s get started.

Tolva

A standout for the year for me was Big Robot’s lonely, exploration-driven first-person shooter The Signal from Tolva. Part Stalker, part Ian McQue painting, it struck such a chord with me that I took the time to write a review of it. I’ll let you go and read that instead of nattering on about it here.

Blood and Wine

I completed The Witcher 3’s second expansion, Blood and Wine. Its writing isn’t quite as impressive or thought-provoking as Hearts of Stone, but it provides an exciting adventure and fitting farewell to the franchise and its characters. It also contains a whole new region to explore, which I did at length simply to bask in how gorgeously colourful and sun-drenched it all was. Quite a change from the main game’s grim and stormy lands. I hope Geralt enjoys his retirement in Toussaint.

A Return to Tyria

The announcement of Guild Wars 2’s second expansion prompted me to revisit that game and finally level my character to 80. On paper, Guild Wars 2 is an iteration of the MMORPG formula ideally suited to me. It’s super easy to drop in and out of, welcomes solo players, has actually entertaining combat (a real rarity in MMOs), and above all has no subscription fee. But there’s something missing, something that I don’t think is the game’s fault. It’s me – I just don’t have a network of other people who play the game who can motivate me to play the high-level content and get the most out of the game, and I don’t have the time to build one. I dunno, maybe I’ll pick up the expansions at some point just to play through the content I can do on my own. I sure do like the look of those mounts.

Warcraft III

I reinstalled Warcraft III recently. It’s still awesome. Blizzard have released a patch that makes it play nicely with widescreen monitors and removed the requirement to insert the disc to play, as well as make it possible to switch between the base game and the expansion from the main menu, so now is a great time to revisit this classic. I’ve been stomping my way through the campaign, which is still probably the best example of linear storytelling in a strategy game.

The editor is also the best thing ever. I used it to make a map for Natalie as a birthday treat and rediscovered what an awesome tool it is. It’s super easy just to make something that looks cool, and the scripting system is very accessible and friendly. It’s no wonder that this is the editor that spawned Defense of the Ancients, a custom map that spawned the ultra-successful genre of games like League of Legends and Dota 2 (for which there still isn’t a good name). I was never into DotA, preferring to explore the vast sea of other amazing things people had created using the editor.

Total Warhammer

I’ve been a fan of Creative Assembly’s Total War series ever since its first outing, Shogun: Total War, set in feudal Japan. I’ve also always had a thing for Warhammer. So picking up Total War: Warhammer was a bit of a no-brainer. Steam says I’ve played it for 20 hours, so how come I feel like I’ve hardly touched it?

Well, it’s a bit of a slog. I enjoy it, but it’s incredible how long it takes to make progress in a modern Total War game. And not just because of the long loading times – these games are timesinks by design. That would be okay if I didn’t have a million other games to distract me away from it.

I hope I can get to a point where I feel like I’ve got my money’s worth out of Total Warhammer so I can buy myself the sequel, which by all accounts is a bit more rewarding.

Miniature Matters

In the latter half of the year I discovered (or maybe re-discovered) the joy of painting miniatures. And while I’ve certainly thought a lot about actually playing a miniatures wargame like Games Workshop’s Warhammer: Age of Sigmar or Joseph McCullough’s Frostgrave, I haven’t actually. Yet.

The closest I’ve come is Games Workshop’s fantastic new release Warhammer Underworlds: Shadespire. It has miniatures in it, but it certainly isn’t a wargame. In fact it’s a board game, and a very elegant one at that. For a few weeks after it came out me and a friend from work were playing it multiple times per week, discovering and mastering its systems. No two of our games were alike. I’m not totally sure about the longevity of it, but I have high hopes that I’ll still be playing it years from now, and that it will have evolved into something even more engrossing.

So what did you play in 2017?

The Hobby

Saurus warrior

Reader, I paint lizards.

I paint them at the weekend. I paint them on weekday evenings. Sometimes I even paint them before going to work. Painting lizards is my new, engrossing pastime.

Part of that was a lie: it’s not really a new interest, but a revived one. The world of miniatures has drawn my attention since I was little, but I drifted away from it in my mid-teens. In the last few years I’ve experienced a growing desire to get back in, spurred on by the enthusiastic evangelism of podcasts like Miniatures Monthly and websites like Hipsterhammer.

Feeling inspired, I dug my old Warhammer models out of the eaves in my mum’s house, dusted them off, and surveyed what I found. It was a wasteland. Many were unpainted and others were painted so poorly that it almost seemed cruel not to repaint them. Which was perfect. It means I have a treasure trove of miniatures to practice on before I need to get new models.

Skink skirmisher with blowpipe

Ever since then I’ve been steadily working my way through them, painting or re-painting a few every week. The majority are Lizardmen (now dubbed Seraphon in the Age of Sigmar system that replaced the crotchety Warhammer Fantasy Battle a few years ago), but there are some Eldar, Lord of the Rings minis, and a mixed bag of others. There’s even an unassembled Space Marine tank which I have no recollection of acquiring.

I find painting highly rewarding. It’s as if the activity is opens my head up and fixes all the faulty wires. When I emerge from a session, I feel calm and energised. Since starting I’ve improved measurably and am already a better painter than child-me ever was. It’s been a joy to watch my skills sharpening as I practice and my knowledge growing as I experiment, consume tutorials, get tips and ask questions.

When I need advice, there’s a channel on The Crate and Crowbar’s Discord server which I’ve found to be a great place to hang out and share my progress. The level of skill on display in there can be astonishingly high – a little intimidating, even – but the welcoming attitude of all the patrons means my questions are always answered helpfully and considerately. I also enjoy the painting tutorials on Warhammer TV.

Old-school Bretonnian archers

Things are different now. The hobby itself is in flux, riding the wake of the recent tabletop games renaissance. Games Workshop are smarter about technology and community-building than I remember they used to be, and it seems to be paying off. They’re also experimenting with more board-gamey designs like Shadespire1, while Fantasy Flight are making inroads into the miniatures wargaming space with their own recent titles. Elsewhere on the landscape, neat-looking games like Frostgrave are making me want to grab some dice and dive in.

I also feel like the hobby is becoming a better place for women. I hope I don’t have to eat those words.

Climate change aside, the biggest difference between then and now is that I have an adult’s patience and a full-time employee’s disposable income. This thing demands a lot of time, dedication, and money. I’m glad I have them.

Thanks for reading! Have you had experiences with the hobby? Tell me about them on Twitter or in the comments below.

  1. I’m really enthusiastic about Shadespire and have been playing about 4 games of it per week since it came out. It’s excellent. If I’m lucky I’ll get post about it written sometime. 

Ding! 24

I turned 24 today. This weekend has been a bit busy and overwhelming – but perfect.

On Friday I went to Dundee for some Marioke, which was fantastic. The event itself was amazing, but it was also nice to see some Dundee friends I hadn’t met for a while. Hopefully we’ll have another Marioke in Scotland some time.

Last night we had some friends over for a flat party. My flatmate had decorated the whole place in birthday stuff while I was out during the day (at edindies, in fact). That was a lot of effort I didn’t expect anyone to take, but really appreciated. She also got me a cake!

Natalie made me a birthday card in short game form, which was incredibly sweet. I’m really grateful for her.

Today I had lunch with my mum and I’m meeting my dad for dinner. It’s nice to see them both, as usual.

I’ve been barrelled over by all the folks who have checked in and said happy birthday, over the internet or otherwise. It’s not that there’s been more than usual, it’s that I seem to be paying attention to it more. I think for a number of years I haven’t really noticed birthdays – in fact last year I thought I was turning 22, not 23 – but this year has been different for some reason. Maybe it’s just that some things kind of settled into place this year? Who knows.

Anyway, thankyou for being along for the ride. Here’s to another year of us.

New Page: Podcast Recommendations

I’ve added a new page to the website containing a few podcasts I regularly listen to, or have listened to in the past, that I think are good and want to share with people. At the moment there’s only a handful. I’ll update it with new ones occasionally.

Check it out.

Custom Deleters: A Real Example

I’ve written in the past about standard-library smart pointers and how they can make management of memory allocated from the heap much easier. How useful are they when working with objects allocated from elsewhere, such as objects created by a library we use?

Box2D is a popular 2D rigid-body physics engine in which the b2World is the top-level object that represents the physics ‘world’. Rigid bodies are represented by instances of b2Body and are created like so:

// world is a b2World*
// bodyDef is a b2BodyDef that describes the properties of the new body
b2Body* body = world->CreateBody(&bodyDef);

The b2World owns the b2Body and the memory it is created from, and when the world is destroyed it destroys all the bodies it contains. To remove an individual body and free its memory we call b2World::DestroyBody(b2Body*).

This creates a small challenge for us when we build our game code on top. Let’s say we have an Entity class, which has a b2Body* member.

class Entity {
  b2Body* body;
};

In Entity’s destructor we may want to call DestroyBody, so that when an Entity goes out of scope, it tells the b2World to remove its body from the world:

Entity::~Entity() {
  if (body) body->GetWorld()->DestroyBody(body);
}

These are unique ownership semantics (just about), so we could make body a std::unique_ptr rather than a raw pointer. Let’s try it!

std::unique_ptr<b2Body> bodyPtr = world->CreateBody(&bodyDef);

Unfortunately, this is no good. By default, std::unique_ptr’s destructor calls delete on its internal pointer, which isn’t what we want. The b2World is who really owns the memory, so deleting it out from underneath it would probably cause undefined behaviour down the line, if not immediately. The memory which the b2World allocates bodies etc. from may be a pool block-allocated from the heap. It might not even come from the heap, it may be on the stack. Either way, calling delete on a bit of it would not go down well.

So we need to call b2World::DestroyBody instead of delete.

Custom Deleters

We’re in luck: std::unique_ptr has more than one template parameter.

template<class T, class Deleter = std::default_delete<T>>
class unique_ptr;

The first is the type to which it points, and the second allows the user to define a custom deleter. A custom deleter must be a type with an operator that takes a pointer to T. The custom deleter lets us define what unique_ptr’s destructor does if its internal pointer is non-null.

Here is a pointless example of one that just does the same as std::default_delete<b2Body>:

struct b2BodyDeleter {
  void operator()(b2Body* body) const {
    delete body;
  }
};

using std::unique_ptr<b2Body, b2BodyDeleter> BodyPtr;

BodyPtr = world->CreateBody(&bodyDef);

Obviously this isn’t what we need because we need to call b2World::DestroyBody.

Gotcha

A quick aside, and a warning – you might be wondering why we can’t just use a regular ol’ free function for this. Here’s why.

void b2BodyDeleter(b2Body* body) {
  delete body;
}

using BodyPtr bp = std::unique_ptr<b2Body, b2BodyDeleter>;

BodyPtr doesn’t compile because b2BodyDeleter isn’t a type - it’s a function. Using decltype and an ampersand, we can proceed:

using BodyPtr = std::unique_ptr<int, decltype(&b2BodyDeleter)>;

decltype(&b2BodyDeleter) gives us the type of a pointer to the b2BodyDeleter function (which I’m not going to write, because ugh). However, when we try to instantiate BodyPtr we hit a snag – the class doesn’t have a default constructor anymore, and must be constructed with a pointer to b2BodyDeleter (or any function with a matching signature, actually – so much for safety!).

BodyPtr body; // Doesn't compile!
BodyPtr body(nullptr, &b2BodyDeleter); // Does compile!
BodyPtr body(world->CreateBody(&bodyDef), &b2BodyDeleter); // Does compile!

Unfortunately, BodyPtr is no longer a zero-cost abstraction as it now consists of both a pointer to a b2Body and a function pointer.

static_assert(sizeof(BodyPtr) == sizeof(b2Body*)); // Fails!

If we instead use a functor like our original b2BodyDeleter then the empty base class optimization allows unique_ptr’s size to equal the size of a raw pointer. When using a function pointer our smart pointer becomes stateful, meaning it carries additional stuff along with its underlying raw pointer. This is a bit of a gotcha, and arguably things shouldn’t have to be this way (i.e. functions in C++ should be first-class types), but writing a functor or a lambda to avoid this isn’t too much bother.

b2BodyDeleter

So finally here’s our real b2BodyDeleter:

struct b2BodyDeleter {
  void operator()(b2Body* body) const {
    body->GetWorld()->DestroyBody(body);
  }
};

using BodyPtr = std::unique_ptr<b2Body, b2BodyDeleter>;

static_assert(sizeof(BodyPtr) == sizeof(b2Body*));

BodyPtr body = world->CreateBody(&bodyDef);

We had a choice here. Instead of accessing the b2World using b2Body::GetWorld we could store a World* (or World&) in b2BodyDeleter, setting it in the constructor. That doesn’t really bring any advantages that I can think of, and I can think of two disadvantages. For one, it would force us to specify an extra argument every time we instantiate a BodyPtr. For another, it’d make the deleter stateful and increase its size. No good!

Now we can swap Entity’s raw b2Body pointer for a BodyPtr, and we never have to worry about manually calling b2World::DestroyBody for the Entity’s body again. The body will be removed from the world when the Entity goes out of scope. We get all the other benefits of unique_ptr, too.

There are limitations to doing things this way: an Entity now must go out of scope before the b2World does, otherwise b2Body->GetWorld will return a dangling pointer. We can no longer destroy the b2World before all the Entity instances who are using it unless we call release on each Entity’s BodyPtr before its destructor is called.

This example may seem like a bit of a strawman to you, but in my homebrew game engine switching from using raw b2Body pointers to smart ones has been a pleasant improvement. It fits into my RAII-based approach to just about everything.

Further Reading

Fluent C++ did a series about smart pointers recently, with a few posts dedicated to custom deleters: