Tower Topplers is a Puzzle VS game inspired by games like Puyo Pop and Tall Infinity: the Tower of Fate. Your goal is to roll blocks around a tower and match colored block sides in quick succession to build up your tower while destroying your opponent’s tower. Your blocks are destroyed when your opponent makes combos, or when a timer on the bottom left of the screen fills up, destroying a line on the bottom of your tower. The game has multiple character classes with unique abilities that let you choose a character who fits your play style. I started developing this game in my free time in April 2021, and then was joined by a second programmer in June of 2021. Development has been slow because of lack of time, but it’s still ongoing, and there’s a playable demo available on my itch.
I am a programmer, designer, and artist for Tower Topplers, though for this piece I’ll mostly be focusing on the programming. On this project I’ve been responsible for programming the core game loop, UI functionality during game-play, and other miscellaneous things.
Core Game Loop
This is the largest and most complex part of my programming work on the project. As this is a game about rolling blocks, the first step was to get blocks rolling and matching with each other. I knew that this was going to end up being a competitive multiplayer action game, so I decided to rotate the blocks using code instead of the Mecanim system. I did this so I could get precise animation timing at 60 fps and easily change how long it took to rotate blocks if future play-testing revealed that it was too fast or too slow. An unexpected issue I ran into here was the fact that the block needs to have its rotation zeroed out at the end of each rotation so that it can rotate around the correct points. This meant re-assigning every material on the block at the end of each rotation so it looks like the block is rotating even though it’s actually resetting itself every time.
The match code was comparatively easier. Finding a match was as simple as raycasting from 3 sides of the block and checking the side arrays against each other to see if their sides matched up. The difficult part was in actually spawning the blocks afterwards. This brings us to our next core system, the block manager. The block manager tracks the state of a tower of blocks and is responsible for spawning and deleting blocks. It’s used just about any time a block is doing anything, it was even used in the rotation functions I just mentioned to check if the block was able to rotate.
At first, the problem seemed simple enough, just spawn a few blocks based on what sides matched on top of the stack, easy, right? In truth, there are actually a number of things that complicate this. First, the column that the blocks spawn in needs to be locked down, because a player moving a block as it’s spawning completely breaks the array that keeps track of where blocks are. This means stopping the player from moving blocks that are already in the column, but it also means stopping the player from moving any new blocks into the column as the blocks are spawning so that a falling block doesn’t end up in the same spot as a rising block. Second, I realized early on that blocks should actually spawn at the bottom of the tower and push up blocks above them so that the player can see what’s coming next. Finally, once the player character got involved, it became clear that we had to stop them from moving while on top of a rising block to stop them from getting stuck inside.
Speaking of the player, that was the next thing I implemented. The player is complex and currently uses about 10 different scripts to function, but mostly the player moves, grabs blocks, handles input, and has data that other scripts use to do things. In Tower Topplers the player can move left and right, and if they move into a wall they climb up it. Since the player can only move on a 2D plane in this game, I used my past experience making 2D platformers and adopted a lot of the same code. If you’ve ever made a 2D platformer in Unity, you’re probably familiar with the implementation. Basically, the player sends out a number of rays to see if there’s an object where it’s trying to move, and then it adjusts where it’s trying to move if it finds one so that it doesn’t go inside that object. This is the code for horizontal movement:
The code for vertical movement is largely the same, except the player parents itself to a falling block if it falls on top of it so that they fall flush instead of the player awkwardly falling slightly above it. The player’s movement changes however if they’re grabbing a block. When a player grabs a block, they set themselves to be the child of that block, and turn off their movement functions. Instead of moving normally, they call the block’s movement functions and the block moves them with itself when it moves. When the player lets go, the block checks if it should make a match if it’s on the ground, or sets a flag to do that when it lands if it’s in the air, and the player is able to move normally again.
The last part of the core loop I have to talk about is how damage is handled. This is mostly done through a MatchManager script that also handles things like instantiating players and ending the game. First, the game needs to figure out who to deal damage to and how much damage to deal. This is dispersed over a few scripts and functions. When the block manager spawns blocks, it tells the player to start a combo, and the player tells the match manager that they’ve started a combo at combo count X where they spawned Y blocks. The player also tells the UI Manager that it started a combo, and the UI manager plays an animation to show what the combo count is. This part is a little circuitous, but I chose to do it this way to keep information related to the player in scripts attached to the player, instead of storing combo count in the block manager. Next, the match manager calculates how much damage the player did. This number is based on how easy the match was to make, what step of the combo they made it in, and if they have any additional damage multipliers because of their character. It’s simple math, but it took some time to figure out how many multipliers we needed and what their values should be.
This damage isn’t immediately applied to the opponent though, they need to have some time to respond and fight back, so this damage is instead added to a running total and displayed by the Main UI controller using icons. The player taking damage can also see which blocks of theirs will be destroyed, as they’re marked with a glowing target. Initially I kept track of the damage with a list of damage instances, but I realized later that it was a lot easier to just use a single float value where positive damage means player 1 is hurting player 2 and negative means the opposite. All this is to say that I multiply the damage by -1 if it came from player 2 and add it to the running total. Later, I added extra logic to deal with damage resistance, which was needed so that damage resistance didn’t reduce the effectiveness of your opponent healing damage.
As I mentioned before, it’s important for players to have time to respond to their opponent. To create this, I use a few timers. The first tracks how long the player has to keep extending their combo. It’s set or reset when a player makes a match, and when it counts down to 0, the player drops their combo and we start counting on the second timer. The second timer is a short comeback timer that gives the opponent a chance to respond with a combo of their own. If nobody makes a match before this timer finishes, then the running damage total is applied and the block manager is told to destroy blocks equal to the damage total rounded down. If this destroyed enough blocks that a player has a hole in the bottom of their tower, the player who dealt that damage wins the game. All this has been a simplified version of the core loop of the game. Making all these systems readable, however, is where UI comes in.
There is a lot of UI in Tower Topplers, and all of it communicates important information. On the top left there is the damage coming towards you. Damage is displayed using colorful icons, and progresses from green > blue > yellow > red, which represent 1, 4, 8, and 40 damage respectively. Converting the damage to icons is relatively straightforward, and so is displaying it. The icons are stored in an array, and I change the sprites they use so that they properly represent the amount of damage coming in, starting with the most damaging icon first.
Next, on the top right, there’s the combo count. When a player makes a combo, I use an animation to make it expand and contract to get their attention, and it shows them what combo count they have. Then, I make the number slowly fade as their combo timer ticks down, and once it disappears the combo is over. I do this using an animator and the color property of a UI image combined with the combo timer I mentioned in the core game loop section.
Also on the top right there’s a warning indicator. This slowly fades into view when your opponent starts a combo, and a red ring around the edge will fill in once the comeback timer starts. The ring fills up using an animation and tells the player exactly when they’re going to take damage. This was actually hard to get working because combos are so subject to interruption. It’s not as easy as just playing animations when timers are done, you have to account for the fact that the animations can be interrupted at any time. With the warning sign this was easy enough to accomplish, I just had it lerp between invisible and visible using the combo timer to tell how close the player is to danger. With the red ring, however, I chose to use an animation so I could fine tune the timing. However, this introduced a race condition where it would sometimes have stale data that made it inaccurate. I ended up just checking if it needed to be reset every frame, which isn’t the most elegant solution, but it works and still conveys what needs to be conveyed.
On the bottom left there’s a few things. The purple circle is the line timer, when it fills up it destroys the bottom row of the tower. It’s just an image with a radial fill that fills based on a timer. The interesting part of the implementation is with how I handled the timer speeding up. There’s an array with different times that controls how long it takes for the timer to fill completely, the index of that array is incremented after set intervals of seconds. To make the timer transition between these times seamlessly, I multiplied the lerp timer by the new interval divided by the current one, so the timer is percentage-wise at the same place, and to the player it just looks like it’s been sped up.
Above the timer on the left side, there’s a number of green bars, these tell the player how many lines are left on their tower, it’s basically a health bar. I made the lines change color based on how many are left on the stack, so if you had 12 lines, the bottom two bars would change to a shade of blue, and if you have 3 lines, the bottom 3 bars would turn red to let the player know they’re in danger. I also change the material for the top line to an emissive material and play a particle effect to draw the player’s attention to how much health they have.
The purple meter on the outside is a super meter that you spend to use your abilities. It’s made of 3 separate emissive radial fills that fill up as the player makes matches. Basically, I store the fills in an array, and iterate through them treating each radial as 1/3rd of the whole fill. As they get closer to being full I increase how emissive they are, and when they’re completely full I swap their material for an even more emissive one and play a particle effect to let the player know that they can use that part of the meter. This one was a little tricky to figure out because it was the first particle effect I had put on UI, and I learned that you have to set up the UI in a specific way to get particle effects working with it, which involved a lot of refactoring.
Finally, there are the two icons on the bottom of the screen which tell the player if there’s a bomb or a rocket off screen that they need to watch out for. These are only enabled when an opponent spawns a bomb or rocket on your side of the screen. They start off invisible, and lerp to be visible over a short amount of time if there are any bomb or rocket blocks off screen. When the blocks are brought back on screen, they lerp back to being invisible. They also adjust their position based on if one or both of them are active, where they’ll be in the center if they’re solo, but they’ll move to either side if both types of blocks have been spawned. This one was simple to execute once I learned that renderers have a local variable that tells you if they’re being rendered. The only sticking point was another race condition where the icons would be rendered for 1 frame when the bomb or rocket blocks spawned even if they were on screen, but I solved that issue by simply starting the icons invisible.
That’s it for the main UI that the game uses. I also did the UI for the game over screen, but that implementation is nothing special, just an animation and a basic menu. UI isn’t the most interesting logic, but it’s important and I’m happy to say that this project has given me a lot of experience working with it. This has been the most complex project I’ve worked on so far, and I’m excited to see how much further it goes by the time I finally complete it.