Week 10 marks an exciting first for my Game a Weeks; happy collaboration. Please indulge in Go Right:
The controls are explained in-game. If you absolutely have to mute the audio, press the M key.
I’m going to start this post off by giving a huge shout out and thank you to the four other people who contributed to the game.
Tom Lamey is the enigmatic hero responsible for the lovely character design and great spritesheets that bring the protagonist to life. He also advised me on the general look of the game
For the music I counted on the talents of the insatiable Jack Drewry. He brought together a couple of rag tag musicians to aid him, collectively they’re known as Squid Tooth, but separately they go by their birth names of Jack, Laurie and Rowan.
I hope you agree that these four all helped raise the bar on my games with their contributions. I’ll talk more about how it all came together below.
I wasn’t planning on doing anything special this week until I had the conversation with Jack in which he offered to provide the music. I figured that together we could probably come up with an overall better end product, so I agreed. I then approached Lamey, as he and I had previously discussed the idea of him doing the art in one of my games, and he was willing. So by the end of Monday I already had a team together. I just needed a concept to match.
As I had Lamey on board for the art, I wanted to do a platformer so he could design and draw a character. Additionally, I had yet to do a platformer in the Game a Week challenge so it was a good opportunity to rectify that. I wanted to come up with a gameplay twist as well, to make the game a bit more compelling and really squeeze the maximum potential out of my teammates. Thus was born the camera-flip gimmick, inspired a little by Fez, a little by Fru and a little by Super Paper Mario, all of which play on alternate worlds being hidden by some change in perspective.
I ran the idea of having two worlds by Lamey, asking if he would be able to provide two alternate versions of the sprite sheets. He would. I ran it by Jack, asking if he would be willing to produce two different-but-similar tracks; he would. To reassure myself, I came up with a couple of scenarios on paper that could use the “different platforms being revealed on different sides of the camera” gimmick and, confident that more such level design opportunities would spring up once I had built the foundations of the game, set to work.
I hit a couple of huge hurdles immediately. After getting a basic version of character control implemented, I started work on the camera. I figured it’d have a couple of quirks but would be a fairly short job. This was a false assumption. The camera was one of the most difficult and finicky parts of the game to get right, and ate around a day and a half of development time. I’ve never programmed a sidescroller camera before, and it turns out they are a lot of hard work. The camera I ended up with is an amalgamation of different bits and pieces, and I think it’s passable, but definitely not perfect. On the plus side, I did end up saving a bunch of great resources talking about cameras from a design perspective, which I found very interesting and is definitely something I’m going to be thinking on how to improve in the future.
I initially wanted to have the camera lead the character, offering a view of what was in front. But it soon became apparent this wasn’t great, and the distance the camera leads got shorter and shorter as development went on. In the final product, she’s around the middle of the screen most of the time.
A big step in getting a nice working camera is implementing the deadzone that the above linked resources mention. I show this in-editor with a big green line around the character:
As you can see, the camera only moves once the character leaves the deadzone, highlighted by the green line. If the character stays still for over a second, and she’s within bounds, I move the deadzone over her then as well.
The second most influential aspect of the camera movement is trying to make it as lethargic as possible. Ideally, the camera will move the least amount it is possible for it to move, while still providing an appropriate view of the area. One way to achieve this is by making the camera move vertically only when a player lands on a platform that is at a significantly different height. This can be seen in one of the starting areas of the game:
Alternatively, if the character is heading off screen, the camera moves to keep her on-screen. This only occurs during long falls.
To wrap up the camera talk, it boils down to this: the horizontal and vertical movement of my camera are handled completely separately. They are governed by different rules and move at different speeds. The character never leaves the view, and the camera never cuts from one place to a completely different one in adjacent frames. Hopefully, this all leads to a natural feeling camera.
The flip mechanic, surprisingly, was one of the easiest things to implement. I simply have a parent object at the same depth as the character and level terrain. The camera script is on this parent object, which rotates 180 degrees when the flip occurs, and therefore sending the child camera with it:
The rotation is controlled by a Lerp, the duration of which is sped up over the first few flips, so that it is clear initially what is happening, but later the flip does not intrude on the player by taking too long.
A continual source of worry was the character control itself. As a platformer, I want the player to be confident in making jumps and navigating thin platforms. My initial attempts resulted in a very skiddy character, which is exactly the opposite of what I just described. In addition, my jumps were extremely floaty. The code for the character was initially quite intuitively physics based, with functions programmed how you’d expect things to work for real; going left or right adds a force left or right, jumping was simply an impulse. As development went on the character controller became slowly more convoluted; I have a function written purely for dampening her movement the right amount when the player lets go of input, as no matter how much I tweaked with friction I couldn’t get it feeling good. Likewise, jumping is initially an impulse force upwards, but if the player holds onto the button a little longer, a continuous additional force is applied. This allows you to make tiny hops or great leaps depending on the situation.
Little tweaks like this litter the code, and make me very curious what the code behind Mario or Sonic’s movement looks like. Rest assured, much of the following week will be spent playing those games and inspecting, in detail, how the characters move and how the cameras follow them. I’ve got to get it right one day.
In order to manage the two different worlds, which I refer to as the right and left worlds, I have a DualWorldController, which tells everything when to change worlds. Every object that inhabits either world has a DualWorldProperties component, which stores which worlds the object is present in, and any other properties needed for this. For example, platforms specify a sprite for the right world and a sprite for the left world. Text specifies its right world contents and its left world contents. In its Start function, each DualWorldProperties component adds itself to a list maintained by the DualWorldController. When the controller wants everything to flip, it simply goes through the list and calls each of the properties’ Flip functions. Simple.
The character is handled a little differently, though, as she’s a unique case. She’ll always be present in both worlds, and all that needs to change are her representative sprite sheet and the direction of her controls. The latter is handled by querying the static InRightWorld bool, so she doesn’t even need that set in her Flip function.
Her sprites, however, are handled purely by her animator:
As she only has three states, this solution works perfectly at this scale. On each side is a standard state machine connecting the idle, run and jump animations. Each of these is also connected to its alternate world counterpart. I haven’t had an opportunity to work with animation since my first Game a Week, so this provided a nice refresher on the system and I’m definitely more confident with it now.
One part of Unity I had yet to explore was particle emitters. Play the game for even a second and you can see that’s no longer the case. The two effects, snow in the right world and warp speed lights in the left world, are very similar in set up, and use the default particle material. Despite this, the effects add a bit of personality to each world at very little effort exerted, so I’m a big fan. I’d be interested in trying them out in different scenarios, like having dust rise from the character’s feet or using them to create a fancy projectile. Something to keep in mind for future projects.
Themes and Collaboration
But why snow in the first place? Lamey’s initial sketches showed the character pretty much how she ended up, including that big furry hat. I shared the early sprites with Jack, to give him a bit of direction, so that we could keep the design cohesive throughout. He later got back to me, stating that for the two different worlds he was thinking of doing an acoustic track for one, and a more electric track for the other. I fed this back to Lamey, and we started experimenting with more neon colour schemes for the level and a neon character too.
So the development process turned into this great feedback loop, ending in a very sturdy end product. Nothing feels particularly out of place, which was my big worry; it was entirely possible that music, art and game design could have gone in completely different directions, but I think each compliments the other. The relief I felt when it all came together like this was substantial.
Honestly, the snow particles were done on a complete whim. I decided on Saturday night to mess about with particles, as my brain was tired from putting together the level. As I said, I’m really happy that I decided to do that. I had this video on in the background while I messed around, which was great, as it explains each component and what they can be used for.
The level design was the final piece of the puzzle. I put the entire game world together over the weekend, adding in lifts and moving blocks Sunday afternoon. After putting together the first half on Saturday, I felt pretty pessimistic about my ability to make the gameplay compelling outside of ‘jump from one platform to another while switching worlds’. I jotted down a bunch of game ideas, including having buttons and switches that affect things in this world or that one, or objects that act differently in the different worlds. I even contemplated having the ability to flip the camera on the Z-axis, reversing the gravity, but this would break the game as I have it set up now; I’d have to redesign the levels with that particular mechanic in mind. In the end, I stayed conservative, implementing only the lifts and moving platforms, that either move in opposite directions in different worlds, or disappear altogether. As I made the maze-room on the second floor of the level, it became clear that this had opened the game up a bit, and I could relax somewhat after that.
Overall, I think this game shows that the concept has potential, and it’d be interesting to explore in the future. I’m a big fan of puzzle-platformers, Braid and VVVVVV coming immediately to mind, so if one day I could work on a concept as solid as one of those, I’d be a very happy bunny. The extra juice added by having some proper art and music involved is totally undeniable as well, so I’ll definitely consider drafting in some more victims in the future.