top of page

The goal of this project was to create a puzzle game based around the rules of; blocks could only be removed when they were adjacent to at minimum another block of the same type, player has a limit amount of removals per puzzle, and the puzzle is cleared when all blocks are removed. Another element of the gameplay was picking up extra removal pickups that were scattered throughout the level if it was not possible for the player to complete the puzzle with the starting number of removals.

Summary -

Challenges - 

The three main challenges of this project were; How to detect when two or more cubes of the same type were next to each other, How to design overall logic to determine when each of the levels were solved, and How to store level generation info to be able to load each level dynamically without using UE4's default "Open Level" node.

Solutions -

In order to determine if the player was facing any of the three types of blocks, I decided to assign each type of block a unique trace channel (Dirt, Metal, or Wood). Then based on the direction the player was facing I would fire a line trace from the character in order to determine what kind of block was in front of them. This was my Blueprint setup for the initial trace (The only things changing being the trace channel and whether the ending vector was in the X or Y direction which was based on the direction the player faced)

If the trace registered a success on the specific block type it was looking for, it would set that block's location and then trace again in all four directions around the block hit. Hit blocks were added to an array of objects of the specific block type in addition to having their location stored and used for further traces. This would continue until the line traces returned four non-hits, which would be when it hit any object other than the specific block type from the initial trace. (This framework was used for each block type, the only things changing would be trace channel and which array of objects the blocks were stored in)

Once the trace failed to find anymore blocks of the same type adjacent to any of the blocks it had stored in the array I would have the array filled with the object references to the blocks destroy all of them. However before it would destroy them, it would check to see if the player had any removals for the block type left (checking both its type & if the player had any wildcard removals left). If the player did have removals left, it would destroy the cubes, remove the reference from the array, and take away a removal. If the player didn't have any removals left, the blocks would remain in the level. (Again the same framework was used only changing the variables for the specific block type needed)

These were collapsed graphs in my final Blueprint setup, so the overall Blueprint logic for each type of block looked like this. Being able to build a generic framework that could be only slightly tweaked for each type of block really helped with solving the first challenge I faced with this project.

In order to figure out when the player had solved the level I decided when each level was loaded to set a value of how many total cubes there were left in the level, assuming they were within a certain range of the player (So that if I later decided to just have all the levels laid out at once I wouldn't have to remake any of my previous logic)

As the player removed blocks from the level, it would subtract the number of blocks removed from this initial value. Once this value reached zero, it would count the level as being solved and then it would clear the level of the exteriors walls and immovable blocks to make space for the new level generation.

The most difficult challenge from this project was figuring out how to generate the levels without either laying them all out before hand in various parts of the overall level or using UE4's default "Open Level" node (which just seems like overkill for what I needed). So what I ended up doing instead was creating three custom events, one for each size puzzle I would have (5x5, 7x7, 9x9), and would have each custom event set a variable that would dictate the logic for spawning the level of each size.

After clearing the array for the new puzzle generation, I would set the default spawn location and run through a while loop adding that spawn location into an array until the current row number was equal to the number of rows and columns set by which custom event was run. After the while loop completed I would then run through another while loop until the level was finished generating. Inside the loop I would take the previous array of spawn locations and add an offset on the Y axis to each element based on the index multiplied by the size of a block. Once that was completed I multiplied the spawn location to have an offset on the X axis based on the current row multiplied by the size of a block. This would continue until the current row was equal to the number of rows and columns value set from the custom event.

After the last while loop finished, I then determined which data table to pull the level generation data to pull from based on the current level (1-5 were 5x5, 6-10 were 7x7, and 11-15 were 9x9). From the data table I used to store how each level would be laid out I would go through a for each loop spawning a specific block, empty space, pickup, or player spawn based on the value from the array. I used the ints 1-9 to correspond to a different piece of a level to spawn which would spawn at the location specified by the array created in the last screenshot. In making use of data tables and this way to generate an array of locations to spawn things I was able to generate any level I created without using UE4s "Open Level" node or prebuilding the levels.

This project helped a lot with understanding how designing proper framework to build off of in later stages when scaling up a product/project is extremely important. If I hadn't built the logic for telling the project where to spawn each element of the puzzle in such a way that only needed to change one value at the beginning of it would have lead to having a lot of redundant code later down the line. In a similar vein I wish I had figured out a better way to handle holding the information for spawning the puzzles rather than needed to have three different data tables depending on the size of the puzzle I wanted to generate. Because I needed to have different data tables for each size led to having a lot of repeated code (for example the screenshot above needed to be done three times, one for each data table). Another important thing I learned from this puzzle was an introduction into using event dispatchers in order to use the character blueprint to "talk to" to level blueprint.

Lessons Learned -

Project File & Executable - 

UE4 Project File: 

UE4 Executable: 

Download Here

Download Here

After generating the exterior walls based on the size of the puzzle that was going to be spawned, depending on which event was run I would set the number of rows and columns accordingly. In addition I would clear the array I use for storing the vector locations of the initial row that the puzzle would generate. 

This was a puzzle game I designed for my Studio I project while at SCAD. I designed and created fifteen different levels of three different sizes: 5x5, 7x7, and 9x9.

Overview -

Block Removal Puzzle Breakdown

  • Facebook - Black Circle
  • LinkedIn - Black Circle
bottom of page