
This one-month project persists in being a not-one-month project, and I’m surprisingly fine with that. What drove me crazy with EverEnding, and which frankly still hangs over my head to some degree, is not knowing when or if it will be done, or really knowing how much progress I’m making in the overall scheme of things. That specter persists in this project, but since the implicit demand of the art style is so much simpler compared to the high-detail art I was making for EverEnding I feel much freer to pursue ideas without being terrified of getting completely derailed.
Additionally, I’ve been doing a lot of work on understanding how I – well, how I do work. I’ve gained a much greater understanding — over the last decade, but especially over the last 6 months — of what my strengths and weaknesses are, what my limitations are and when I can aspire to exceed them, and how to best cooperate with myself to achieve my goals. The most recent part of this process is a system I’ve devised this month which is somewhere between a form of time management, a form of accountability, and a form of gamification. Maybe I’ll create a snappy name for it at some point, but right now I just think of it as the token system. I bought a bunch of little glass blobs in various colors from a craft store — similar to those I and my friends used to use as counters playing Magic: The Gathering — and a few nice-looking containers of different colors. Whenever I work on something for a half-hour I add a token to a container, with the color of the token and container representing different pursuits in different areas of my life. So, for instance, when I’m working on the game I add a green token to the clear glass for each half-hour I work on tech/code and a pink token for every half-hour I work on art/level development.

This serves several purposes. First, it helps me keep track of how long I’ve actually spent on something, rather than just how long it feels like I’ve worked on it — which of course can vary based on my mood and how well I think things went. Second, a frequent tripping point for me is forgetting some particular job or task I need to do or being unsure what to do next and spending a lot of time and energy fretting about it before coming to a decision — but, since all of these tokens conceptually represent either a pending or complete task, I can just set tokens representing whatever I expect to accomplish the next day on my desk as a reminder to actually do it. Third, the tokens, and the act of putting them into the containers, serve as a concrete representation of what I’ve done, helping solidify it in my mind as something real and which happened – which is sometimes easy to forget when all of the work I do, being largely digital, can feel so ethereal.
While this is all very helpful, it has also reinforced and reified the understanding that game development is hard and it takes a long damn time to get anything done. I am pleased by my progress so far on this project because every time I look at the game it seems to be significantly further along, but I’ve still got a long way to go! Realizing this, it’s clear now that the way I was working on EverEnding, where so often it felt only marginally further along after another month of work, it was never going to get finished. While I still intend to go back to it, when I do it’s going to have to be with a plan on how to make the project feasible.
In the meanwhile, this is the DevBlog for a completely different project! All of this month’s work centered on building levels — some of it very directly, creating tile art and placing those tiles in the environment, and some of it a bit less directly, developing new tiles and styles of rendering them. One of the most foundational developments was creating exits for traveling between map layers — that is, when there’s a door or path visible in the background, it’s now possible to enter that door and go into another room that occupies the same space as the room you’re in but exists on a different layer of the map. It’s a bit of a pain to set these doors up right now, requiring manually creating a matching room and placing a paired door on the other side while the Unity Editor spits null reference errors, but it’s good enough to work with for now — and, frankly, given how much time is necessary for simply placing rooms compared to all the time it takes to add detail to them, it might not be worth the effort to make that work quickly or more intuitively (a thought process which I should perhaps have applied when developing the cursed map editor). The inverse problem, appropriately enough, seems to have emerged with a special effect I’ve been developing: Reflection tiles.

I really wanted to have some sort of reflections for both thematic and aesthetic reasons, but a lot goes into a reflection — and, while in many ways the process of reflecting is simpler in a 2D game, it also tends to be more abstract and less generalizable: Since the actual path of travel of light only exists in the artist’s mind, rather than having a direct analogue in the game’s rendering engine, there’s no way to create a generalized solution for all reflections. Because of this, I’ve created a shader which reads a texture containing all the screen-space objects getting reflected and transforms it somehow, based on the coordinates and color of the tile, and renders out that pixel. Most of this isn’t that complicated — I can just use the red and green color channels to offset the reflection by x and y pixels, respectively, which works fine for background reflections — but when it comes to a reflective wall, like a mirror or glass building, or reflective floors like shiny tiles or water, things get tricky because in order to reflect plausibly on these we have to flip the x or y coordinates around the reflective edge. Furthermore, if I want to simulate perspective at all I need some way to squash and stretch the reflection. I ended up packing all of this information into the blue channel of the tile color: 1 bit for x flip, 1 bit for y flip, 3 bits for x scale and 3 for y scale. This is programmatically functional, but the problem I ran into was generating actual tiles for use by the shader. It’s very difficult to visually parse the differences in color and what they mean even between the red and green channels, and completely impossible for the blue channel, and it was also difficult to get any sort of real-time feedback on what the tiles were doing, what they were reflecting and how, in the editor.
I eventually came up with a solution of of sorts: I overlaid a coordinate grid on each room, so you could see where each tile was on the grid and see, in reflections, what part of the grid was being reflected. This was an improvement, but actually placing the reflections was still a trial-and-error pain in the ass, plus the huge number of tiles I had to create to represent each different kind of reflection has started to slow opening the project significantly. The next step, I’ve determined, is to largely phase out special reflection tiles completely (except in the case of animated reflections, such as water) and create a custom tilemap brush, allowing the user (me) to manually set reflection parameters and then automatically pack that into a color for the shader to interpret. This probably won’t be too difficult, but I’ve learned to avoid making assumptions about that when it comes to Unity’s godforsaken Tilemap system.

