These past few days have been relatively productive, but in a way that hasn’t really changed anything about the actual game if you sat down to play it. Recently it’s felt like every time I go to add something, I’m needing to clean up a lot of cruft first. I suppose this is normal for this stage of development, but it does feel a bit like wading through mud from time to time and has been slowing down development progress. Furthermore, although it might be appreciably nicer to work with the code after a good long day of refactoring. It’s boring as crap to talk about what I did.
I finished up the meta-tiles in the manner I mentioned in the previous post. Getting them to work alongside the dice face mechanic and the walk-able puzzles was fairly straightforward. Mostly because of the choice I made to use meta-tile numbers for all of the run-time puzzle calculations. The current implementation of the area search feels like it’s a bit inefficient, but it works so I’m happy enough.
Part of how I managed to get everything working relatively quickly is that I created a nice little helper function that looks up the meta-tile for any given (x,y) position and sets it to a certain state. This means most of my old algorithms work just the same; I can just drop in this setMetatile() function in place of my old calls to set individual tiles, and I’m good to go.
I’m still using the connections-based approach for the puzzle editor, but I may end up changing that as well. As I mentioned before, although switching to editing the meta-tile numbers directly might make building puzzles a bit more time consuming, it would also give me higher precision and allow me to implement some puzzle types that I don’t currently have. So, it’s probably worth it.
There are some other interesting details that came alongside the implementation for the walk-able puzzles, but I don’t want to spoil everything!
As I’ve said previously, I mostly implemented these metatiles because it felt like something obvious that was missing. This is a bit strange feeling, because I don’t have any immediate plans for puzzles involving them. I do hope to find some, but usually I don’t do this much work before I even know if the idea is going to bear fruit.
Normally, I use a process for prototyping new puzzle ideas that is intended to reduce the amount of wasted implementation work as much as possible. I start with prototyping ideas on paper. Just drawing stuff out in a notebook of graph paper. Then, if I see some potential there, I will usually implement a bare bones version of the mechanic into the game, without much thought for what it looks like. In this case, I think the mechanic itself ended up being just complex enough that it was pretty hard for me to paper prototype it, and just visual enough that it was difficult for me to digitally prototype it without doing a fair amount of implementation work.
I think there’s a similar situation in my mind with any puzzles that have to do details in the visual element of the game. Those kinds of visual puzzles tend to be rather subtle, and as long as the game has programmer art, there are only so many ideas that are going to come to my mind. Simply enough, the elements necessary to build the puzzles just aren’t there yet.
In any case, I hope to find some good puzzles.
P.S. I still have yet to upload the higher-quality archives for the past 4 development streams, including two I did in the past week. So look forward to that before too long.
This week, I’ve been working on implementing a feature that I have wanted to have for a long time: puzzles which feature tiles of non-uniform size.
Thus far, all of the puzzles in the game have been built around fixed-size tiles. It’s a bit hard to explain the difference in words, so here’s a visual example:
The left image is how all the puzzles in the game currently operate, as a grid of uniform tiles of all the same size. The panel on the right is a mock-up of what I want to do. Essentially, I want the capability to make puzzles where tiles can be “connected” together into larger groups, or meta-tiles. Doing this requires a bit of ingenuity, both within the tech and from a graphic design perspective.
Since I’m still keeping the grid-based setup, the problem is much simpler than it could be.
As far as the artwork is concerned, we can cover all of the shapes we might want by subdividing each panel tile into 4 smaller sub-tiles, each of which can be one of three different graphics:
This is the most economical choice from an asset design perspective, because although there are more variations required than the 3 sub-tiles, they can all be expressed simply by rotating the tile images.
As simple as the art is, the code is kind of complex, both in determining how to rotate the sub-tiles, and because there is an additional “corner” case (Get it?).
For example, with the basic approach, in which you just check the neighboring tile and see which ones are connected, if you were to have a large connected block of four tiles, you’d end up with something like the left-hand image below:
Notice that each tile is drawn as a single-width corner, and so we end up with a hole in the middle of the area. This might be desirable in some cases, but here it’s really just an accident.
Luckily, this isn’t too difficult to resolve. You simply check, for each tile, if it is connected so as to form a corner, and then you additionally check if the tile diagonally opposite that corner is also connected to form a corner, and if it is, you just change the inner corner graphic. This technically requires a fourth sub-tile for the inner corner, which is just a solid color.
One of the other challenges was deciding upon a data format to express these meta-tiles, and additionally, how I would interface with that format in the code.
There are two approaches that initially came to mind, both of which have their costs and benefits.
Add four booleans (true/false values) to each tile, for each of the four cardinal directions, to indicate whether or not the tile is connected to its neighbor along that direction. The benefit here is that checking for connections is simply a matter of checking a value stored alongside the tile. However, it is rather wasteful of memory, with four additional entries per tile. And furthermore, for each connection, there are two values, leaving the possibility that the connection values could end up out of sync. (This can be resolved with reference types though, as I’ll explain later)
Create an array which stores the connections between tiles as booleans. This is memory efficient, as there is no data duplication. However, it is somewhat cumbersome to work with in the code, without doing some additional engineering. (The panel is made up of one 2D array, and the connections are an additional 2D array, but it is somewhat hard to make direct comparisons between the two arrays.)
I decided to go with the second option to begin with. Both options have their upsides and downsides, but the memory efficiency of the second option seemed most appealing to me for whatever reason.
Notice that both approaches are thinking about properties of the individual tiles which make up the meta-tile. Each tile has connections to its neighbors. This approach has some flaws which will come back to bite me in a bit, but this is what I chose to go with first, and I think it’s important to document my process as it happens.
My general strategy when doing any engineering work (and sometimes design as well), is to do the simplest dumbest thing that seems like it will work, and clean it up later. This means I may just implement the first solution that comes to my head. This is a good approach because, most of the time, unless a problem is utterly trivial (or you have implemented a similar solution many times before), you don’t really understand the problem well enough before you begin. The likelihood of anything you think of before you start coding being the right solution is pretty close to zero.
So get your ego out of the way and just start coding!
It’s a bit difficult to explain the way that I structured the data, but since I went through the trouble of creating an editor interface for the connections, I’ll simply show you what that looks like, as it’s a useful way to visualize the data structure of the panel in terms of how it relates to the connections.
In the editor interface shown above, the actual tiles of the panel are represented by the ☐’s. The connections between the tiles are represented by the checkbox buttons.
In terms of the data layout, the panel state is stored as a 3×3 array of booleans, and the connections are stored as a 3×5 array. I need the additional rows. as each tile has vertical as well as horizontal connections.
Fun fact: For any particular panel of dimensions W¹×H¹, the formula to determine the size of the array necessary for storing the connections between tiles is
Second Fun Fact: Every other row, I don’t use the last horizontal entry in the row, so I technically do waste a bit of memory.
As I mentioned earlier, because of the unusual data layout, it is not exactly obvious, for any given tile (x, y) on the panel, which (x, y) to look at in the connections array. This is one of the flaws of the tile-centric approach.
This function gets called a lot, and is pretty computationally inefficient. One solution would be to cache the results of these calculations and store the results alongside each tile. This is equivalent to option #1 from earlier, however if the stored values were only references to the values in the connections array, this would avoid the problem of the data getting out of sync.
The next thing we have to resolve is toggling the whole connected piece when the player clicks on it, and handling the highlights when the player hovers over the piece.
Since the code that deals with the player clicking on tiles still works with individual tiles, rather than the whole connected group, when the player clicks on any given tile, we have to do a search to determine all the tiles connected to that tile. From a technical standpoint this is somewhat non-trivial, but it is analogous enough to the issue of finding all the tiles within a colored area, that it was a problem which I’d already solved. The only difference here is the criteria by which the tiles are considered “connected.”
So, we do the exhaustive search for all connected tiles when the player clicks to toggle. Although this works well enough when we’re toggling, we also need to highlight the tile when the player mouses over it. (Notice in the above GIF that the tile highlight is still isolated to the individual tiles, and doesn’t cover the whole connected group)
We could do the same search that we were doing when toggling a tile, it would technically work, but doing it every frame seems a bit wasteful. Of course, we could do some basic optimization and only do the search when we really need to, when the player has moused over a new tile.
This is all fine, but something started to smell funny to me. I didn’t like how wasteful things were getting computationally. After thinking about it for a bit, I came to a more optimal solution.
Until I got fairly deep into the implementation, I had been thinking about this whole problem from the bottom up. I was thinking only about the same uniform tiles I always had, rather than the meta-tiles. A meta-tile, as far as I was concerned was just an emergent result of a system which allowed tiles to be connected to each other.
But what if we think of a meta-tile as it’s own entity? If we do, then our problem of finding all the tiles that make up a meta-tile suddenly becomes trivial.
Additionally, because the layout of the panels in the game never changes in real-time (thus far), I have the luxury of baking down any complex calculations that have to do with the panel layout. In this case, I can just bake-down the meta tile groups at startup.
In the baking process, I iterate across all the tiles on the panel and store an integer for each tile, denoting which meta-tile group it is part of. For example, if the first tile I check is connected to form a meta-tile, I will mark all of those tiles with a meta-tile number of 1. The next meta-tile I find, will have a meta-tile number of 2. And so on.
The numbers don’t really matter as long as they are the same for all tiles within the same meta-tile group.
This means I only have to do the exhaustive search at startup, and from then on, whenever I need to find all tiles that are connected to a current tile, I can simply compare the current tile’s meta-tile number to all the other tiles on the panel, and if the numbers match, the tiles are connected.
(This is actually a simple enough way to handle connected tiles that I may choose to do away with the connections array. Additionally, opening up the ability for overriding the meta-tile group manually would allow for some additional things, such as having tiles that are not physically connected, but can only be toggled in unison.)
Fixing the Mechanics
Getting the gameplay mechanics working again is somewhat more complicated, as I have to combine the idea of areas connected by color with the idea of multiple “tiles” being connected together into one big tile. This shouldn’t be too difficult though, as we just have to add meta-tile awareness to our normal area search. Still, I didn’t get to it this week.
So…to be continued.
In the process of doing all of this, I ran into some performance problems. This is somewhat to be expected. Previously, each puzzle panel tile required 3 sprites, but under the new system, there are 9 sprites per tile. (I have the four corner sprites both for the fill part of the tile and the outline part, as they can be colored/enabled separately. Additionally, there is a background color sprite for each tile.)
One of the obvious issues was a huge uptick in the time spent on start-up. This has been a bit of an issue for some time already, but it really just skyrocketed. I try to keep the startup time down to less than 5 seconds (Ideally it would be much faster than that, but there seems to be a certain amount of overhead in Unity that is simply unavoidable), but after making the changes to allow for the increased graphical flexibility, the start-up time ballooned past 10 seconds.
This may not seem like a lot, but I like to keep my iteration times as fast as I can. This desire for instant feedback (or as close to it as possible) is why I took the time to get a live updating feature for the puzzle panels.
The overhead came because I was initializing every single puzzle panel in the game at startup. This involves not just spawning objects for each panel, but for every single tile on every single panel. As many of you who are familiar with Unity may know, spawning new GameObjects is one of the more expensive things you can do. Unfortunately, with all the additional GameObjects involved in the new sub-tiles, there were just too many objects being created at start-up for it to happen in a reasonable timeframe.
So in order to reduce the start-up time significantly, the thing that made the most sense was to avoid initializing anything that wasn’t completely necessary. I could have chosen to go right to an object pool system, where I reuse tiles from panels as needed and only spawn a few at a time. But instead, I just chose to go for the simpler method, which is just to check which panels are visible to the player when the game starts, and only initialize those.
Apart from the startup time, there were some other issues with how I was handling control of the colors and images on the sprites. I made the initial mistake of delegating all of that work down to the individual 8x8px corner tiles, but it really made more sense to cluster the work up at a higher abstraction level in the 16x16px tiles. There is a decent overhead to each individual MonoBehaviour component in Unity, so the less you can have of them, the better.
As time goes on, it may make more sense to bring that tile management work all the way up to the level the entire panel itself, but for now this is a good balance between locus-of-control and performance.
There were some additional minor performance issues unrelated to the new panel changes that I nevertheless took the time to clear up. I won’t really go into those here, but it always feels nice when you get things running better.
I’ll be back next week to talk about getting the puzzle mechanics working again. I also need to repair the walking puzzles, cause I seem to have broken the graphics for them.
This week I didn’t spend a ton of time on the game, nor did I add anything flashy. However, I did take some of the things that I learned last week while improving the puzzle panel editor GUI and used them to redesign the editor for my custom animation system.
This was the previous system, which involved using several separate components. Both a master Sprite Animation component, and an additional Sprite Animation Strip component for each individual animation:
Although this certainly worked. It was pretty cumbersome to add new animations or tell what you’re looking at. As you can see, the first Sprite Animation component simply has a flat array references to the other Sprite Animation Strip components. Unfortunately, it is impossible to tell the difference between each animation in the list, because all the duplicate components have the same name. Not to mention, having a bunch of separate components wastes vertical space on irrelevant information, and overall… it’s just a mess.
Here’s the redesigned interface:
Although it is almost functionally identical to the previous system (in fact, this is the same set of animations), you can see that there are a number of usability improvements here. For one thing, each animation gets its own name, this makes things way more readable.
Now, you might ask, why even go through the trouble of writing your own animation system when you could just use the built-in Unity animation system, which surely supports way more that this.
I prefer as much as possible for the code to be doing the heavy lifting on things like this, so the Unity GUI editor and data-driven approach just doesn’t appeal to me. Additionally, although the Unity system is fully featured; for a 2D sprite-based game, it’s just overkill. I’m not doing animation blending, so thinking about the animation as a tree is a strange way to think about it. Essentially, a 2D animation is just a flipbook of frames. That can be represented as a 1D array both in the code and in the interface. If I give each of these arrays an index, this makes it super easy to change an animation from within the code. There’s no need to for me to create a FSM with a state change graph and all that when I could just set an animation index. If I want to change which animation is currently playing. I can just do this:
playerAnimation.index = 0; //Or the index of the animation that I want
And the animation component will just change over to the new animation and continue handling the playback.
Now, it is perhaps a bit cumbersome if I want to think about things in terms of the names of the animations, as the code is not particularly illuminating on this front, but that can either be handled by just adding a comment to the code, or by creating a lookup that maps from the name to the index.
Either way, it just works better for me.
Additionally, as with the Puzzle Panel editor, reducing the overall complexity on both the editor end and the code end leaves me with much more room to add, without having an overwhelming amount of unnecessary complexity. For the time being, the only frame animation in the game is the player’s walking animations (which need to be redone), so I don’t really need more functionality than this.
That may also mean that this was a misappropriation of my limited time to work on the game, but time will tell.
After making the changes to the “dice face” puzzles which I described in a previous blog post, I ended up with a few edge case puzzles which didn’t work under the new mechanic, but were still within the boundary of the game’s subject matter. This meant that I would need to do some extra engineering to keep these puzzles working the same way. This caused me to confront some of the growing problems with my puzzle design tool.
Here’s a screenshot of the old interface:
This is the tool that I use to design all of the puzzles in Taiji. Although it has been perfectly serviceable, it was starting to take up a bunch of vertical space, and there are additionally a bunch of very subtle details which were starting to make it icky to work with on a regular basis. Additionally, if I want to add more functionality (which I do), it was becoming very unclear how I was going to add it, both in the interface, and the underlying code.
So I have done a bunch of under-the-hood work, which although completely invisible to players, allows me to clean up the code andrevise the puzzle designer interface.
This is how it looks now:
Although also somewhat complex, it actually has more functionality than the interface shown above, while taking up a bit less space. (Admittedly, these aren’t the same puzzle, so it’s not a 1:1 comparison, but I don’t really want to take the extra time to grab a better screenshot right now.
There are still some more improvements that I’d like to make, including basic ones like making sure all the input boxes still line up when there are disabled tiles on the panel, but overall I am much happier with the interface and the underlying structure of the code going forward, and I think it will definitely be more amenable to adding new functionality.
You may have noticed that I haven’t been posting updates for the past few weeks. My computer hasn’t been hooked up and so I couldn’t work on the game. Instead I’ve been finishing off a major move.
The house we’ve moved into really should have been cleaned before we moved into it, so it’s been a bit of a challenge to clean thoroughly with all our stuff in the house. So a lot of that has been happening, as well as repairs and general moving stuff. Still hard to relax as most things are not really “in their right place.”
I did finish setting up my computer and desk and did a short test stream earlier this week to see if the internet here was decent enough to use for streaming (in short: it isn’t). So, barring a miracle, if I do any work streams going forward, they will be more of the Starbucks variety that they were a few years ago.
Unfortunately, I didn’t really find the gumption to sit down and work on the game any more than just that short test stream. On the stream, I added a little bit of a color difference for the puzzle panel backgrounds depending on whether or not there are active tiles.
It’s a pretty small change, but it should make panels a bit less confusing for new players. I’m still not 100% happy with the look, but it’s a step in the right direction.
I’m hoping to get some more done on the game in this next week. Still lots to do around the house though, so we’ll see.
Seems like I’m writing these things on Mondays most of the time now…
Didn’t get a whole lot done over the weekend, at least not visibly. Most of the work was under the hood or maintenance. I repaired the puzzles which mix the “dice” and “dot” mechanics, after having changed the way the dice mechanics work. The combined puzzle sequence stills need a lot of work to be enjoyable to solve, but at least the puzzles aren’t actively broken anymore.
I got them working again through a small change to how puzzle solutions are validated. Previously, with the dot mechanic, whenever the color of two dots needed to be checked, the code would use an arbitrary number which specified which color dot we were talking about. (i.e. 60 = blue dot, 61 = yellow dot, 62 = red dot, etc.) The change I decided to make is to have it actually directly compare the color values of the two symbols in question. (Technically I compare an integer hash of the color to avoid the == operator overhead of Unity’s built-in color class) Directly comparing colors has a couple benefits when it comes to simplifying the code and also makes future puzzle possibilities much easier.
I didn’t end up revamping the entire puzzle panel system, because after some further investigation, there are some good reasons that I architected it the way that I did, in spite of the fact that it’s unwieldy at times. The main reason is that I’m relying on the Unity serialization system to save the panel layouts, and certain data formats just serialize more straightforwardly and quickly. One dimensional data type arrays are the most easily serializable format. So, even though it would be more useful to have a single tile structure which stores all the relevant data, including references to spawned GameObjects at runtime, it is a bit more challenging to implement than it would immediately seem.
Furthermore, serialization can get real nasty when dealing with null references, as stated on this page in the Unity docs:
Consider how many allocations are made when deserializing a MonoBehaviour that uses the following script.
class Test : MonoBehaviour
public Trouble t;
public Trouble t1;
public Trouble t2;
public Trouble t3;
It wouldn’t be strange to expect one allocation: That of the Test object. It also wouldn’t be strange to expect two allocations: One for the Test object and one for a Trouble object.
However, Unity actually makes more than a thousand allocations. The serializer does not support null. If it serializes an object, and a field is null, Unity instantiates a new object of that type, and serializes that. Obviously this could lead to infinite cycles, so there is a depth limit of seven levels. At that point Unity stops serializing fields that have types of custom classes, structs, lists, or arrays.
Since so many of Unity’s subsystems build on top of the serialization system, this unexpectedly large serialization stream for the Test MonoBehaviour causes all these subsystems to perform more slowly than necessary.
I may yet return to make some more of those changes, but you can see that the water is fraught with peril. A good approach would probably be to have two formats, one for all of the runtime code, and one that is used for serialization, but this would also create a bunch of potentially slow startup code every time the game was run in order to translate between the data formats (and there’s already more initialization code for the panels than I really want there to be)
On a humorous note, before some of the changes I made, I had this monstrosity of a line of code:
symbol = litSquares[p.x+width*p.y].GetComponent().transform.GetChild(1).gameObject.GetComponent();
And now, with some data restructuring and a few helper aliases, it becomes the much more manageable:
Bit of a short update this week, but I’ve been busy with life things (moving, putting in a mailbox for four hours), and I didn’t have much free time left to work done on the game.
A few posts back, I wrote about some ideas for revamping the “dice face” mechanic to remove the requirement that the player remember that “white = black” for every panel in order to solve it. So this weekend I worked on taking some steps there. That work was streamed live, so if you want all the details, you can check out the archive here.(although there are a few spots where YouTube didn’t like the music and I had to mute the audio)
I will still have to redesign the start of the area in order to have more interesting puzzles, but I am fairly happy with how the change went. In fact, there are now some interesting ambiguities to play with there that I can probably exploit for more depth.
Unwieldy Puzzle Panel System
I probably need to make some changes to the puzzle panel system in the game, both in order to accommodate a few of the existing puzzles which have become broken after changing the dice face mechanic, as well as for some new ideas that I haven’t implemented yet. I am pretty concerned about how to go about making these changes, particularly without fundamentally changing the way that the puzzle panels themselves are implemented.
Some of the unwieldy aspects are just the interface I use for editing puzzles, but I think the main issue is caused by a design choice that I made early on to shrink the memory footprint of the panels themselves. Essentially, each puzzle panel is just a series of 2D arrays (technically stored as 1D with width and height variables) for each thing that we might want to know about the tiles on the panel.
This was not really a big deal when there were only a few things that we might want to know about the tiles, but at this point, there are 5 different arrays for each panel. That’s not an obscene number, but I am fairly certain that to accommodate all the features I want, I will need to add 2 or 3 more arrays. That’s 8 different arrays that all have to be shuffled around separately.
At that point, it becomes pretty obvious that the data related to each tile should be bundled up. That way we can work with just one array of structs or objects that stores all the relevant data, and easily expand the structure and support each new additional feature without many unexpected code changes.
I have a few concerns with how this will affect the saving/loading code system, but it hopefully shouldn’t be too bad. Overall, it’s just a big revamping project on a core system and I never look forward to those because you end up touching a lot more code than you expected to and possibly breaking some things in the process.
A bit late on this post, but hey! Better late than never.
This weekend, I streamed some work on improving the starting area. Managed to get in a few non-trivial puzzles to cap off the area a bit better and introduce the concept of locked tiles. Locked tiles are just tiles that you cannot toggle from their starting state. Here’s a screenshot of those new puzzles ( a bit low quality cause I snapped it from the stream video):
I also changed the game from an oblique renderer back to an orthographic one. This is a bit of a subtle technical detail, but suffice to say that the change simplifies some graphical things and makes some others more complex.
I had hoped to do the first full art pass on one of the game’s areas, but unfortunately I ran into a bug with Unity’s tile-mapping system. I upgraded to 2018.1 in an attempt to fix it, but I have since been told by Unity Support that the bug is not fixed until 2018.2b, so I will either have to upgrade to the latest beta version, or wait until it gets a full release to hopefully get started on that.
In last week’s devlog post, I talked a bit about some of my thoughts relating to accessibility, particularly when it comes to deaf players. This week I’ve been thinking more about colorblindness.
Trying to come up with a set of color-blind friendly color options is quite difficult as there are several different forms of the condition. Some people have a hard time telling between red and green, and others between blue and green, and a rare few cannot distinguish colors at all.
I tried a few different variants, but many of them had problems:
The absolute best way to deal with colorblindness, of course, is to just use different symbols instead of different colors. This unfortunately is not a straightforward option for Taiji, as differently shaped symbols have different mechanical meanings. You can also use patterns instead of colors, but since the game uses pixel art, the detail possibilities are very limited.
Luckily, since most people can tell the difference between blue and yellow, those colors in combination with black and white provide a 4 color setup that will work for most people and most puzzles, at least where the only thing that matters is telling the colors apart.
However, this may still not be enough for some players, so I’ve decided to address this issue with a two pronged approach. For most puzzles in the game, I will just stick to the “safe” color palette, and the game should be accessible to many players by default. However I will have an additional assistance menu where the player can choose alternate colors if the defaults are not easily distinguished.
Additionally, there will be a set of completely color-free assistance symbols which can be enabled. These will be useful for puzzles where the player needs to know exactly which color they are looking at, or for when more than 4 colors are necessary.
Here’s my first pass at that:
Of course, the symbols themselves are subject to change, but the important thing is that the symbols combine and mix the same way that colored light does in the real world. In this case, the color model is subtractive.
For clarification on what I mean, here are the symbols again, now colored with their corresponding colors:
I’m not certain this will work for all the puzzles in the game, but it’s a start and it’s fun to think about.
So, I’ve finally finished up auditing all the puzzles in the game. Essentially, just solving them all and taking notes on what might need to be improved or removed. Overall, I think the game is in a pretty good place moving forward. There are some areas that I’m pretty happy with as is, but there is still a lot of work to be done to improve some other areas. Obviously this is just considering design work. Let’s not even get into how behind the curve I am from an aesthetic point of view.
This week, I chatted with a deaf accessibility advocate for games. This was an interesting and challenging conversation, and has left me thinking a little bit about what’s involved in making a game more accessible, and how that intersects with the design of Taiji. Obviously, I think that accessibility is an important and often ill-addressed concern, and my goal with the game is to never make a puzzle difficult for reasons that have nothing to do with its subject matter.
However, I think there is some tension between accessibility concerns and the pursuit of particular subject matter. As an example, if you want to do puzzles that are “about sound”, deaf people will unfortunately, but necessarily, be excluded.
It is easy to see why making a puzzle that relies on pure audio cues is a bad move from an accessibility standpoint. In many cases, it would be easy to make additional visual cues, and to not do so can simply be chalked up to laziness.
But my big question is, are there particular cases when not adding those cues can be justified? And if there are, what are they?
Some of my thoughts on this are a bit hard to clarify without specifically addressing and spoiling some of the puzzles planned for Taiji. Even still, after discussing the details of the puzzles with the aforementioned accessibility advocate, they did not seem particularly convinced that there was any tension other than my laziness and lack of care.
Similar concerns arose in the wake of the release of The Witness. There are some puzzles in that game which people who are color-blind or hard of hearing will have trouble with, or may simply find impossible without just looking up the solutions. Because of this, the designer—Jonathan Blow—has been called callous, “ableist”, or at best unconcerned about accessibility. The last one is particularly strange, considering the game received a PC patch to add a click-to-move mode, and nearly all of the puzzles in the game—including many that use color as a cue—are designed to be as accessible as possible; symmetry puzzles that care about colored hexagons using cyan and yellow, for example. In my last point of defense of Jon Blow before I move on, he has been quoted saying that he wanted to ship the game with a puzzle which only color-blind people would be able to solve, however in this case he was hamstrung by the the poor color consistency of most display technology.
So, what is the reason to make those kinds of decisions? To create puzzles which by their very nature exclude certain people from fully enjoying your game? Jon Blow says it is because the puzzles in The Witness are all “about things.” I agree with this sentiment, but it perhaps requires a bit more clarification to even make sense.
In many puzzle games, the “point” of the puzzles is essentially to be a challenge. The puzzles are meant to be hard for the player to solve, and probably fun as well. In games like The Witness (or Taiji, for that matter) the point of the puzzles is significantly subtler. The puzzles are intended to be interestingand, about something real. By “real” I mean that the subject matter is, at best, not confined simply to the game. The thinking that a player will do when solving the puzzles can be taken with them back into the real world.
It may seem a bit callous, but it should go without saying that both sound and color are phenomena that really exist, even if some people cannot experience them.
This can seem to lead down a path of reckless disregard for other people, so I think it is also very important to emphasize that what I’m talking about here—both in my own case and the case of The Witness—are puzzle games.These are games that, by design, will exclude people who are simply not intelligent enough to complete all of the puzzles in the game.
Perhaps all of this can just be seen as a long elaboration intended to serve as an excuse for my laziness, or “ableism”, or perhaps some other unidentified flaw of character. However, I still have not addressed the core issue:
What am I going to do about accessibility?
Currently the plan is to make the game as accessible as I can. When puzzles involve the use of color for separation, but are not explicitly aboutcolor, I will endeavor to choose colors that will work for as many people as possible for that purpose.
But what about when puzzles areexplicitly about those things? What about puzzles about sound, for example?
In these cases, I will primarily design the puzzles with the intent of pursuing the subject matter that interests me. If I have to choose between a puzzle which can be made accessible or painting myself into an inaccessible but more interesting corner, I will most likely choose the corner.
However, I also intend to provide some level of assistance when possible. This, in itself is a tricky proposition, because I do not simply want to condescend to players who are using the assistance options. In essence, adding accessibility seems as though it will often amount to designing an entirely different set of puzzles. The puzzles therefore must be interesting in their own unique ways, and must endeavor to be analogous to, and at least as challenging as, the inaccessible puzzles.
Perhaps this will not be enough, or not even be possible. After all, I am mostly opining here without having fully designed any set of puzzles like this. But I think this is the best way for me to balance these two ideals: accessibility and truth.
I want to clarify a couple things: What exactly is the difference between a puzzle which is about sound or color and one that simply uses it as a cue. And why do I think that the former cannot be made accessible without simply designing a different set of puzzles?
To do so will require spoiling a couple puzzles. The Witness is a hugely broad puzzle game, so I can actually find examples in both the positive and the negative without talking about any other game.
Spoiler Warning: If you have not completed the two areas shown below in The Witness, then avoid reading further.
So, in the example of puzzles which simply use audio as a cue, but are not really aboutsound; we have the example from The Keep. The third hedge maze puzzle in the front courtyard must be entirely solved by listening to the loudness of your footsteps while walking on the gravel pavement inside it. The maze on the panel matches the shape of the hedge maze which contains it, and particularly crunchy spots found while walking through the physical maze denote an area to be avoided when drawing a corresponding path through the maze on the panel.
The reason that I say this is not a puzzle about sound, is that it would work just as well if you simply wrote out separate captions for the footstep sounds. The softer ones being written as “crunch“, and the louder ones being written as “CRUNCH“. The puzzle would essentially work the same.
It is important here to note the difference between subtitles and captions. Subtitles only show you spoken dialogue, whereas captions will also give you a textual indication of important audio cues.
The actual puzzle here is about noticingthat the loudness of the footstep might be important, and then figuring out in what way. The argument against accessibility here is that hearing players are inundated with the sound of their footsteps throughout the whole game, and so this is a subtle thing to notice. Consequently, captions would be much less subtle.
I think this is actually not a very good argument: First, it isn’t really thatsubtle, as the important footstep sound is unusually loud here. And secondly, if the consistency is really that important, just put captions on all of the footstep sounds in the game. Make them small and unobtrusive if you have to.
Sadly, The Witness does not support captions at all, and therefore this puzzle is impossible for deaf players without simply looking it up.
So, in the positive example, we have the puzzles in the Jungle. These are puzzles that are actually aboutsound, or more specifically: about hearing. This will be harder to explain, because the puzzles themselves are much more subtle.
First, if you need a refresher on the content of these puzzles, I actually have an analysis video on the first half of this area, in which I discuss some of the subtle details involved:
Now, I want to bring the attention to my specific point earlier. Why do I think that these puzzles cannot be made accessible without simply making a different set of puzzles?
In this area, the essential task that the player is doing is listening to some bird songs, and transcribing the different pitches of the notes onto the panel. One could easily imagine some sort of analogous visual cue: a series of mechanical birds which all chirp in time with the notes, and are set on branches of varying height, with the height of the branch corresponding to the pitch of the note.
This type of cue would in fact work quite well, but only for the first three puzzles in the sequence. Past that point, the puzzles begin to play with both the particular difficulty of distinguishing different notes by ear, and the way in which we focus our attention on certain sounds by filtering out others. Both to our benefit and our detriment.
Perhaps again, there could be some analogous changes to our cues here. Perhaps the birds start out in linear order as they would be on the panel, but they begin to be shuffled up, and the player must watch the order in which they chirp. Perhaps the branches which the birds are situated on begin to blow in the breeze, and so it is more difficult to tell which bird is supposed to be higher. Perhaps there is a branch which is broken and the bird has fallen onto the ground. Perhaps there are birds which are not situated on branches at all, and they are irrelevant. These could be interesting ways to evolve the sequence, but what I am trying to argue is not that the puzzles cannot be made accessible, but that by doing so, they are now puzzles which are fundamentally about something different.
They are no longer puzzles about sound, and now are puzzles about spatial relationships between moving objects.
Does this make these accessible puzzles bad? No. But it does make them different puzzles.
The issue itself I’ve talked about in a previous blog post. You can read all about the problem there, but to briefly recap: I have a mechanic where depending on if a symbol is white or black, this indicates whether the tile containing it should be lit or unlit:
The correct combination is “black means lit” and “white means unlit”, but the issue is that some players find the opposite to be more intuitive, for perhaps obvious reasons. This means that those players will continually input solutions that are technically correct, but are logically reversed from one that the game will accept.
This is a particularly nasty issue, and solving it seems to require a compromise of aesthetics or intuitiveness. Again, I’d suggest you read the original post if you want to understand more, but in summary: none of the possible aesthetic solutions I could think of really worked well.
So why do I think I have a solution now?
Partly, I think I mistook the domain of the problem. I believed that what I had was an aesthetic issue, and so I was trying to solve it in the aesthetic domain. But in fact, I believe that the core of the problem is mechanical.
See, the dice face mechanic has two aspects. The first one is the one that we have already mentioned: a black symbol means that a tile should be lit and a white one means that it should be unlit. The second aspect, I don’t want to spoil here, so bear with me if I’m being vague (although I have talked about it previously on this blog).
The solution is that I need to decouple those two aspects. If I simply remove the lit/unlit requirement from the mechanic, it solves most of the problems. The only downside that I can see is that I will have to redesign the early puzzles in the area (about the first 10 panels or so), as those panels mostly focused on this aspect of the mechanic. For the later puzzles, I believe I can make most of them work by using the separate mechanic of locked tiles (tiles on the panel that the player cannot toggle from their starting state) in order to force a certain dice face to be on or off.
In some sense, this is a realization of my failure to enforce orthogonality (one of aesthetic virtues outlined in this talk, which I also share) between the dice face mechanic and the locked tiles. In fact, I mentioned this exact possibility in a previous post about orthogonality:
Second, I felt like the “is it lit up or not” aspect was an additional point of overlap with the dice faces, which already care about being lit up. It may come to a point where I want to separate out that aspect of the dice faces themselves, but at this point, I’m letting them care about what’s lit up or not, so it seemed like the new mechanic shouldn’t care.
So when I said “win-win-win”, what are the 3 wins here?
Removes confusion. By simply locking the tiles whichever way they need to be for any given puzzle, I remove the cognitive overhead of the player having to remember which is which, and put the focus on the actual content of those puzzles.
Removes busy work. At the moment, a skilled player starts one of these panels by immediately turning all the black marked tiles on and all the white marked tiles off, because no matter what, the solution will always require them to be that way.
Larger possibility space for solutions. The fact that, by default, the tiles no longer care about whether they are on or off, allows the player to have more flexibility in the way that they choose to solve a puzzle. This also gives me as a designer more room to play with the player’s expectations, and create puzzles where the solution may require some thinking about which colors to choose.
There’s also an additional and more subtle win across the rest of the game, in that as long as the dice face symbols were always suggesting that “white means black” and “black means white”, there would always be a bit of incoherence to other puzzles in the game that might simply require the player to match colors.
All the way back in the second devlog update, I mentioned that “the best ideas are the ones that solve like 3 problems at once and in hindsight just seem stupidly obvious.” Admittedly, I haven’t done a full pass on the entire area, so I may be putting the cart before the horse, but I feel pretty strongly that this is another example of that phenomenon.