DevLog - The Making of Matchstick Relay
Welcome!
Hello and welcome to the DevLog for Matchstick Relay! While Adam and I developed the game, we kept track of everything we did here so that you, the reader, could see exactly how this game came to life. Enjoy!
Game Idea
This game was created for the Speedy Game Jam #1. This jam had a focus of "speed" and a theme of "match." The game is a platformer race where the Player controls a sequence of burning matches. The matches must reach their proximal match before burning out or the run will end! It incorporates speed because it is a relay race, and it incorporates the theme because it involves matches.
First Mechanic: Burning
Matches burn! And the most important mechanic – the one that makes my game unique – is the match burning mechanic. I began by getting a basic match made from a sphere and a cube.
Next, I created a script called “BurnComponent” that will handle all the match burning mechanics in the game. It consists of public fields for burn rates of both components, the matchstick and match head transforms, and public box collider field for the matchstick collider. It also has a boolean to keep track of if the match’s head is completely burned up, and a delegate void called “BurnedUp,” which is invoked when the matchstick is completely burned. I will use this delegate later to signal a loss.
In the BurnComponent’s update function, I scale down the head at the given rate until it is burned up, then I begin to reduce the matchstick component’s localscale.y property. I also reduce the y component of the matchstick’s box collider, so it consistently falls and gives the appearance the match is shrinking. The result is a nicely burning match, with configurable burn rates for both parts of the match (the head will probably burn a bit faster than the stick).
Match Movement
The next priority is making the matches move, so that they can complete the platformer level. I think it would be interesting (and humorous) to make the match move only when its off the ground. This creates a frequent jumping mechanic, so the match hops arounds frantically trying to reach its next match friend.
To do this, I leveraged Unity’s new Input system (I want to support gamepads!) and the Rigidbody.AddForce method. All input listeners (callback contexts) are handled in the new “MatchControllerComponent” script. All methods related to jumping and z-axis movement are handled in the new “MatchMoveComponent” script.
The only tricky part of this implementation is allowing the player to “queue” movement. Meaning, if they hold down the positive input, then jump, they should launch at an angle. I achieved this by creating a class variable called “moveIntent” that updated with the Move method regardless of whether the player was grounded. Then, I modified the Jump method to also add a movement force based on moveIntent. Now, when the player jumps, and its moveIntent’s z component is non-zero, it will launch at an angle.
Moving Platforms
Next, I wanted to start creating an interesting environment for the matches to traverse when relaying. Moving platforms will add to the variety of the level and test the player’s basic prediction skills.
To implement moving platforms, I created an empty game object, then parented a primitive cube to it. I added the script “MovingPlatform” to the parent. Then, I added three empty game objects (transforms) to the parent, to represent the points the platform will move between. The “MovingPlatform” class has public fields for these points in an array.
The method I used to implement movement was a basic feedback loop. I got the idea from a post I cannot find in a quick Google search. If I find it again, I will be sure to update this entry. This feedback loop takes in five parameters:
- target position – current destination of the platform
- max velocity – maximum velocity at which the platform can travel
- “toVel” – a conversion factor between distance delta and velocity
- max force – maximum force that can be applied to this object to reach its maximum velocity
- gain – a feedback parameter to dictate the accuracy of the stop behavior
Together, through an algorithm in the FixedUpdate, these parameters allow the platform to constantly reevaluate how close they are to their next target, and speed up or slow down the platform accordingly.
Chain Reaction
One main mechanic of this game is to pass the flame from one match to the next. This is what makes it a relay race! To achieve this, I amended the “MatchControllerComponent” module, first to include a boolean to track whether the match in question should be currently controlled by the player. I then added an “OnTriggerEnter” function, which reacts only to other matches. Upon this collision, the new match is set to the current match, and the old one is flagged as “isPreviousMatch,” to make sure the flame cannot be passed back. Additionally, the burn behavior (the rates at which the head and stick burn) is also transferred to the new match. The result is the player losing control of the old match and gaining control of the second, and then second starts burning!
Winning and Losing
I set up a basic Game Manager script to track whether the player has lost or won, depending on events in the game. In Entry 1, I anticipated this and added a delegate to the MatchBurnComponent that signaled when the game had been lost (i.e., when the match had burned up entirely before passing on its flame). I subscribed the new Game Manager to this delegate, and had it print out “You Lose!” to the console for now.
What do matches want to do with their flame? Light a bonfire of course! For the winning mechanic, I created a bonfire out of primitives and gave it a box collider. Again, in the “OnTriggerEnter” method of the “MatchControllerComponent,” I checked to see if the other collider was indeed a bonfire via tag. If so, we invoke a new delegate (called “BonfireReached”) to signal the Game Manager that the game has been won. The Game Manager prints out “You Win!” to the console for now.
Game State and Timer
Another aspect of the game is getting to the bonfire as quickly as possible. This can be tracked using a timer, which will be dependent on game state. I created a simple “TimerManager” class that starts and stops a timer based on game state and emits a signal any time the time changes. I created another simple “UIManager” class to subscribe to that event and update a UI element on the player’s HUD to depict the current time.
With winning, losing and a timer, I need to start tracking game state. I don’t want the timer running if the game hasn’t started yet, if its over, or if the player is paused. One way to manage this is to create a state machine for the game. To do this, I created an enum in the Game Manager class with the following states: Boot, Pregame, Running, Paused, Postgame, and Default. Boot will be used later for scene transition management. I then created a GameState enum field in the Game Manager, and set it up with a property to invoke another delegate whenever GameState is changed, passing along which state the game is now in. Now, things like the timer can behave accordingly by pausing its counting during the pause state, and resuming it when the Game Manager transitions back to running.
Solo, Coop, and Versus
I want the game to be playable in three different modes: solo, coop and versus. I divided the game in to three scenes, one for each mode. I also had the Game Manager determine which mode it was in based on scene name, for testing purposes.
In solo mode, there is one camera following the player, and that camera is passed off to each match the player encounters along its journey. Like a relay race, but the camera and the fire are the baton. Pretty simple. The player aims to get the lowest possible time to complete the obstacle course.
In Coop mode, I still want the string of matches to pass a camera and fire along, but this time, I want the players to alternate control of the matches (red for player 1, blue for player 2). Players aim to get the lowest possible time to complete the obstacle course as a tandem.
Finally, in Versus mode, I want the two players to be controlling their own string of matches simultaneously, with two cameras, that still follow the “Chain Reaction” camera passing behavior. In this game type, time is no longer kept, it is about who can reach the finish line first.
Multiplayer Input
The result of implementing these game modes leveraging the new Unity Input system is a little messy, hopefully the source code can help supplement this explanation. To achieve this, I had to wrestle quite a bit with the new Unity Input system. A huge thank you to Broken Knights Games, who’s methodology I adapted to fit the needs of my game. Here is a link to a very helpful video for trying to implement this kind of thing:
Broken Knights Games: Local Co-op in Unity using the New Input System - Tutorial
https://www.youtube.com/watch?v=2YhGK-PXz7g
To start, the messiness of this implementation results from what I see as a shortcoming in the new Unity Input system. That is, ID numbers are assigned to devices as they are added to a scene rather than when they are connected to the game. The result of this is the necessity to instantiate new controllers before you know precisely what they will be controlling, especially if you want to use split screen. For example, in this game, I plan to have 10 or so matches lining the obstacle course, so that the player can have a bit of fun getting to the bonfire. I do not want to instantiate each one at run time! It takes away from the aesthetic. Instead, I want to dynamically assign controllers to matches as the player takes control of them. I have limited experience with the system, but accounting for this quirk is the reason this implementation took me several hours.
So, the crux of this implementation relies on two things: the “GetCurrentMatch” method in the MatchControllerComponent script, and the Game Manager’s GameType enum.
The MatchControllerComponent is no longer assigned to a specific match, as this is not conducive to the input system’s way of handling managers. Instead, the MatchControllerComponent is connected to a new GameObject called “PlayerInput,” which has a component of the same name from the Unity package, and it is stored as a prefab. Since it must be a prefab, I had to get creative telling this newly instantiated object what it should be controlling. Enter the GetCurrentMatch method. It takes in a playerIndex integer – either 0 or 1 depending on if Player1 or Player2 is getting a match. It listens for a flame being passed from a MatchBurnComponent, and it expects that event to tell it which playerIndex is requesting a match switch. It then searches the scene for all objects that have a MatchMovementComponent (I know, I do not like it either). From the resulting array, it selects only MatchMovementComponent that meets two conditions:
- It is a current match (Which I assume is unique for each player based on my “Chain Reaction” mechanic described in Entry 4)
- Has the same playerIndex of the requesting player.
Upon initialization, the GetCurrentMatch method is called using the playerIndex of the controller being instantiated, so that the starting match can be located. After that, it dynamically listens for which player gets to which match and handles accordingly, moving the player-specific camera along the string of matches. This handles the Solo and Versus game mode very well, but it struggles with the Coop mode, because the coop mode has one camera being shared between two players. It’s quite a headache…
The solution was to implement an enum in the Game Manager to track which mode the game is played in and amend the GetCurrentMatch function to only handle the camera exchange when it is not in Co-op mode. We allow the fire-passing logic to also pass the camera in the Co-op mode. Additionally, for Co-op, I had to create another PlayerInput prefab, this time without a camera, and I had to disable the PlayerInputManager’s split screen functionality. Finally, I had to assign the main camera to the first match as a starting point, so the match could pass its camera transform along as intended.
The implementation works well. I noticed a bug I believe is with the Unity input system. When the game shuts down (when I exit Playmode), it seems that occasionally the player objects are unloaded before the InputManager. When the InputManager has split screen enabled (in Versus mode), it tries to update without the player’s cameras and throws an error. This seems to only occur on shutdown, and I tested it with scene transitions instead to make sure it would not break the game. It seems to be stable but I will keep an eye on it as I go along.
Game Maker’s Toolkit
As I designed the level for this game, I was heavily influenced by Mark Brown’s analysis of the Super Mario platformers on his YouTube Channel Game Maker’s Toolkit. The specific video link is here:
Game Maker’s Toolkit: Super Mario 3D World’s 4 Step Level Design https://www.youtube.com/watch?v=dBmIkEvEBtA
The mechanics in my game are not nearly this complex, but the core remains:
- Introducing a new mechanic starts out easy, where the player is not penalized heavily for failing to grasp the concept.
- Situations where the player finds themselves using the mechanic get progressively harder
- There is a satisfying “show-off” sequence where the player can bask in the glory of their comprehension.
Now, the only control mechanics in my game are jumping and moving – not terribly complex. But the constraint that you can only move while in the air, and that there is a variable jump height, make for some interesting jumps. Couple that with the “secret” double tap of the D-pad to get even more horizontal force and there is some learning curve to ascend. In my level design, I loosely tried to follow this philosophy so the player can learn and master my game, then start competing for high scores.
Level Design
The level is broken up into 6 sections, each with a fresh match to start it off. The first section is simple stairs. The first stair can be climbed just by tapping the jump button, but that method will fail on the second and third steps. Here, the player must learn the variable jump height mechanic with no major penalty if they have trouble with it.
Section 2 adds to this mechanic by forcing the player to think about combining it with the move mechanic to traverse a series of floating, stationary platform. The penalty increases a bit here – if the player is skilled enough to reach the third floating platform, but then fails to reach the end of the section, they now must deal with a water hazard (yellow pipe). The water hazard drops water on to the match to extinguish it, an instant game over! It is unlikely here that the player must deal with the water hazard, so the penalty is still considered minor. It also gives the player a chance to see and recognize water as an element in the game. Hopefully, they will deduce that water could put out their precious flame and realize it’s a hazard just by viewing its behavior from a safe distance.
Section 3 is the first showoff sequence – the player is tasked to “bunny hop” a series of small platforms to demonstrate their mastery of the jump-and-move mechanic. There is also a water hazard here, this time in more central location, thus the player is more likely to encounter it should they not pass the section. The penalty in this section is greater than the other two, and upon completion should be somewhat satisfying.
Section 4 introduces a new mechanic – moving platforms. These are designed to test the player’s predictive ability and reflexes. Since they are now masters of the Jump-and-Move mechanic, they now must apply it with their existing gaming expertise to overcome a new challenge. In the image below, the blue dots represent nodes to which the platforms travel in a periodic fashion (there are two more blue dots covered by the platforms). The first two platforms simply move back and forth between two points, and the last platform oscillates in a triangular shape above and below the second platform. Section 4 is straight forward and acts as an intermediate introduction to the moving platform mechanic. There is another water hazard here to add a penalty but like in Section 2 its unlikely the player will hit this water hazard.
Section 5 is the showcase for moving platforms. It features an elevator on the far left, two “Ferris wheels” in the middle that move in syncopated fashion to give the player a window to transfer, and a high-speed horizontal moving platform to end the section. Although tougher, this section should be somewhat intuitive for veteran platformer gamers, but it might take those new to the genre more time to grasp. The penalty in this section is heavy because it is not easy to get back up on the elevator. Falling in this section will likely burn through the entirety of the match, ending the game!
Section 6 is the most dangerous – it is a series of water hazards. By now the player should know that touching them is a bad thing. They may not know that its an automatic loss if they do! Therefore, the stakes are high as the player proves they have mastered the jump-and-move mechanic, patience, and timing (from moving platforms) and reflexes. After they get through this gauntlet, they ignite a giant bonfire, winning the game in a blaze of glory. This is akin to what Mark Brown speaks of in the video, with a “satisfying flag sequence.” The particle effects are not in yet for the bonfire, but you get the idea.
Perfect! After completing this obstacle course, the player should feel some sense of accomplishment. They may want to show off to their friends by playing in versus mode or learn from their peers by playing a cooperative game. Maybe they will want to test their mastery against the high score board!
Game Flow and Scene Management
My current approach to scene management and game flow is ad-hoc and not very robust. I essentially just patch in new functions to my manager classes until I achieve functionality. It is not great. This being my third project, I have finally realized I need to develop a true solution for this to make life easier in upcoming projects. But for now, you may find this approach (and my manager codes) a little messy. Due to how long this implementation took me, I am going to keep this explanation brief and very high level. Comments are your friends and please feel free to reach out to me if you have any questions about how or why I did something.
The Singleton Pattern
I used a Singleton pattern for my two managers and abstracted it out to a base class for easy creation of new managers, should the need arise. I pack both of my singletons into a “boot” scene. The game object I chose to house my UIManager singleton is the Canvas to which all UI in the game is parented. This way, UI is never destroyed on scene loading, and I just hide UI pieces that are not currently being used. There is some debate about the Singleton pattern and “DontDestroyOnLoad” with Unity, but I have never had issues with it.
Game Manager
This is a typical implementation of a Game Manager, handling scene transitions, win and loss events. Something that I added to this is a very, very simple Finite State Machine to help facilitate game flow. There are 4 possible state and a default state, declared in an enum. I set a static variable in the Game Manager to track this state, so that any other class can access it. Then, in other classes, if I think something should only occur during certain states (for example, you cannot unpause if you are not in the paused state) then I simply check this field before doing that action. Sometimes, objects behave differently when a state changes. So there is a property to set the GameState which fires off a signal to all interested objects that the state has changed, and to which state it is now in.
I also track game mode in the manager, for a similar reason. The MatchControllerComponent, MatchBurnComponent, and the UIManager all behave differently depending on game mode. The GameManager is a centralized point to check which game mode is currently active. It works well, because it derives game mode from the scene name, and it already uses the SceneManager API.
UI Manager
The UI Manager holds public references to all objects that represent collections or menus in the games UI. It also has methods to show and hide these collections. Making all these methods public allows the Game Manager to call them at will during its many game-flow routines. The result is an extensive class that handles all things UI and it is a bit messy.
The Asset Store
Particle systems are paramount to the feel of this game. You are a match; it should be all about fire!
Although I have a functional grasp of the particle system editor in Unity, to make fire you also need to have 2D drawing skills, which I have yet to develop. Fortunately, Unity has a special effects package that has everything I need to make this game come to life. I downloaded it here:
Unity Particle Pack – Unity Technologies
https://assetstore.unity.com/publishers/1
I used their explosions, candle flames, and large flames effects to create fire effects for the match, bonfire, and main menu. I used the explosion to signal ignition (in a dramatic way). This leads to a satisfying pop whenever a match is light, and a very satisfying explosion when the bonfire is lit.
They also had some water effects that worked nicely for the water hazards called “Shower.” I coupled that with the small splash effect for maximum believability. It was a little tough to get the timing of the hazard collider to align with the water effects, but plenty of trial and error led to a combination that is playable and can be anticipated. That is the goal!
I also used to asset store for the nice skybox that now is the backdrop to the game. It can be downloaded here:
Free HDR Skyboxes Pack – BG Studio
https://assetstore.unity.com/packages/2d/textures-materials/sky/free-hdr-skyboxes-pack-175525
This skybox was of heavy influence with the (somewhat) final color pallet of the game.
The Color Palette
I am a programmer who severely lacks artistic ability. My fiancé helped me choose new colors for the platforms, moving platforms, and water hazards based on the skybox. The result is aesthetically pleasing!
Some Polish
I decided to change the angle of the directional light to create a shadow that covers the first match. Then, when the match is ignited, I added a point light to illuminate around it. This makes the entrance more dramatic!
The clouds are stylized with a gradient that I tossed together in Aseprite. It is not perfect, but it looks pretty good when you are focused on the matches. I added a simple script to randomize their sizes and move them slowly across the screen, because clouds are not stationary!
I made a fog plane based on this StackExchange post:
https://gamedev.stackexchange.com/questions/143382/how-can-i-create-a-height-based-volumetric-fog
The goal was to hide some of the imperfections of the level design, and to blend the level into the skybox. I think this simple trick did well to achieve that!
I also used particle effects to light the “i” on fire in “Matchstick Relay” on the main screen. I even used the tiny explosion to give it a kick. It looks sharp!
Audio Collaboration!
For all sounds in Matchstick Relay, I worked with a friend of mine who is an avid musician and who is blossoming as a sound engineer. You can listen to his material on TikTok (@adam_babcock). Show the sound guy some support!
I started by creating a list of sound effects I thought were necessary to bring this game to life and sent the list of roughly 20 sounds over to Adam. We then met up the following day (respecting Covid-19 guidelines, of course) and got to work. My sound engineer uses the industry standard DAW called Pro Tools, and most sound effects were created by mixing percussion instruments, with some more high pitch tones to fill in the blanks (like crickets). Our workflow was mostly me watching him work his magic in the editor and giving comments about how I thought each sound would fit in the game.
As for the soundtrack, Adam had sent me a tom-centric drum riff toward the beginning of the Jam that I fell in love with. I asked for a tom focus because I thought it gave a sort of tribal feel, and the game is about lighting a bonfire. Although the artistic direction did not end up going for a jungly theme, the drum riffs still work perfect to create a sense of urgency and make you feel like you are on a time limit. Luckily for me, Adam can think up brand new riffs on the spot, so he just came up with a few and we cleaned them up in Pro Tools to make a soundtrack. I named all of the songs somewhat arbitrarily so that players could pick their favorites!
I did write one riff – “Doom Cannon” – played on the main menu. It’s a riff I came up with around the time I started drumming, and I am very happy to see it has found its home in a game who’s soundtrack is a magnificent homage to the power of percussion.
Adam helped to mix the sounds as audio files, and I placed them into Unity using my knowledge of the editor. The songs were made into loops that were just over three-and-a-half minutes long, because 3:12 is the maximum amount of time you can spend in a level based on the matches burning. I used the “compress in memory” function on these to limit the memory overhead of the larger files. I also end the songs when the player loses and play a neat four-tom drum sound effect when the player loses. Most of the time, it fits right in with the song that’s playing and it feels really, really crisp.
It was tough to mix the sounds in 3D space, but I managed. I utilized the audio curve feature quite a bit to control the distance at which sounds were heard. It was a lot of trial, error, and playtesting to get it to sound just right.
Oh, and do not forget the screen shake added to make that gut-busting win sequence hit even harder than it does alone.
When it is all said and done there are 17 sound effects and 5 unique tracks that bring Matchstick Relay to life, and truthfully the game is underwhelming without them. Special thanks to Adam for making this game pop!
My Personal Play Testing Crew
My journey in game development has not only been supported but enhanced by the cast of friends I have who are interested in my path. They are always eager to try out my new games and give me their opinions, but for this game I asked them to do it a little more formally. My sound guy, my fiancé, and two of my college friends have all helped tremendously in playtesting, but the latter two gave me a more serious critique. I sent them an alpha build of the game and asked for their initial impressions and if they noticed any bugs. This entry will detail what they said about the game during our Zoom session.
Highlights from the Alpha Playtest Session
Comment: Josh only saw one tip in his entire hour of playtesting
And it crippled his ability to improve at the game. The goal was to have these tips show frequently. A massive oversight on my part.
Issue: In hindsight, this seems ridiculous. I had an arbitrary “if” statement to only allow the loading screen to show if the transition was from the main menu to the game scene. I think I was trying to prevent the loading screen from showing up during the boot sequence, but even that is silly, because a loading screen feels natural there as well.
Fix: I removed the condition checking the game state and now the loading screen appears during every scene transition, no matter which scene it is transitioning from or to. A few other of Josh’s concerns were alleviated when he learned that they were discussed in the tips (for example, he was unsure what the high pitch tone was. It was our water pipe warning tone).
Bug: Josh can cheat by climbing walls.
Yeah. This is a huge issue because it makes the game really easy.
Issue: The collider for the ground check was wider than the matchstick itself by just a hair, and all platforms (including walls) are tagged as ground, so the ground check could register the wall, and, well, you get cheaters.
Fix: I simply reduced the radius of the ground check sphere to tuck it in behind the matches collider, so it could no longer register the wall as ground.
Bug: James and Josh’s matches got put out while standing on top of the water hazard.
Well, that’s not supposed to happen!
Issue: This was tough to pin down, mostly because I couldn’t reproduce the bug in my playtests. I had the pipe through which the water was exiting marked as ground, and I have the water collider deeply nested inside of it. I could not imagine the match penetrating the hazard deep enough to collide with the water. I deduced that it could be caused by the water collider beginning its life in intersection with the collider of the pipe.
Possible Fix: I move the collider to no longer intersect with the pipe. It does not feel like a perfect fix, but I was unable to recreate the bug in 10 minutes of playtesting with the new collider size and position. More testing is required to fully understand and fix this bug.
Comment: Inability to use the arrow keys frustrated James.
I never even considered using the arrow keys to move the match. This is why we have play testers, everyone! Frustration is an emotion I want to cultivate in the obstacle course, not on startup.
Issue: Key bindings for the keyboard were simply too restrictive, and only allowed for the A and D keys to be used as movement input. This, along with Space to jump, made for an awkward control scheme.
Fix: Thanks to Unity’s new input system, I just added the extra bindings, and was sure to update the player HUD to reflect the new controls. Hopefully, this makes James’s life a little easier.
Comment: “The soundtrack is the best part of the game if I am being completely honest.” – James
Nice! I told everyone in the last post that Matchstick Relay is nothing without its stellar but simple soundtrack. Adam and I are proud to have elicited such a heartwarming response to the game’s audio profile.
Bug: In some cases, Josh was able to stack matches on top of each other when transferring flame. He felt it was unnatural.
I agree, it is a little weird to have them stack, especially because they affect each other’s ability to move.
Issue: Matches can collide with each other. They need to register their trigger collisions and pass flames. I did notice this bug myself during development but stopped short of a good fix when I realized the following: This behavior is actually a result of some poor architecture. Each matches’ collider should be a separate game object so I can control for stuff like this. Unfortunately, the match collider is tied to the parent object, and it Is a little too late in the development cycle to change it and deal with the consequences. Thankfully, the bug is not game breaking, its just a little annoying. And its somewhat physically accurate? I determined that cost/reward of fixing it is not worth it with respect to my time constraint…
…UNTIL AN IDEA STRUCK ME.
It’s messy, but I decided that I can change the layer of the spent matches to “spent” upon passing a flame, then in the project settings, I ensured matches could not interact with spent matches.
Fix: Change the layer of used matches to one that cant interact with unspent matches.
Bug Squashed
I noticed one more bug – if you fell off a platform without jumping (due to a slide) you never become grounded again and thus lose the ability to jump. I fixed this by resetting the ability to check ground if the player jumps OR if the player’s velocity is greater than a small dead zone at rest. It works great and the game is much smoother now.
PostProcess Volumes
I created a simple PostProcess volume to apply to all scenes in the game on all cameras. The most important effect was Bloom, which made the fire look less like paper and more like an actual flame. I also turned Antialiasing on, to soften the sharp edges of the cubic geometry in the game. Finally, I used the Ambient Occlusion to deepen the contrast of the shadows. I toyed with using Color grading to make the scene warmer, but ultimately, I decided I liked how the scene felt with the aforementioned slight augments.
Finishing Touches
- The flame on the main screen is a match, right? It now plays sound as if it is a match.
- Snuffing out matches in between scenes feels natural, so I did that.
- The win and loss screen text were hard to read, so I darkened the panel on which they sit.
- I added a few more loading scene texts, including one that encourages the player to turn down the music and listen to sound effects.
- Time to collect screen shots and write our post!
A Special Thanks To You, Dear Reader
This is my first game jam and I absolutely love the thrill of working with a deadline. I can’t wait to do more of these.
Thanks for reading my entire Dev Log! Please feel free to reach out to me on Itch.io, or email me at TheIndieDream@Outlook.com with any questions. I am happy to answer any you have and hey, if you want to work together on a project, let me know!
Files
Get Matchstick Relay
Matchstick Relay
A fast-paced racing game about passing on the flame!
Status | Released |
Author | TheIndieDream |
Genre | Platformer |
Tags | 3D, Atmospheric, Co-op, Multiplayer, original-sfx, original-soundtrack, race, Singleplayer, Speedrun |
Languages | English |
More posts
- Running Matchstick Relay on Mac OS X (Big Sur)May 06, 2021
Leave a comment
Log in with itch.io to leave a comment.