The above paragraph was written at the start of the week, on Monday. It is now Friday and I regret to say that my reservations were validated. The entire function of a reflection brush rested on the ability to set tile colors: This is a capability that is nominally present in Unity’s Tilemap system, but seems to be implemented very sloppily and inconsistently internally. While I have indeed created a brush that places a tile, packs the reflection information into a color and uses it to color that tile, two huge issues persist: One, the preview for any changes made is completely non-functional, making it much less useful for exactly the kind of fast feedback about what changes I was making that it was intended to achieve. Any time a brush preview is used, it sets the color of underlying tiles to white permanently, seemingly a fairly severe bug which I’ve now made the Unity team aware of. Secondly, whenever an undo is performed on a Tilemap it seemingly reverts every single tile back to white, regardless of whether it was even touched by the undo, an even more severe bug than the previous and one which, regrettably, probably makes it not worthwhile to pursue this reflection brush component further until it is fixed. The good news is that after languishing for quite a while, Unity seems to be taking steps to fix issues with the Tilemap system, so perhaps there’s hope for this getting resolved.
The bulk of the work accomplished over the last month has been in creating and placing tiles. There have been a few other stopping points of the sort I mentioned last month, where I had to spend a while thinking about how it could actually make sense to represent a plausible space using tiles. The logic of a 2D space presented this way can get very odd at times: If you think about how a player would move in most 2D games, expanded out to a 3D space, it would involve a lot of weird sideways jumps around corners, through surfaces, choosing unnecessarily tricky parkour routes rather than taking simple detours around things, and so forth. It’s an abstraction that is both absurd and fascinating, as elegantly compelling as pretending the floor is made of lava, but it can make the job of artistic representation quite tricky. Most such games take place in large open rooms, warehouses full of crates, which make it relatively straightforward to map a grid-based 2D world onto a reasonably plausible environment. The hotel section, the first major challenge section of the game, is fairly close to this ideal scenario: there are a lot of boxy rooms with a number of plausibly blocky things placed in them.


However, while they seem like they’d operate on similar principles I realized that the apartment areas I developed early on were using way too many tiles and being way too inconsistent with their representation of the space to be satisfactory in the long run. In setting out to revise these, I realized that my approach to tiles was inconsistent: Some tiles only represented one edge, others represented a whole block, and there wasn’t a lot of logic to which was which. I kept working on it until what I eventually realized was that in 2d platformers there are broadly two different types of collision tiles: bounding tiles and obstacle tiles. Bounding tiles represent the edges of the game space: Walls, floor tiles, soil, cliff faces and such. Obstacle tiles represent objects encountered within that space that need to be navigated around: Girders, boulders, cars, crates, etc. This maps to how we interact with objects in 3D space: We can’t see what’s past the walls around us, though we might be able to make an educated guess, but something like a table we can walk around and see all sides of — even if it blocks our path, we understand the shape of the object in its entirety. Thus, bounding tiles only show the edge of the object, as with the various rock and wall tiles visible in these screenshots, while obstacle tiles show the entirety of the object, as with tiles like the vents, counters, pillars and so forth. There are several exceptions even in this relatively small sample size of tiles, but it’s a helpful principle to keep in mind.


This knowledge was invaluable to me, and though it seems like common sense that many game artists must know I had somehow missed learning it anywhere before, or at least hadn’t retained it. Soon, though, I ran into a whole other artistic challenge: Sure, it’s not that difficult to represent human-made spaces using a tile grid, we tend to build along grid-like lines anyway, but what about representing nature? Well, in fact this space wasn’t so much nature as a city park, an interstitial zone between the starting apartments area and the hotel area, but I still had to figure out how to make trees that the player could plausibly interact with and grass that felt realistic and aesthetically interesting without cluttering the area. I had to redesign the tree branches and grass tiles several times, but in the end came up with a style I really like.


Finally, lumped in with all this other stuff I created a number of animated tiles — mostly for water, but also for fiery light sources and smoke. I ended up doing most of these animations at very low frame rate, a frame or two a second, especially for pure background elements like water. The animated tile provided by Unity is bafflingly useless for anything past the most straightforward usage, providing a way to randomize the speed of the animation (which, to be frank, looks like pure garbage at anything but the highest frame rates) but no way to randomize the starting frame. Fortunately, they did make this animated tile class very easy to understand and modify, so I took a day to create a version of it with a randomizable starting frame, along with the option to randomize its orientation in variable ways — so, for instance, I could paint an area with water tiles that all started on different frames and were randomly horizontally flipped. This all may have been overkill, but the main thing I wanted to avoid was the player walking into a room where all of the torches were perfectly synced frame-by-frame, where the ocean moved like a marching band — though these may be interestingly uncanny effects to play with in certain situations.
The next month will, I expect, proceed largely as this one did: Areas will continue to get built out, though I’m running out of room to build in this segment of the game I’ve designated as the starting area (probably about 1/4 to 1/3rd of the main map, as I have it planned now). I should probably start adding actual interaction to these environments soon: Enemies, NPCs, pickups, and so forth. Better to have a sense of how they play and revise that towards where I want it to be than to try to engineer everything up front and have to discard a bunch of work that doesn’t end up fitting. I hope that by then I will be at least close to the vertical slice I keep talking about.