Hey, everyone. Spryke and I are alive and well, just working quietly as usual. Though it's been a long time since I posted an update, so I've popped my head up for one now.
I've tightened my focus this year and have focused on consolidating, streamlining and completing the various modules of Spryke's engine. Some of the previously-built parts were made for certain deadlines or milestones, such as a demo, a PAX show, or the kickstarter. As such, certain pieces of the engine were rushed, left unfinished, or were built to work in a standalone level or two but not yet properly integrated into the whole.
So I've been hard at work getting the Spryke engine shipshape and ready for the bigtime. I've simplified my internal level editor, consolidated the way levels are loaded and constructed, expanded the capability of my camera system to handle story sequences, vastly accelerated my graphics workflow, and other things like that. From now on, I'm also applying this ship-shape philosophy to anything new I add to the game. Everything I build from now on must be well integrated and must not create roadblocks or speedbumps down the line.
With that in mind, I've just finished a floating particle system for Spryke, which has been on my todo list for years. It's probably one of the most complicated things I've tackled thus far, as I had three vital yet conflicting criteria that needed to be kept in balance. Firstly, it needed to produce great-looking and believable particle effects of just about any type. Secondly, it needed to be super easy for me to use, so that once it's working I'll be able to add any particle effects I want without much time or effort. Thirdly, it had to be well-optimised for decent performance.
It was going to be complicated, and I knew that once it was done, I didn't want to ever have to deal with its intricate inner workings again. So it needed to be able to handle any particle type I could feasibly throw at it between now and Spryke's completion: dust, rain, leaves, snow, Matrix-like cyberdelic effects...
Particles had to be able to float gracefully, flutter unpredictably, or vibrate frenetically. Some must twirl in circles while others must create splashes on platforms. They had to be able to dynamically move if caught by the wind, Spryke whooshing past them, or a nearby explosion.
What's more, they must figure out a lot of stuff on their own. If they are twirling objects, they should twirl more often if there's a brisk wind. If they get knocked about by Spryke, they should seamlessly resume their original motion after a while. They must contribute visual depth to the game by spawning at various distances to the player, with those in the background being smaller, blurrier, fainter and more numerous. They need randomised variety in their movements - those which spin or move quickly must be redrawn more frequently, while those that are small, slow and/or distant should be recalculated only rarely, to optimise CPU performance.
I need to be able to control how and if their colors get randomised, so I can create just green leaves in Photoshop but still get brown, yellow, orange, and red ones for an autumn effect in-game. And if a level has a dark cave on one side and a bright light source on the other, I want a way for the particles' color and opacity to adjust accordingly. Finally, with so many parameters available to me, I needed to be able to tweak them rapidly and without confusion.
So the list of features I wanted was substantial, and I decided on an approach I hadn't fully utilised before: planning out the entire engine on paper first. For the most part, this worked excellently. While I filled up close to an entire notebook of diagrams and equations, I discovered and fixed many issues while still at the paper stage, and some 80% of the features I planned worked immediately as intended when I coded them into Fusion. I still see myself as essentially a non-programmer, so that was a delight to experience.
The final result is probably even better than I'd hoped. It does all the above-mentioned features and more, and the particles look really nice, to my eye. It won't be long before the engine's 200+ variables and numerous equations become totally opaque to me, but that shouldn't matter because the 'front end' that I'll be using is very straightforward. I just need to enter some simple parameters in an INI file, hit a single key on my macro keyboard, and see the changes reflected immediately in-game. I configured most of the effects in the GIF at the top in a matter of minutes.
Performance is good too. 100 leaves on-screen, each wobbling to its own rhythm, twirling, pivoting, shrinking in and out, colliding with Spryke and more, consume just 45 microseconds per frame. Simpler particles like raindrops consume far less. On just about any PC with a graphics card, the performance will be negligible even at max settings.
One more piece of the puzzle done.
If you've been following Spryke for any length of time, you know that I'm terrible at updates. This year I've been all but invisible. Partly by accident, partly by design.
As it does to all of us, life's been throwing more demands of my attention than I am equipped to properly handle. There was a health scare a while back, with endless scans and doctor's appointments (everything's fine now). There was the World Cup month (I'm a life-long World Cup addict). I also got sidetracked for a few months with a side project which, while ultimately valuable for my Spryke work, took far too long.
And then there's working in a home office with two young children, which is less a work/life balance than a work/life Magimix blend. It's a sacred blessing to see so much of my daughters in the most adorable and excitable stages of their lives. It's also a massive challenge to someone who relies on solitude and time spent in the zone to get his work done.
One thing has never changed though, and never will, and that's my commitment to Spryke's high quality. As I always say, there's no point releasing just another good indie game, because it'll immediately drown in the sea of all the other good indie games, and the whole thing will have been a waste of time, for both me and the players (the last thing you need is another merely good game - your Steam backlog is overflowing with them as it is!) Spryke needs to be one of those games that creates lifelong memories in its players.
As work on Spryke entered its fifth year this year, a few things came into focus for me. Firstly, that making a few levels for a cool demo is a world apart from making a complete game. It's not just that a full game contains so much more content. It's also that the very structure and logistics of the two are fundamentally different.
A 5-level demo can be made of 5 separate parts, stuck together with Blu-Tak and goodwill. A full game needs to be able to save, load, and reload dozens of levels in a row, without a hitch, without ever clogging up memory, yet without unnecessary load times. While elements of a 5-level demo can be hard-coded if need be, the sheer amount of work involved in designing, testing, and tweaking the dozens of levels in a full game mean that the entire workflow must be as streamlined and automated as possible, else you'll drown in a deluge of exponentially-multiplying mundane tasks.
I've been pretty careful with how I've developed Spryke, spending a lot of time on making modular, well-commented, code in a centralised engine, with a powerful bespoke debugger. And I've carefully moulded my graphics workflow for maximum reusability and non-destructibility, making judicious use of various Photoshop features like artboards, generator, custom shapes, custom textures, layer styles, actions, and more. Here's a sample:
I've done my best to streamline my physical workflow for maximum productivity too. I might actually be the most hotkey-laden computer user in the world. I've set up dozens of hotkeys and macros for almost every task I do with any regularity in Photoshop or Fusion, and the most important ones are all a split-second away, either on my 15-button mouse, my 10-button Wacom setup, my 22-key Ducky keypad, or the 18 macro keys on my keyboard. All this may seem like overkill or OCD, but it's not. I've learnt over the years that entering a state of flow is essential to my work; my rapid and near-frictionless workflow routinely gets me there quicker and more often.
So I've put effort into making my code and my workflows robust, but I've also taken various smoke-and-mirror shortcuts along the way, especially when it was time to make a PAX build or a trailer video. This came into sharp focus for me when I was thinking about making a build for this year's PAX.
I've been working on some major improvements to Spryke this year. Among other things, I've been addressing what I see as the last major weaknesses of the game: blocky foreground elements and weak narrative. Both of these are huge areas, and I've made considerable progress in each. But neither are game-ready yet, so making a PAX build would entail undoing or hiding much of what I've done this year, to cobble together a cohesive and workable build. This would be time-consuming, exhausting, risky, and kind of pointless.
So I've decided to skip PAX this year, as well as all other marketing-related activities. I've effectively removed myself from all social media (a productivity boon and happiness enhancer if ever there was one), stopped following the news, and have tried to filter out as much other noise from my day as I can. What I need to focus on is working on the game.
Really, this is all in keeping with the general philosophy I've taken since the beginning. It's very simple, even naive. But it's served me well so far, and I don't know of any approach that's as likely to succeed. It's illustrated perfectly in a scene from the beautiful film Gattaca.
Two brothers compete to see who can swim the furthest out to sea. Anton has a more athletic build and superior lab-enhanced genes, so he can't understand how his brother Vincent always beats him. Exasperated, he finally asks Vincent how he does it. Vincent's secret is dead simple: he never saves anything for the swim back.
When I dived into the deep end of game development almost 5 years ago, many people expressed admiration, and even sometimes good-natured envy, for the courage it took to follow my dream. Though as each year passes, they're probably more and more glad that it was me who took the plunge and not them!
There's an insanity to Vincent's approach, but also an incredible freedom. The reason Vincent succeeds despite the odds being stacked against him is not because of anything that he does, but because of all the things that he doesn't do. Unlike Anton, he doesn't look over his shoulder; he doesn't continually update a mental map of his distance traveled in the back of his mind; he doesn't keep freaking himself out by wondering whether he's going to make it or not. He's free to focus on just one thing - going forward - and doesn't have to waste resources on anything else. Vincent's approach is brave, and reckless, but it's also incredibly efficient.
Had I not dived in the deep end with this game, I would have quit ten times already: when the going got tough; when I got tired; when other opportunities caught my eye. Or, I would have seen the game through, but to a mediocre standard, chalking it up as a mere learning experience or relegating it to a weekend hobbyist project while I worked a day job. Thousands of other indie games have ended up exactly like that - unfinished, shelved, simplified or downgraded. At the very least, my advantage is that I'm still here, and still plugging away, albeit sometimes slower than I'd wish.
So yes, here I am. Spryke's still alive, and she's doing great. The game's going to be finished - eventually - and it's going to have an insane amount of love and care put into it, so that it can leave lifelong memories for as many players as possible. But you won't see it at PAX this year, and you probably won't hear from me much at all, until it's closer to completion, because until then I need to focus. Hopefully you'll thank me when you get to play the finished product. But know that Spryke and I are still here, still swimming....
We took Spryke to PAXaus 2017 a few weeks ago, and it went great. Lots of great feedback, lots of people loved the game, and unlike last year there were few criticisms or suggestions for improvement, which suggests that I'm getting things right.
We had a speedrunning contest this time, which turned out to be a fantastic idea. It got people really engaged, showed off one of the more addictive and intensely fun sides of Spryke's gameplay, and we even got to see a little speedrunning community form organically, which was really wonderful. I enjoyed it so much I made a short video about the weekend.
The Speedrun Demo build we had at PAX is now available to download. It contains 5 levels, with a focus on speed-running. It still presents Spryke in an early, in-progress state. Everything is always improving - but I hope you'll agree that it's coming along really well!
You can also watch me doing a speedrun myself, for a total time of 48:30. I could probably shave off enough to get up to 47:59 if I really tried....though I'd have no chance at getting into the top 3 scores at PAX, which were all around 44-45! Seeing people out-perform you in your own game is a surprisingly delightful feeling, actually!
I'm cramming as much eye candy and mechanical nuance into Spryke as I can, to make it as impressive and satisfying to play as it can possibly be. That means that I push the Clickteam Fusion 2.5 engine pretty hard. Overall, the old girl copes pretty well with what I throw at her, but I'm still taking optimising very seriously, to make sure that Spryke runs smoothly on as many PC setups as possible.
A while ago, I wrote a post describing some of my optimisation efforts. A very helpful commenter pointed out that I really shouldn't be blindly optimising everything I can, but should be profiling the code to find the bottlenecks, and then devote my energy optimising those.
It was very good advice. The trouble is that Fusion doesn't have any kind of native profiler built-in. And cobbling together one's own was more or less impossible because Fusion didn't provide the means to measure code time finely enough.
Well, it's a few weeks later, and I'm now pleased to say that I've gotten around these problems, and have built Fusion's first ever code profiler that can accurately measure code performance in microseconds! I'm sure it's not as full-featured as the profilers that come with 'real' programming environments like Visual Studio, and it only measures the performance of your Fusion code (not, for example, the DirectX & GPU side of things). But it's still pretty damn useful, if I do say so myself. It's called volPROFILER, and the Clickteam developers among you can get it on the Clickstore for just $2.99.
I recently started putting together a large article about various good practices Clickteam Fusion 2.5 developers should be aware of. A 'Top 30 tips' type of thing, aimed primarily at beginner and intermediate users. One of those tips was: Learn how Fusion scopes.
But as soon as I waded into this topic, it quickly became apparent that it required its own blog post. Its own very long blog post. Well, here's that very long blog post. (Stay tuned for the article with the other 29 or so tips - that's probably coming in the next weeks).
If you're not familiar with the word "scope" in the context of Clickteam Fusion, don't worry - you're almost certainly familiar with the concept. One of the great things about Fusion is that it frequently scopes things automatically, in a way that is intuitive to the user....most of the time.
The basics of scoping in Fusion are very simple and easy to grasp. But as will soon become apparent, it becomes pretty byzantine the deeper you dig, with all sorts of unintuitive rules and weird exceptions that will sooner or later generate frustrating bugs in your projects, unless you familiarise yourself with their hidden idiosyncracies. But fear not. At the end of this post, I summarise it all into some simple guidelines.
Scoping in Clickteam Fusion 2.5 - The Basics
OK, let's dive in. In this first example, the simple action set angle of pear to 45 results in all pears being tilted. Naturally.
However, in the next example, the exact same action has only managed to rotate two pears. That's because the preceding condition (Y position of pear > 100) has scoped those two pears. In other words, Fusion has singled out those pears which have a Y value greater than 100px (ie. are visually lower down, and closer to the bottom of the screen, than y100). Thus, the subsequent action, because it takes place in the same event, now only concerns itself with those pears. I'm probably not telling you anything new here.
In the next example, notice that this scoping is cumulative. Both conditions have combined to scope just one pear (the only pear that happens to be both lower than 100px on the Y axis and further right than 100px on the X axis). And both actions have honoured that scope (only the scoped pear was tilted, and only the scoped pear was alpha-faded).
Scope on the left
So far so good, right? In most situations, scoping is as straight-forward as this. However, there are certain situations where Fusion's idiosyncrasies can make scoping less intuitive. One case is when two objects are compared. Look at the following two examples:
Mathematically, both above events appear to be identical. In each case we're talking about pears which are lower than apples. Yet only the pears in the first example were successfully scoped (the second example applied the tilting indiscriminately to all pears).
This is because when you compare two objects in a condition, Fusion generally only scopes the leftmost object. If this seems weird, then it may help to remember that a condition in Fusion is essentially an IF statement.
Let's replace the apple with the number 100 again, and look at these two events again:
The first statement, essentially, reads as follows:
If the Y position of a pear is greater than 100, then rotate the pear.
The second statement reads:
If 100 is less than the Y position of a pear, then rotate the pear.
While that second statement isn't exactly broken, it's kind of....odd, right? The focus of the sentence seems now to be the number 100, so it doesn't feel entirely right to assume that we're talking about any specific pears. It's a bit like, instead of saying.....
Fred went to the the third drawer, and got himself a spoon
.....I instead said.....
The drawer was the third from the top, and Fred got himself a spoon
There's something a bit off about the second statement, right? You can still infer that Fred's spoon came from the same drawer that was the third from the top, but it's not 100% clear. And since computers have a much lower tolerance for ambiguity than humans do, you can imagine that a computer would struggle to make that inference.
Hopefully this will help you get an intuitive sense of why Fusion only scopes objects from the left. Regardless, as long as you remain aware of this idiosyncrasy, it's not likely to cause you many problems.
Scoping and overlap
There are some exceptions to the 'scope on the left' rule. One such exception occurs, thankfully, when we test for overlap.
As the following example shows, when you test for overlapping between two objects, both objects are scoped, regardless whether they're on the left or right. Just as well - testing for overlaps would be near-pointless if it didn't result in both specific objects being scoped! The same is true when testing for collision, by the way.
Scoping and newly created objects
Creating new objects also affects scoping. When a new object is created, all subsequent actions in that event will be scoped to the newly created object(s).
Notice in the next example how only the 2 newly created pears are tilted and faded, while the original 5 pears are untouched.
Now notice below how the same event - but with the actions reordered - achieves a very different result. Because the fading and tilting actions appear at the beginning, before anything is scoped, they apply to all pears. So all 5 original pears are modified. The 2 new ones are not modified because they only get created after the fading and tilting actions have taken place:
So far so good. But now let's shuffle these actions around a little:
Hmmm. Shouldn't one of those new pears (the one that was created earlier, at x50 y100) now be faded? Perhaps the second newly created pear is stuffing things up somehow? Let's remove it:
Nope. We get essentially the same result. Both the fading and the tilting get applied to all previously existing pears, and not to the new pear (even though the fading is supposedly applied after it's created).
Perhaps newly created objects only affect scope when they are the topmost action? Let's try something:
Nope. In the above example (exactly the same as the preceding one, except that the tilting action is applied to apples instead of pears) the create new pear action does indeed affect scope. Only the newly created pear is faded. This all seems pretty inconsistent and weird. Who knows how exactly it works under the hood? But I can start to cobble together a hypothesis:
Perhaps, the first time an object is encountered in an action, its scoping is cemented for the rest of the event (including any scoping inherited from conditions, naturally).
The above hypothesis appears to agree with everything we've seen so far. It explains that when a pear is first encountered in Example newlyCreated #5 it cements the scope to that 1 pear (only that pear is faded).
And it explains that since the first pear action encountered in Example newlyCreated #4 applies to all 5 pre-existing pears, the scoping is cemented to those 5 pears (which is why fading is applied later to those 5, but not to the 6th that was created a moment after the scoping took place).
It also explains the next example. Because the first action applies to the 5 pre-existing pears, the third action does too. Thus, the newly created pear is neither destroyed nor faded. So far this hypothesis is looking good.
However, before I get too excited, I need to come clean and admit that, if you hadn't noticed already, the hypothesis doesn't actually fit with #1 newlycreated, where not 1 but 2 actions affect scope (both created pears are successfully faded and tilted).
My hypothesis also doesn't explain this:
The above example is identical to the previous one, but for the extra condition (Y position of pear >100). Yet while the newly created pear was spared in the previous example, it's destroyed in this one. Why? The first action here is clearly honouring the scope from the condition, since it destroys those pears which are lower than y=100 while leaving the top 3 intact.
So why does it also destroy the newly created pear? The newly created pear was neither part of the original scope (it didn't even yet exist when the scope was determined), nor does it qualify for that scope once it's created (since its Y position is less than 100).
Sadly, the best conclusion that I'm able to muster is that Clickteam Fusion is kind of like the English language: dazzling in its overall utilitarian simplicity, yet knotted with arcane rules below the surface that present seemingly even more exceptions than there are rules. People might think they know exactly how it works, but no fully does. Yet somehow we all get by anyway.
To try and summarise this section then: Creating objects at the beginning of an event automatically scopes those objects. This is highly useful. There may also be times when you want to create an object lower down in the action list - but do so at your peril, as it may produce unforseen consequences.
Scoping and fastloops
Scoping can also be unintuitive when fastloops are involved. In the next example, the insertion of the fastloop has broken the scoping of the pears, resulting in all the pears being rotated, rather than just the ones that are Y>100.
In a way, this makes sense, since the fastloop is wedged between the pear condition and the pear action. It shoots us out of event #1 and into event #2, thereby disrupting the hermetic nature of the event. We can perhaps forgive it for forgetting event #1's initial scoping once it eventually returns from the fastloop in #2.
So what happens when we move the Start loop "fade apple" 1 times to the end of the action list?
Well, nothing. It's no longer wedged in between the pear condition and the pear action, and there doesn't seem to be any intuitive reason why the fastloop should continue to break the pear's scope. Yet it does. It would seem that the mere presence of a fastloop call anywhere in event #1 breaks the scoping of the pears. They are all tilted, rather than just the Y>100 ones.
It gets weirder though.
This time, look what happens if we modify the fastloop to include a pear in it:
The fastloop successfully fades all the pears, but when it comes back to event #1, not only does it still not honour the Y>100 condition, but now it brings with it its own seemingly senseless scoping that no one asked for (the lower-right pear). In my view, this behaviour is no longer just a quirk but a definite flaw.
You might wonder what, if anything, was so special about that lower-right pear that gave it priveleged scoped status. The answer is that it happened to be the last pear that I created (in the frame editor). So at least it's a predictable flaw. But it does hint at some potentially useful functionality. Observe the next example:
As before, the fastloop causes Fusion to dishonour the Y>100 scoping. And as before, the fastloop imprints its own scoping on the event. But this time, that scoping has a somewhat satisfying logic to it: we specially created two pears in our fastloop, and upon returning to event #1, it is precisely those two pears that are scoped. I can imagine some good uses for that.
But don't get too excited...
This time, all we've done is add some extra actions to the fastloop, and suddenly our two newly created pears are no longer scoped. We are back to just the most recently created pear being scoped. I don't know about you, but this sort of behaviour seems far too flaky and unpredictable for me to ever rely on it. My advice is to exercise caution and avoid mixing fastloops and scoping. If in doubt, call the fastloop in a separate event.
Scoping and forEach loops
ForEach loops have their own scoping idiosyncrasies that are often different from those of fastloops. For one thing, a forEach loop's mere presence doesn't break scope (or at least, not in the same way that a fastloop's does).
Below is a recreation of Example fastloops #1 from above, but using a forEach loop instead of a fastloop. Notice how the apple forEach loop doesn't interfere with the successful pear scoping.
Furthermore, watch what happens when we call a forEach loop on pears instead of apples, below. The scoping from event #1 is actually remembered in event #2 (only the Y>100 pears are faded)! This gives you the ability to call a forEach loop on only a specific subset of objects, which is useful in various situations (eg. run a forEach loop that makes enemies shoot at the player...but only those which are close to the player).
Just to be clear, this is an ability that is unique to forEach loops. The exact same scenario using a fastloop causes scoping to be broken (all pears are faded, plus only the most recently created one is tilted):
So far, forEach loops seem like the good guys. Their mere presence doesn't seem to break scoping, and they obediently inherit scoping from their parent conditions. And of course, scoping is one of the main purposes of a forEach loop in the first place, as the very name "for each" implies: the forEach loop iterates through each instance of an object, one at a time, scoping each in turn as it progresses. Each time, all actions inside the forEach loop will be performed in the context of one specific, scoped object.
But alas, forEach loops also carry their own set of weird scoping problems.
In the next example, we create two new pears next to the apples. Then, we ask for the pears to be tilted. Intuitively, we might expect one of two scenarios: (a) that scoping will carry over from the forEach loop and only the 2 new pears will be tilted, or (b) that it won't, and all 7 pears will be tilted. We probably wouldn't expect the actual outcome, where all but the new pears were tilted. Strangely, event #1 behaves as if the order of its actions were reversed.
Incidentally, replacing the forEach loops with a fastloop, in an otherwise identical scenario, produces the exact opposite result. Now, only the new pears are tilted.
While a fastloop that returns to its parent event can bring with it new scoping, a forEach loop seems to arrive late for the party; it's as if any new objects it created don't quite make it back to the parent event. This can be seen explicitly in the next example:
In the above example, we start off with 5 pears (created in the Frame Editor). We then shoot off via a forEach loop to create 5 more. When that's done, we come back, and ask Fusion to tell us how many pears there are in total. Fusion declares confidently that there are 5, when we can see with our own eyes that there are 10.
We already know by now that creating new objects can do some wacky things to scoping. So let's see what happens if we try a similar scenario to the one above, but without the create new object bit:
Even now we have the same problem. The number 1 was added to Global Value A 5 times (since there are 5 pears, our forEach loop looped 5 times). Yet somehow, when we display this value afterwards, it is as if time has rewinded, and it's still 0.
Could it be that forEach loops are simply executed last, after all other actions? Even though the forEach loop appears to be the topmost action, is it secretly being bumped down in the queue? Upon further scrutiny, it appears that this may be what is happening. Have a look at this:
The fact that the pears in the example above end up tilted proves that the forEach loop did indeed run. Yet it was only allowed to run if at least one of the pears was ripe (ie. we changed its alterable value "ripe" from 0 to 1). But the pears only became ripe after the forEach loop had finished!
There are only two possible explanations for this that I can see. Either forEach loops have discovered the secret of time travel, or they are always executed last, no matter where they appear in the action list. The former explanation is the more compelling one. But we must keep an open mind and at least consider the possibility that Fusion routinely delays forEach loops until all other actions are completed.
Here's another example. Notice that we create a pear at the precise location of the apple. Yet when all is said and done, the pear ends up nowhere near the apple. That's because we moved the apple (but before the pear was supposed to have been created). Again, it seems as if Fusion has, without telling us, shuffled the forEach loop to the bottom of the action queue.
However, things are not this clear-cut (which by now probably shouldn't be surprising). This next example proves that although forEach loops often seem to be executed last, they aren't always executed last:
Had the forEach loop run in the above example, the application would have immediately ended. But as you can see, the application is alive and well. We can deduce from this that the order of events played out exactly as we would expect from looking at the events (for once).
First, Fusion ran a loop for each pear - but since there were no pears yet, it ran the forEach loop zero times, so it never had to see the end the application action. We can assume that only afterwards was a pear created (since the existence of a pear should have caused the forEach loop to execute). In this case at least, the forEach loop seems to have executed at the start of the action list, not at the end.
These last few examples weren't technically about scoping, but I think these idiosyncrasies are useful to know about, since they can, and do, affect scoping in certain circumstances (as we saw in Example forEach #4, for instance).
OK, so we've investigated the different ways in which Fusion automatically scopes objects (or doesn't). If you pay attention to the basic principles and steer away from the problem areas we identified, you'll find Fusion's automatic scoping to be both useful and easy to work with.
But there will still be times when Fusion won't automatically do the scoping that you need, and will require a helping hand from you. This will be the case when you need scoping to persist over multiple events (Fusion's autoscoping is predominantly limited to singular events).
Below, we have 4 pears. On top of each pear, we've also placed a worm:
Now, let's say that we want to rotate those pears whenever we press spacebar; we'll do it via a forEach loop. When we rotate the pears, the worms are left behind:
We can tell Fusion to rotate the worms the same amount as the pears, but that won't work properly. Each time we tell Fusion to rotate a pear, it does them one by one, because of the forEach loop. But when we tell it to rotate a worm, we haven't specified which worm we're talking about (ie. we haven't scoped the worms), so it rotates all of them. As a result, the worms are all rotated together, 4 times, and they end up facing the same way:
So we need a way to tell Fusion which worm we're talking about. In particular, we need some way to 'marry' each pear/worm pair. There are a number of ways to do this, though they all work on the same principle. Some people use spread values, for instance. My preferred method is to used fixed values, like so:
A fixed value is a unique number that Fusion automatically assigns to every object in the scene. It typically looks something like this: 374928. But the beauty of this method is that you don't need to actually know , or care, what the fixed value is. The point is that every object in your game already has its own unique little identification number, without you needing to do anything, which makes these fixed values perfect for manual scoping. OK, let's break down this example step by step:
EVENT 1: We launch a forEach loop for the pears. This will only run once (at start of frame).
EVENT 2: This is the forEach loop. In the first action, we create a worm at the pear. Fusion knows exactly which pear we're talking about, because the forEach loop is carefully going through each pear one by one, scoping an individual pear each time. At this point, we are in a unique position: Fusion has scoped a single instance of a pear (because of the forEach loop) and also a single instance of a worm (the one that was just created). But not just any pear and worm, of course: this pear and worm are located at the same physical X+Y location.
So while Fusion has both these objects scoped, we must take advantage of the situation and quickly find a way to slap some sort of permanent label on our duo, forever 'marrying' this particular worm with this particular pear. We do this in the second action, by assigning an alterable value (that I've chosen to call "ID") to the worm, and giving it the same value as the fixed value of the pear.
As discussed earlier, each object has a totally unique fixed value that can be used to tell it apart from all other objects. So by copying the pear's fixed value to the worm's "ID" (alterable value), we've effectively formed a link between them that we'll be able to use at any time in the future to locate the happy couple.
EVENT 4: Whenever spacebar is pressed, launch another forEach loop that will rotate the pears.
EVENT 5: The first condition (the forEach loop one) scopes the pear. Fusion now has one single pear in mind. The second condition scopes the worm, because it forces Fusion to find only the worm that has an "ID" (alterable value) that exactly matches the fixed value of a pear (which pear? the pear that was scoped in the preceding condition, of course!)
By the time we get to the actions, Fusion has successfully scoped one pear/worm couple. So when we ask Fusion to rotate the pear, it rotates just one. Then when we ask it to rotate a worm by the same amount, it knows to only rotate the worm that's 'married' to the pear.
This technique doesn't just apply to pairs (nor just to pears, har har). It can be used to combine and scope any number of items. Here, we add a cowboy hat to the mix:
Scoping - Rules of Thumb
Well, if you got through all of the above, then you know that Fusion's autoscoping can become one crazy rabbit hole. But that doesn't mean scoping needs to be intimidating or confusing. By simply remembering a few basic points, you'll be able to steer clear of 99% of Fusion autoscoping's weirdness, and reap the benefits of its intuitive, pleasant side. Here are the key points to be mindful of (as I see them, at least):
That's (not) all, folks!
This is the first such Clickteam Fusion article that I've posted, and I've no idea how many people will read it, and whether they'll find it useful. So please let me know what you thought. Tell me what you liked, and what you didn't like, either in the comments below, or at the Clickteam Fusion forums.
Stay tuned for the larger article that this post was originally meant to belong to. To be notified when new posts arrive, sign up to my newsletter.
It's been a long while since I've written any updates on Spryke, so I figured I'd better hop to it. I've spent the past couple of months overhauling Spryke's code to make it more optimised. I'm doing this for a few reasons. Firstly, the performance was starting to creep into an area where even on my relatively high-end gaming PC it would sometimes dip into subpar territory (ie. less than 60 frames per second). I always told myself that this would be the point where I'd stop and start looking closer at how I'm doing things. Spryke will never be the sort of game that runs blisteringly fast on a tinny laptop with integrated graphics, but I'd certainly like it to run well on anything even resembling a gaming PC.
Secondly, I'm determined to make Spryke feel like more of a game this year. Not just an assemblage of levels, but an actual game, with a solid skeleton and all the necessary stuff, like proper loading screens, graphical options, robust camera, and so on. Part of that also means cleaning up the code and getting it into something resembling a publishable state.
Also, some of the really core code (eg. Spryke's unique movement engine) was 3 years old, written when I was a beginner with Fusion. This code was visibly inefficient, and all but completely incomprehensible to present-day me. I was getting tired of breaking things when I added a new feature and not even being able to tell how it was broken.
Redoing all that stuff was a real drag. Merely figuring out how it worked was time-consuming, as has been untangling it and reshaping it into something more modular, optimised and manageable. I've refreshed a lot of the code already, but I'm still knee-deep in the process. And, of course, I've broken lots of little things along the way, so after all this my next step will be to repair all of the 'optimisations' ;)
To be honest, I'm getting pretty sick of this process, but it's important, and I know I'll be very grateful to myself when I'm done. Up until now, I'd taken to heart that silly adage about premature optimisation being the root of all evil. I always knew I'd eventually do a wave of optimisation, so I was never too fussy about how I made my code. I was never sloppy, but tried not to be too fastidious either. I'm now questioning the wisdom of that. Though I know so much more now than I did when I started, so it's probably best that I left the fastidious stuff till now. However, cleaning up after old code is proving so time-consuming that I'm determined to make all my code from now on as optimised as possible. I've done a lot of benchmark testing to see where I can most beneficially streamline the code, and I'm developing a lot of good habits that I'm going to keep as I go forward.
Here's a little sample of the sort of optimisation work I've been doing:
Spryke generates animated smoke clouds out of her side vent as she moves. These are hand-drawn and animated in Toon Boom Harmony, but to make them look extra believable and fun, they are also generated and manipulated programmatically. For instance, they come out semi-randomly, at slightly different speeds and sizes, and each smoke cloud randomly chooses from 7 separate handmade animations. They're also more numerous when Spryke's jumping (since that takes more energy), and their angle naturally adapts to the arc of Spryke's jump as they come out of her.
Previously, I had 4 separate events for 4 different scenarios (jumping left, jumping right, ground/ceiling left, ground/ceiling right - all shown in the image), with each event taking care of that scenario's particular requirements for smoke angle, direction, and probability, as well as positioning the smoke just right so that it comes out of her vent. So one event basically said if Spryke's jumping left, generate some smoke and do this, this and this to it, while another said if Spryke's on the ground moving right, generate some smoke and do that, that, and that to it...and so on.
But with some careful maths using some pre-existing variables, I was able to consolidate all 4 events into a single event. The code no longer needs to check whether Spryke's moving right or left, airborne or not. The unified event simply runs in all of those circumstances, and adjusts the smoke's position, angle, direction, and probability as needed on the fly.
For example, this equation takes care of the angle for all 4 scenarios:
set angle to inAir * (VAngle(XinputSpeed, YmainSpeed) + 180 * Abs(Xdirection-1)*.05)
the VAngle bit uses Spryke's horizontal and vertical movement (XinputSpeed and YmainSpeed) to set the correct angle for the smoke...if she's jumping diagonally right. However, if she's jumping diagonally left, we need to spin the angle of the smoke around by 180 degrees. So I needed the equation to subtract 180, but only when she's facing left.
Depending on which way Spryke's facing, my variable Xdirection is either 1 (right) or -1 (left). So I used this in the equation, by subtracting 1 and halving the result. So when Spryke's facing right, that results in (1 minus 1) * 0.5 = 0, and when she's facing left, it's (-1 minus 1) *0.5 = -1 (but because I also used Abs, which forces a positive number, the final result is actually 1 instead of -1). So now, when we multiply 180 by this result, we end up with either 180 * 0 = 0 when facing right or 180 * 1 = 180 when facing left. Which is just what we needed.
Finally, we multiply the whole lot by inAir (which is either 1 or 0), which will leave the result unchanged when Spryke's airborne, but force it to 0 when she's on the ground/ceiling and her smoke doesn't need any angle change at all. So now we don't even need to test for Spryke's direction or whether she's airborne. We simply run the code each time, and it will figure out the rest on its own.
With this kind of convoluted gymnastics, I was able to dynamically work out the smoke's direction, movement, position and probability as well. The end result is a bit harder to read, but I've commented it well, so future-me shouldn't have too much trouble understanding it. And despite the extra computation required by the slightly more complex actions, the reduction in conditions (from 14 to just 3!) more than makes up for that. I did some performance testing to make sure, and indeed the new version runs about 10% quicker.
On top of this, I improved performance further by turning the smoke generation code off a portion of the time, preventing it running at all when Spryke isn't eligible for smoke (ie. when falling, floating, or on a wall), and switching from animation sequences to animation directions (which is significantly faster, as I discovered in some tests I did recently). All up, this new vent smoke looks better, yet runs up to 50% faster in stress tests.
But stress-tests aside, what's the real-world impact of the change, during normal gameplay? Not much. 1 or 2 FPS on my system, though it could be more on a slower system. But that's the nature of the beast when it comes to this optimisation stuff: few single changes will make a significant difference, and one can only hope for cumulative benefits, from the systematic weeding out of such inefficiencies across the whole code. And that process is what I'm knee-deep in right now.
Spryke launched on kickstarter earlier this week. It's going well, though there's a long way to go, so please support us!
To get you up to speed, Spryke is a quirky, colorful, and deeply crafted platformer that I've been developing for almost 3 years, along with a team of highly talented and dedicated people.
We're aiming to make Spryke nothing short of one of the remarkable platformers of this generation. It's a lofty ambition, but we're serious about it. Here's a peek at some of the love that's going into this game:
If you'd like to help us make our vision for this game become a reality, please back our kickstarter campaign. We have some pretty cool rewards on offer! Oh, and please tell your friends about Spryke! :)
For those of you who use Clickteam Fusion, I'm pleased to release VACCiNE (Volnaiskra's All-purpose Customisable Controller & iNfo Engine). It's a combination of a couple of systems I've developed for Spryke over the past couple of years. I figured they'd be useful to others too, so I've spent the past week or two cleaning it up, adding more features, and commenting everything.
What is VACCiNE? (the short version)
VACCiNE is a handy bit of Fusion code that makes pretty much every gamepad under the sun work out-of-the-box and flawlessly with your Fusion PC game. It greatly simplifies the work required for your game to have robust gamepad and keyboard controls. It also provides a sophisticated in-game debugging panel that you can fill with useful info, to help you monitor the nuts and bolts of your game. VACCiNE does all this with regular, well-commented Fusion code, and regular Fusion Active Objects, meaning that you can easily enable/disable/customise/expand any part of it to suit your own project. It's designed to be as simple as possible, though an intermediate level of familiarity with Fusion is recommended.
What is VACCiNE? (the long version)
For a more in-depth overview of what VACCiNE does and how it works, please visit the forum page, read the comments inside the MFA file itself, and/or watch the video below.
You can download VACCiNE towards the bottom of the Downloads page
Now that IGR Avcon (where I received a lot of very positive feedback, including landing on a 'best of IGR' list) is over, I can concentrate on the next stage of Spryke's development, which is going to be a really, really cool one: the playable intro sequence.
Spryke's already a very pretty game, but I can promise you that this intro sequence will be more spectacular and visually rich than anything we've shown before. It'll be a playable sequence that introduces the player to the game's core mechanics as well as the Spryke universe, starting in the Sporala homeworld deep under the sea. There'll be tons of action and beautifully animated critters swimming around and, at last, story exposition! I think it's going to ground the game and inject it with a lot of soul, not to mention wow factor!
Pulling off the intro sequence according to my vision for it will be a massive amount of work. In preparation, I've just completed my productivity-enhancing Clickteam Fusion skin:
Clickteam Fusion is the engine I use to make Spryke. It's a syntax-free yet very powerful engine, which makes it perfect for someone like me who's more artist than programmer. Its interface contains some unnecessary friction points though. So I did my best to improve the user experience by making a skin that's designed to maximise productivity (as much as is possible in a skin)
I've called the skin Productiva, and it's designed to minimise clutter, keep the eye focused on important areas, and add a better sense of clarity and hierarchy to your workflow.
I've actually been using a version of this skin for almost a year, occasionally iterating and improving it throughout that period. I felt it was time to finish it up and put the final adjustments on it. It's now as good as I can make it, so I feel it's ready to publish. If you're a Clickteam Fusion user, you can buy it for 2 bucks at the Clickstore.
Below is a comparison between Productiva and the default skin, outlining some of the areas I addressed (click it to enlarge)
So we spent the weekend exhibiting Spryke at Avcon (a large gaming and Anime conference in Adelaide). It was great!
It was the first time Spryke was shown to the public, and the reaction was overwhelmingly positive. Comments like "it's so polished!", "the controls are just perfect" and "I thought the difficulty would frustrate me but I just kept going back for more!" kept coming.
We got some critical feedback and suggestions for improvements too, which is obviously very important. But the majority of feedback we got was positive, which felt wonderful. Seeing people who played the demo earlier drag their friends to our stall saying "you HAVE to play Spryke!" is a great feeling, and makes you know that your game is on the right track.
Anyway, now that Avcon is over, it's time to officially announce the Spryke demo! Go and grab it!
I've been working on Spryke for about 2 and a half years now - most of that full-time. Steam tells me that I've logged 1927 hours in Clickteam Fusion (the engine I use to program Spryke). I figure I've probably spent another 2000 hours or so in Photoshop doing the graphics, and a good few hundred animating in Toon Boom Harmony. Then there's all the planning, the sketching, the marketing, the emails, the textbook reading, the online tutorials..........long story short, I've been busy!
Spryke's coming along great. I have basically one motto for Spryke: make everything excellent. That might sound unrealistic or pompous, but it actually translates to something very simple: work bloody hard. That's all. It's not easy, but it's straight-forward.
Spryke has more intricately detailed parallax background graphics than any other 2D game platformer I can remember seeing (and that includes those made by huge teams, like Ubisoft's Rayman games). Its foreground graphics aren't quite up to scratch yet, but they will be. And the intricacy of Spryke's animation is right up there too, with more nuanced animation than you see in most 2D games. The gameplay's fun too, because I spent months tuning it to make sure it was the right balance between superfast and forgiving.
None of this is because I'm amazingly talented or special. It's simply because I love Spryke so much that I let it consume just about every waking hour I can spare. I pour attention onto every facet of it until, finally, after a hundred iterations, that facet feels excellent to me. One of my main strengths is simply having the stamina to improve things beyond the point where many would have said "eh, good enough". I have no social life so that you, dear reader, may have a beautiful game!
Anyway, soon you'll be able to see some of the fruits of my labour. I'm off to Adelaide in a couple of weeks to show off Spryke at IGR 2016, and I'll upload a publicly available demo to this website at that time too.
And today, I'm very excited to say that I've finally finished Spryke's first trailer! It's made entirely of in-game footage, so I think it gives a great sense of what the game is like to play. The audio was done by the excellent team at Kaleidoscope Audio.
Now that Spryke is fully animated, I'm spruicing up the website with a few new GIFs. Please take this quick survey to help me decide which GIFs to use!
If all the scrolling in the inline survey below is too annoying, take the survey on the surveymonkey site
I've been hard at work on Spryke this year, particularly on animation. I promised you guys that Spryke would have killer animations. (I believe my words were "something at the level of Rayman"). And I think I've delivered!
I'm super happy with how Spryke has turned out. She's bouncy, rubbery, squishy, full of character, and has got an intricacy of movement and level of detail that, frankly, you rarely see in indie games.
I still need to put together some animated GIFs and youtube videos to show her off. But for now, please enjoy some new still screenshots, including a first peek at the new cave world!
2015 was a big year for Spryke. 2016 will be even bigger.
2015 saw Spryke go from a blocky prototype full of placeholders to something starting to resemble a game. I began giving the world a look and feel, with some detailed graphics, an in-world alphabet, and procedural background animation systems.
Spryke herself took shape, after countless iterations. Several test levels were designed and built, and the game got an official logo. The backstory and narrative got some love and care too, though that part is still marinating.
Perhaps most importantly, Spryke received a substantial funding grant from Film Victoria, a government Arts agency in Australia. Emotionally, this was great validation for me. It's one thing to passionately believe in your own project, but it's another to see that others believe in it too. The grant will give Volnaiskra extra stability in the coming year, and will ensure that I can enlist the help of extra developers and/or whoever else I might need to help make the game as good as it can be.
That was just the beginning though, and 2016 is where everything really will come together. Right now, I'm concentrating on character animation and gamefeel. Spryke had only the most rudimentary of animation until now, but she'll get a total overhaul now. You can expect something approaching the level of the Rayman games.
Over the coming months, you can also expect to see some interesting and unique new locales take shape too, alongside the futuristic city that you see in the current screenshots. Plus new enemies, mechanics, effects, and plenty of new levels. Maybe even another alien alphabet or two.
I have a top-notch composer lined up, and Spryke will get a full outfit of original music this year too.
In general, I hope you'll be able to learn much more about Spryke over the coming months than you've been able to so far. The last post on the Volblog was over half a year ago, and it wasn't even about Spryke. That's just not good enough.
There's actually a lot of stuff that's already in the game but that I haven't yet shared with the public because I've been so busy developing. But I'll endeavour to keep you guys more informed this year, so look for some posts revealing some of Spryke's mechanics, story, as well as some behind-the-scenes stuff that you might find interesting.
I'll also need to expand my pool of user testers soon, so look out for a playable demo early(ish) this year too!
The Melting Pot and the Salad Bowl: Why the Witcher 3 is a step forward for ethnic diversity in games
I watched an Akira Kurosawa film the other day. It was good, but it was too Japanese.
No, not really. But I did read a Forbes article today titled "Yes, I'm Colorblind about The Witcher 3, and Yes that's a problem". The author responds to an article by South African writer Tauriq Moosa that criticises The Witcher 3 for its lack of non-White characters. Moosa complains that it's symptomatic of a general tendency for games to ignore minorities.
I sympathise with Moosa, and agree that diversity in games is generally pretty dismal. But in targeting The Witcher 3, I believe that Moosa was wrong-headed, culturally insensitive, and has inadvertently attacked the very diversity he seeks to promote. I have no doubt he has good intentions, but I find his article personally offensive.
First, let me clarify where I'm coming from.
I'm no reactionary or anti-political-correctness crusader. I'm what many people would call a bleeding-heart liberal. I've never voted for the Labor or Liberal parties (the Australian equivalents of the Democrats and Republicans, respectively) because I find them both too conservative. I've always voted for the very liberal Greens instead.
I am, for example, generally a fan a Anita Sarkeesian, and have no tolerance for her army of hateful detractors (the mere existence of people who call themselves 'anti-Feminist' strikes me as incredible).
I'm also no stranger to racial diversity. My wife is a dark-skinned South African woman who grew up under Apartheid. We delight in our mixed-race daughter, and we're raising her with dual influence from both our cultures, and in both of our native tongues: English in my wife's case, and Polish in mine.
In 2010, something very special happened to me. After decades of playing computer games, I played - for the first time in my life - one that was for me. It was a first-time game from a young Polish developer called CDProjekt RED, and it was called Wiedźmin. I was enthralled. The people in this game looked like me. They spoke my language. They emanated a Polishness that at once resonated with my own.
You might think, as Moosa would seem to: "Pffft, big deal - you're a White guy, so you've been playing games about yourself all your life." But that's a very myopic way to look at ethnic identity. I find the notion that a person's identity might be defined by their skin colour to be patently horrific, not to mention inaccurate. There are a thousand physical and cultural idiosyncrasies that can make up a person's ethnic identity, of which skin colour is, at most, one.
When I grew up watching White Americans in Hollywood movies or big budget games, I never felt like I was seeing a representation of myself. They were from the other side of the world to me, their roots were different to my Slavic ones and, with their square jaws and rectangular heads, they didn't particularly look like me either. I imagine that a similar thing would be felt by an olive-skinned Venezuelan watching movies about olive-skinned Italians: they would see foreigners, whose coincidentally similar skin colour would be mostly irrelevant.
Sure, I had American heroes, but they were as likely to be Hispanic (Lou Diamond Phillips' Chavez in Young Guns) or Black (Mr T) as White (Val Kilmer's Madmartigan in Willow). I just saw them as cool guys, rather than 'guys like me'.
I felt increasingly out of place in the predominantly Anglo-Saxon society I was growing up in. Very rarely in a threatened or hostile way, but just like I never quite fit in. I'd grown up in a Polish household, and Polishness was a large part of my makeup, though I almost never saw this part of myself reflected in Australian society. It was a part of myself that felt fundamental to who I was, but existed mostly quietly inside me, lonely.
As I grew older, I discovered Polish cinema, and fanatically devoured every Kieślowski and Wajda film I could find, among others. These films felt like home. Sure, they weren't exactly about me, since their protagonists hadn't spent most of their lives in Australia. But they spoke intimately to that part of me that had hitherto remained unspoken to.
And then in 2010, I played Wiedźmin ("The Witcher"). Here was a huge, 50-hour game that was unashamedly, profoundly Polish. I played the demo, was at once entranced, and hurried out and bought the full game. At every step in its sizeable world, I would encounter people who looked like they could be my relatives, or even looked like me.
The high cheekbones. The small triangular jaws. The heads that were wide and flat at the back. The lean forearms. Here I was among my own people. I found elements of Slavic mythology and Polish history (both old and recent). The world was covered with Polish folk art and architecture, and I recognised the world's alphabet as a variant of the ancient Slavic Glagolica script. I noted in Wiedźmin's world the twin pulls of Romanticism and Positivism that had so defined the various ebbs and flows of uprisings throughout Polish history.
And then there were the less tangible things: the humour, the melancholy, the colourful profanity, the earthy philosophising - it was all so familiar. I spoke to old women who sounded like my grandmother. Zoltan the Dwarf reminded me of family friends. I mean, drinking vodka and getting blind drunk was actually an important gameplay mechanic! Playing the first Wiedźmin game remains one of my most cherished memories in three decades of gaming.
This wasn't just the rosy-eyed romanticism of a culture-starved ex-pat talking. In the DVD that accompanied the Collector's Edition, the creators positively beamed as they spoke proudly of their singular achievement: the bringing of a piece of Polish pop culture - the Wiedźmin books by Andrzej Sapkowski - onto the world stage.
No one had achieved this since Chopin. Sure, Poland produced some renowned art film directors, jazz musicians, and a few Nobel Laureate writers. But these were 'high art' works that never really seeped into global mass culture. We never had, say, an Abba or a Björk. The average Westerner was likely to have read just one Polish book in her life, if any - and it was about as un-Polish as a Polish book can get: written in English, by an ex-pat with an Anglicised name, about Africa (Heart of Darkness).
But now, CD Projekt had done it. They had made a game by Poles, for Poles, and placed it upon the world stage. By doing so, they opened up a window through which the world could glimpse a slice of Polish popular culture. Sure, Sapkowski's world borrowed liberally from Tolkien's, which was based largely on Germanic, Nordic and Finnish mythology. But Geralt of Rivia's world was still unmistakably steeped in Polish culture, history and mythology.
It was a modest achievement. The Witcher could at best be described as a "cult hit". Sales were good for a first-time small studio, but technical issues marred the game, some juvenile sexism had crept into the otherwise mature narrative, and reviews were mixed. In many ways, The Witcher 2 was a quantum leap forward. It was graphically and artistically stunning - at times peerless - and with writing that was almost universally praised for its complex and believable characters. Though it too was not without problems, and its limited scope still made it feel like a little brother to a Skyrim or a Dragon Age: Origins.
The Witcher 3 changed all that. It's a truly AAA title; it arrived with bombast and grandeur and promptly raised industry benchmarks. It was sprawling, ambitious, and well-made. Critics praised CDPR's refusal to take shortcuts that must have been tempting when making such a huge game. Care was taken to ensure the scores of NPCs felt like believable people, and almost all of the numerous quests feel like solid stories, their many possible outcomes intertwining meticulously with the narrative whole.
There have been AAA games by Polish studios before, but they weren't really Polish Games per se. Think Bulletsorm or Dead Island. The latter, incidentally, contained an Aboriginal character who looked absolutely nothing like a real Aboriginal person, but like a Black American. This is absurd, given the tens of thousands of years and vastly different genealogies that separates those two groups. But no one in the media seemed to pick up on this - as long as the skin colour matches, that's all that matters, right?
Anyway, one of CDPR's achievements that hasn't been mentioned much is how they managed to make such a gigantic game without watering down its inherent Polishness. By now, the Polish market must be a small fraction of CDPR's target audience. They could easily have watered down the cultural elements of the game to make it more suited for an American and/or global audience, which was far more instrumental to its commercial success. This happens routinely with Hollywood movies. But they didn't. Witcher 3 is as Polish as Witcher was. This is a great thing, for everybody.
As it stands, The Witcher 3 is Poland's finest export of popular culture in living memory. CDPR have produced a world-class game that would not have been the same if it had been produced anywhere else on the planet. It is a unique gift to the world that only Poland was qualified to give. The French gave us Asterix, Hong Kong gave us Bruce Lee, and with The Witcher 3, Poland has finally made its contribution to global mass culture too. It's a win for Poles like me who rarely get to see themselves in a game, but it's also a win for pop cultural diversity in general.
But for writers like Moosa, a Polish game like The Witcher 3 is unacceptable - it's too Polish.
Of course, Moosa would surely never say that the game is too Polish. For him, the issue is much coarser than that: it's simply too White, and that's that. No need to look deeper than skin-deep.
Well, yes. Of course everyone in The Witcher is White. It's a Polish game, made by Polish people, based heavily on Polish history and Slavic mythology. And so everyone in the game - whether Human, Dwarf, or Elf - tends to look.....surprise surprise......Polish.
Poles, like most Northern Europeans, almost all happen to be White - this paleness helps our skin get more vitamin D from the scarce sun. The largest non-White ethnic minority in Poland are the Vietnamese, who comprise less than 0.1% of the population. Not surprisingly, there were even fewer Vietnamese people in medieval Poland, and fewer still in ancient Slavic mythology.
For me, the saddest thing about this whole thing is that people like Moosa have clearly missed the cultural uniqueness of The Witcher 3. Some Polish critics praised the game's Polish elements, yet optimistically predicted that the game might be even more interesting for outsiders than for Poles, since it would contain elements that were exotic for them. But for people like Moosa, the opposite seems to have occurred: all he saw was just another Western game.
It's not just another Western game. It's the first ever AAA game that portrays Polish people and Polish culture. This is our game. The Polishness of this game is special to us, because it's the only one we've got!
I get it - there are no AAA games with all Brown or Black characters. I wish there were; I would eagerly play them too. But to Moosa I say: please understand that until The Witcher, there were no AAA games about Poles either. Although we're a smaller and tighter group than you, we finally got our game. I hope that you finally get yours too. But you have no right to begrudge us ours.
I kind of get the misunderstanding. For one, much of the historical and cultural nuance would have been lost on Moosa, who obviously isn't well acquainted with Polish and Slavic cultures. He can hardly be blamed for this. Though the irony is that he'd be better acquainted with them if he'd paid attention to the game he just played with a grain of cultural curiosity, instead of choosing to dismiss it all as frivolous nonsense.
Thus he calls any attempt at historical accuracy in the game "nonsensical" because "accuracy and realism flew out the window with the harpies." Really? Greek and Incan myths were as outlandish as Slavic ones - does that mean that insisting that the humans in them be portrayed by people who look like Greeks and Incans is also "nonsensical"?
Also, Moosa would have played the game with English dubbing, complete with American and British accents. I always played through the games in Polish, but I briefly switched to English out of curiosity, and it does indeed feel like a very different game. The voice acting seems solid enough, but the dialogue feels heavily watered down, and much of the nuance is lost in translation.
So I can see how an American, Briton, or South African might fail to grasp the cultural content of the game, and instead look through it through his own cultural lens (especially since many other fantasy games are entirely fictional, without real world cultural meaning). I think this is a lazy and crass way to view a cultural product from another country, and I'm not excusing it - but I do find it at least understandable. Especially if that cultural lens happens to contain an obsession with skin colour, as the South African and American lenses tend to.
For this is a key point: Poles aren't anywhere near as obsessed with skin colour as South Africans Americans seem to be. Nationality or ethnicity? Yes. But skin colour? No.
We have no reason to. Unlike South Africans during Apartheid, we were never conditioned to see the world in terms of skin colour. Unlike the British, we never colonised distant lands. And unlike the Americans, we didn't take part in the African Slave Trade (though, if you're Anglo, some of your ancestors might have owned some of my Slavic ones, before they owned the ancestors of present-day Black Americans, since that's where the word "Slave" comes from).
So, without colonisation or African slavery, we don't have a resulting large Black population, and we don't have any White Guilt, because there's nothing to feel guilty about. White Guilt is largely an Anglo-Saxon and Afrikaner problem - please don't project it onto us.
This is of course not to say that Poles have any kind of moral superiority to Anglo Saxons or Afrikaners. Like every nation, we have a checkered past with too many atrocities to count. It's just that our traumas are different to your traumas. In your case, the wronged parties were frequently people of colour. In our cases, they tended to be Ukrainians, Lithuanians, Jews, and Czechs, to name a few.
If playing a game where everyone is White makes you feel uncomfortable because you're American and you live in a country where most people are White but 10-15% of people is Black, then go play a game where most people are White but 10-15% of the population is Black. It's called Skyrim. It's American, and was clearly made with an American demographic in mind.
But if you play a Polish game, please don't complain that there are too many Poles in it, and that you'd like the demographics to be a bit more similar to that of your own country's. That's like walking out of the airport in a foreign country and angrily saying "Where are all the McDonald's!?"
Broadly speaking, there are two ways of looking at multi-ethnic harmony. One is the Melting Pot, and the other is the Salad Bowl. The Melting Pot is by far the more commonly understood metaphor, but it's also by far the least desirable of the two.
A Melting Pot is a crude furnace that assimilates everything into a single, homogeneous pulp. Some melting pots are mindless, producing whatever random gloop happens to remain at the end of the melting process. Some, as in the case of a metal alloy, use a recipe, and carefully discard and select elements accordingly. Neither is a particularly desirable conception of multiculturalism.
A Salad Bowl is a harmonious and exciting environment where the unique qualities of every single ingredient are honoured and celebrated. The lettuce is green and crispy, the tomatoes are red and acidic, the oil is mellow and fatty, and together they make for a sumptuous dance of flavours and textures. No one demands that the tomato be more green and crispy, or that everyone become a little more acidic. The only requirement is that they get along harmoniously. When they do, the whole becomes greater than the sum of the parts. This is multiculturalism at its best.
A world where a Polish dev isn't allowed to make a fully Polish game is the world of the Melting Pot. It's not a more diverse world. It's a less diverse world. It's a world where everyone is asked to become a little bit more similar, and the unique demographics of any one culture must be downplayed. It's a world where the smaller cultures of the world get smeared into incoherence by the normalising wooden spoon of conformity. It's a world that's not likely to produce many culturally diverse games.
I want to live in a Salad Bowl. I want to be able to play a game where I can see my own people, in all their glory, uniqueness and imperfection. And I want to be able to play games where I can see other peoples in all of theirs.
If you're like many Photoshop users, you might not use Layer Styles much. Or maybe you think that they're only good for cheesy bevel and drop shadow effects. Actually, Layer Styles can be very powerful and surprisingly versatile. In fact, I do almost all of Spryke's graphics using Layer Styles (applied onto vector shapes).
Note: This guide is based on Photoshop CC 2014 (the latest version as of writing); minor differences may exist in older or newer versions of Photoshop.
Quick rehash: What are Layer Styles again?
To access Layer Styles, double-click a layer in photoshop. From there, you can tweak various settings to alter the appearance of the layer. Layers that contain Layer Styles have an "fx" icon on them. If you make a Layer Style that you think you'll reuse, you can save it in the "Styles" palette.
Below is one of the above layers shown with all of its Layer Style attributes. Not every Layer Style needs to be this complex of course, but by stacking multiple attributes like this, you can achieve a great deal of variety and visual subtlety.
This particular Layer Style is used for lights and other illuminated objects. It has a round inner glow (from Gradient Overlay), intense coloring (Color Overlay and Satin, both using Overlay Blend Mode), noise (Inner Glow), and a somewhat intense reddish glow (Stroke, Outer Glow, Drop Shadow).
My mission is to create one of the prettiest and most visually detailed platform games the world has ever seen. Fun and beauty are equally important in game design, in my book.
Here's the background of one of the planets in Spryke. It's made of about 20 parallaxed layers, with dozens (actually, hundreds) of little animated elements :)
It was quite a ride getting Spryke to where she is now. There were dozens of drafts and iterations, and plenty of back-and-forth between me and my character designer (who's totally amazing, by the way!). I'm super stoked about how she looks now.
Next stop: Animating!
I just made a HUUUUUUUGE change to my logo. Do you like it?
If you haven't got your magnifying glass handy, I'll help you out: it's the little symbol at the end. It was ™, and now it's ®.
But I wasn't joking about it being a huge change. Anyone can use ™, as it has no legal weight. But you're only allowed to use ® if you've been legally recognised as the holder of a registered trademark.
As of recently, I'm finally the legal owner of the trademark "Volnaiskra". It's a surprisingly convoluted process that required lots of paperwork, hundreds of dollars, and some 8 months!
It's a pretty small (albeit expensive) thing, but it feels like a bit of a milestone to me :)
I'm working with my character designer on the look of Spryke's titular character. I think she's coming along great!
When I'm not working on Spryke, I also make Skyrim mods. Here's a sneak peek of my latest one.
It's a complete overhaul of the Nordic murals found in many of Skyrim's dungeons. The murals should be one of the most interesting things to look at in all of Skyrim - they're large, dramatic, and are filled with Elder Scrolls Lore. Unfortunately, they're absolutely awful. They're so low-res that they're not only ugly, but damn near indecipherable.
In 3+ years of Skyrim modding, no one's satisfactorily improved them, because to do so would require redoing them completely from scratch, which would be a really loooooong job. No one has been stupid or crazy enough to do that. Until now.
Here's a before and after. I hope you'll agree that the improvement is dramatic!
I've done some more work on alphabet I created for Spryke. Firstly, I gave it a name (Sprykski). Secondly, I've assigned phonemes to it.
In other words, Sprykski is now fully capable of being used to write English, Polish, and many other languages :)
It also contains a number of more unusual sounds (including several clicking sounds found in African languages), which should lend itself well to the exotic inhabitants of Spryke's universe!
UPDATE: Spryke is now on kickstarter! If you want to see this rich universe (and its alphabet) come to life, please support us by becoming a backer!
A great way to enhance a gameworld's believability and atmosphere is to make a custom alphabet for it. The written word is all around us, and plays a major role in making our world look and feel the way it does. A unique alphabet helps make a unique gameworld.
Anyone who's ever tried designing a font knows how difficult it is. Our brain is very sensitive to disturbances in the flow of readability, and each tiny alteration to curvature or line thickness can mean the difference between elegance and awkwardness.
The good news is that the rules are much looser when designing a fictional alphabet, and it can be very fun. But there's more to it than just throwing down some random squiggles. I've recently designed a complete alphabet for Spryke, and I'll take you through my whole process.
The benefits of adding a custom alphabet to your game
First off, let's take a look at some reasons you might want to design a custom alphabet for your game.
An alphabet's aesthetic and functional aspects reveal a lot about its creators, its forms naturally springing from the traits of the home culture.
Take this ancient alphabet, for example:
Step 1: Consider your gameworld's culture
Comprised mainly of sturdy, masculine shapes, these glyphs have a uniformity of size and economy of form that makes them seem almost engineered, rather than merely written. They are solid, upright, efficient.
Judging by this alphabet, one could imagine that it was created by a pragmatic, rigid culture that prized order, strength, and structure. And actually, that's not a half-bad description of the ancient Romans.
Now look at these characters from another ancient alphabet:
These lack the frugality and symmetry of the Latin characters, and are much more complex, intricate, and floaty. One could suppose that the culture that created them was one that cherished sophistication, artisanship, and nuance.
Now examine a third ancient alphabet:
These jagged, spiky shapes have neither the balance and structure of the Latin letters nor the grace and complexity of the Chinese ones. Instead, they evoke an aggressive, almost savage vibe. And so they should; they are the Dovahzul alphabet: the ancient language of Skyrim's dragons.
Your game's alphabet can and will inform your audience about your gameworld. If your alphabet looks interesting, boring, complex, or frivolous, your game's inhabitants will seem interesting, boring, complex, or frivolous. Use this to your advantage, and make sure that it's communicating the message you want it to convey.
Step 2: Consider your gameworld's technology
Apart from looking cool and a little bit hostile, there's another reason the dragon alphabet above is comprised mainly of long heavy slashes: It was carved by dragons. Dragons didn't have pens, brushes or chisels, but claws, and the clever designers at Bethesda took this into account.
You may not have consciously thought about these logistics when looting Skyrim's tombs, but you probably noticed it unconsciously on some level. By considering not just the alphabet's personality, but also its logistics, the Bethesda crew designed an alphabet that feels right.
There are various technological factors that can influence a successful alphabet. These Anglo-Saxon runes were usually carved into wood, so they avoid curves and horizontal lines (straight lines were easier to carve, and horizontal lines could have caught in the wood grain and split the wood):
Conversely, this gorgeous Sinhala alphabet from Sri Lanka avoids straight lines and corners. Sinhala was written on fragile palm leaf paper, and sharp corners would have caused tearing.
As you can see, technological considerations can have a profound impact on the look of your glyphs. Paying attention to technological logistics won't just make your alphabet more believable, but may take it in an exciting aesthetic direction.
Some things to think about:
Spryke is set in a distant planet sci-fi setting, so my alphabet needed to look somewhat modern (as it would most often be rendered by precise machines, just like in our present-day world). It would also need to be alien and unfamiliar, while maintaining an element of fun to suit the cartoony vibe of the game.
Step 3: Research
There are loads of writing systems on Earth - possibly more than you think. Look through a few of them to get ideas about what your own will look like.
So, do some research and get ideas. Don't forget to check out different fonts where possible, as they may employ different design solutions. After all, a traditional Japanese scroll will have a dramatically different aesthetic to downtown Tokyo neons.
But if you're like me, inspiration is just a few centimetres away!
Step 4: Choose your elements
Both of my arms are tattooed with a prayer written in Glagolitic, an ancient Slavic alphabet. Convenient! Clearly, I have an affinity for this alphabet, and so this is the one I chose as my starting point.
Most writing systems are constructed using just a few building blocks, in various combinations. It's a good idea to pick your building blocks before you start designing any characters. This will help you create a cohesive design while guarding you from relying too heavily on the shapes of your native alphabet.
Pick a few appropriate shapes that will form the backbone of your alphabet's aesthetic. Remember to peruse existing alphabets for inspiration if need be.
Spryke's alphabet needs to look a bit cartoony, and like it belongs to an alien race. My starting point of Glagolitic is actually a pretty good choice, because it's unique looking and looks quite alien to modern eyes, having gone out of usage long ago. In addition, its hollow circle and equilateral triangle motifs lend it a certain geometric look that fits well with my desired cartoony vibe. To make my alphabet a bit more hi-tech looking, I focused on straight lines and precise angles.
Step 5: Paper
Next, I used those elements to doodle several pages' worth of characters, referring to my Glagolitic alphabet (ie. looking down at my arms) as I went. Some characters looked good, others sucked, and most took several iterations to find their sweet spot.
Step 6: Vectorise and finalise
Once I had loads of characters on paper, I went back through them and circled the 40 or so that had the most promise. I ported these into Photoshop using the vector shape tools (You could of course use Illustrator or some other software). After plenty of fine tuning and iteration, my alphabet finally took shape. I'd created 52 finished characters in all:
Some things to consider while working on your characters:
Step 7: Punctuation
Forgot about punctuation, didn't ya? For our purposes, there are two types of punctuation, which I'll call structural and emphatic.
Whether or not you need punctuation at all is up to you, and the specifics of your game. I decided that Spryke won't need structural punctuation, but could benefit from some emphatic punctuation.
If you choose to use emphatic punctuation, you must make it somehow decipherable by your audience, even though the rest of your alphabet isn't. There's no point inventing a question mark symbol to replace "?" if people will think it's just another letter.
There are several ways to tackle this:
I went with the last option, and made three different punctuation marks. My players won't know what exactly they mean, but the marks should stand out enough to make it clear that they imply emphasis of some sort. Their unique design, raised position, and parenthesis-like clumping of other characters should all help with that.
Step 8: Numerals
As with emphatic punctuation, numerals need to be visually different from your letters. I achieved this in two ways. First, I made them smaller and more uniform in size. Second, I constructed them from different shapes. I exclusively used arcs (incomplete portions of circles), to give them a different appearance from the letters, which were made from complete circles, triangles, and straight lines.
Step 9: Fonts
I'm writing this in a small home office, yet I can see more than 20 different fonts without even getting off my chair: several across my computer screens, a different one on the logo of almost every appliance and piece of computer hardware in the room, and a few on an old bill on my desk. No matter where you are, I'll bet you'd find plenty of fonts around you too.
Our world is loaded with different fonts, and things would look weird if everything was suddenly written in just one. So your gameworld should probably have a few fonts too. Making new fonts won't be quite as time-consuming as inventing your characters was, but it will still take work. I suggest making a few fonts, with specific use-cases in mind.
I made four:
Putting it all together
Done! I now have a unique, cohesive, and interesting alien alphabet comprised of 52 letters, 10 numerals, 3 punctuation marks, and 4 fonts (that's 260 characters in total). I can now pepper it throughout Spryke's gameworld as I continue to develop it, confident that I have glyphs to suit any context.
I hope this helps someone, and if you've designed your own alphabet, I'd love to see it!
To watch Spryke as it evolves further, like my facebook page.