How many times have you tried to call a function that alleges to return a time value only to realise you don’t know what units the value is in? Or that takes a time value as a parameter, but doesn’t specify whether the value is expected to be in milliseconds, seconds, or hours?
// What is it? I guess milliseconds? Could be microseconds!intGetGameTime();// deltaTime is probably in seconds?voidTakeStep(constfloatdeltaTime);
Hopefully there are comments somewhere near the declaration of the function that can help straighten things out, but you may not be so lucky. You may have to read through lines and lines of code to see how these functions are used before you understand what units they use.
APIs like this are hard to understand at a glance and can cause a lot of bother. Consider the potential cost of a bug that occurs when an API expects milliseconds, but is passed seconds. Here’s a slide from Bjarne Stroustrup’s CppCon 2017 keynote:
…in which he pointed out that the failure of the Mars Climate Orbiter was due to a software bug that would have been completely avoidable had a particular API encoded the units of measurement it used (in this case, imperial instead of metric).
UPDATE: STL pointed out in a Reddit comment that Stroustrup’s slide is wrong! But the sentiment is correct, anyway.
And so we have strongly-typed time values like C#’s System.TimeSpan provides. In the world of C++, many libraries and frameworks have their own time type. For example, SFML has sf::Time and sf::Clock. sf::Clock::getElapsedTime returns a sf::Time, which can be compared to, added to and subtracted from other instances of sf::Time. Then it can provide its value as seconds (float), milliseconds (int32) or microseconds (int64).
Until C++11, the language didn’t have a standard way to represent times. Then chrono was added to the standard library.
chrono exists at a higher level of abstraction than sf::Time/sf::Clock. The library consists of three concepts: clocks, time points and durations.
Clocks
Clocks are time providers, consisting of a starting point (“epoch”) and a tick rate. A clock has a now() member function that returns how much time has passed since the starting point. The standard library provides three clocks for your basic out-the-box time-getting functionality, the main one being system_clock. If you need to, you can create your own class or bundle that satisfies the Clock concept.
Time Points
time_point represents how much time has passed since the start of the clock it is defined in terms of. For example, a time_point<system_clock> would record how long since the system_clock started. You’d initialise it like so:
time_point<system_clock>t=system_clock::now();
You won’t be able to initialise it with the now() of a different clock because its time_point type isn’t convertible to that of the original clock.
(Note: because high_resolution_clock may be an alias to system_clock, it may be possible to convert between their time_point types. Don’t count on it, because your code may not be portable if you do.)
At runtime a time_point is a simple arithmetic type like an int or a float, and it can be added to and subtracted from other time_point instances, as long as they all come from the same clock.
Durations
A duration is, like a time_point, just a puffed-up arithmetic type. Unlike time_point, it’s not coupled to a specific clock type at compile time.
Along with its runtime value the duration contains a compile-time ratio specifying the units of time that value represents. A ratio of 1:1000 means milliseconds, a ratio of 1:1,000,000 means microseconds. The default ratio is 1:1 – that is, the default units for durations is seconds. The standard library defines some ratios for us in the <ratio>header.
You declare and set durations like so:
(duration::count returns the value of the underlying arithmetic type.)
// integral representation of 10 millisecondsstd::chrono::duration<int,std::milli>d(10);// d.count() == 10d=std::chrono::milliseconds(5);// d.count() == 5d=std::chrono::seconds(10);// d.count() == 10,000
Casting from seconds to milliseconds can happen implicitly, but in other cases it is necessary to use duration_cast.
User-defined Literals
These are wonderful little things of which chrono provides a handful. The s literal, for example, turns its operand into a duration<unsigned long long> or duration<long double>.
usingnamespacestd::chrono_literals;// integral rep of 1 secondstd::chrono::duration<int>t1=1s;// floating-point rep of 1 secondstd::chrono::duration<float>t2=1s;// floating-point rep of a fraction of a secondstd::chrono::duration<float>t2=1ms;
Conclusion
Finally, here is the API from the beginning of this article, rewritten to use chrono:
For one thing, I settled into my job. I have a long way to go and so much more to learn, but I feel like I’m in the swing of things now. I still find it amazing that people are willing to pay me to write code for games, surrounded by awesome people in a lovely office. I’m very excited about what I’ll get to work on in 2018.
In February I visited San Francisco to attend Game Developers Conference (GDC), an amazing opportunity to rub shoulders with people from all across the industry. I wouldn’t have gone if Connor hadn’t invited me along with him, so I’m very thankful to him for that. You can read all about my GDC experience here and my time in San Francisco here.
In the summer I took a few days off work to attend two short courses at Edinburgh University. The first was “Scottish Politics in Context”, which was a whirlwind tour of Scottish politics from the early modern period to the recent upheavals. The second was “Introduction to Solar Power”, a one-day course that explained the many ways we can use solar power, from heating water to the various kinds of photovoltaic cells. We also got to make our own PV cells using blackberry juice as a dye, which I didn’t know was even possible. I’d recommend both courses. I’m definitely going to do some more short courses this year coming.
In October me and Natalie went on holiday to the South of France, my first actual holiday out of the country for years. It was excellent.
My Mum moved house, so I had to say goodbye to the house I grew up in. I felt sad, but the process made me realise that I’ve well and truly moved out – her house hadn’t felt like my home for several years. Her new place is great, anyway, so it’s all worthwhile. (It also made me think about the Edinburgh housing market (Holy shit! (What the fuck?)))
In the latter half of the year I reached out and became an attendee of C++ Edinburgh, the local C++ usergroup. Everyone who attends is nice, works on cool stuff and has a lot of knowledge to share. In December I gave a short presentation at the meetup about my game engine, Quiver, which was quite good fun. I hope I can fit in some other meetups in 2018.
Speaking of Quiver, that project chugged along a fair bit, although I struggled to commit enough time to it. I finally came up with a good name, so it’s no longer just “the Quarrel engine”, and I made it open-source. You can check it out on GitHub. I look forward to continuing to tinker with it next year – there’s a lot of work to do! Maybe I’ll actually make Quarrel into a playable game! (Ha ha!)
In short, my 2017 was a blast. Just about everything that could have gone well went well. I have a lot to be thankful for. I live in a lovely flat with a lovely flatmate, I have excellent friends and a wonderful girlfriend, I love my job and it seems to like me. I know that 2018’s going to be a tough one (both professionally and personally), so I’m glad I get to begin it on the best possible footing.
Thanks for reading. I hope your 2018 is productive and peaceful.
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.
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.
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.
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.
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.
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. ↩
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.