Duo Slide - Global Game Jam 2022

Hey everyone – figured I would toss a forum post up about this game to help explain how it works, track any feedback you have or bugs you might encounter, and explain some of the technical aspects.

Play the game here: Duo Slide
Gameplay GIF:

🕹️ How to Play The overall concept behind the game is fairly simple: You use the directional input to move blocks around and try to get the red/blue neon blocks to their respective goals. Any time you move, all movable blocks will slide as far as they can. Your score is determined by how many moves it takes for you to get both neon blocks to their corresponding goals – lower scores are better.

Each level consists of at least these elements:

  • A blue neon movable block and it’s corresponding goal
  • A red neon movable block and it’s corresponding goal
  • Wall blocks
  • Open spaces

Any level can also contain any number of these special elements:

  • Movable walls - They act like normal walls but also slide when you move
  • Bounce spaces - If a block lands on one of these it will move in the corresponding direction until it reaches another block. These look like double arrows (>>) that indicate direction.
  • Teleport spaces - If a block lands on one of these it will be instantly moved to the corresponding end location. These look like little hashtags (#) and the end location looks the same but rotated 45 degrees.
  • Sticky spaces - If a block hits one of these it will stop. These look like little squares with double lines.

Every level has been built by hand and tested to make sure it’s beatable. In almost all cases they can be completed in less than 30 moves.

At any time you can reset the level, exit the game, or view the level leaderboard by using the buttons listed at the bottom of the screen.

The arcade machine in the starting area is set to auto advance through levels as you complete them. The arcade machines in the “warehouse” don’t auto advance (so you can practice individual levels and shoot for high scores).

⚙️ How it Works Here's an overview of how the game functions...

When your player/character walks up to a machine they enter a trigger which starts the process for level creation. This process is basically the same when you reset a level or move to the next/previous levels. The process includes:

  • Making the player invisible and stopping them from moving
  • Setting the player camera to an in-game camera pointed at the ground outside the playable area
  • Running through a table of numbers that correspond to the types of blocks listed above and spawning them in place (more on this later)
  • Toggling the visibility of those blocks only on the client (ie: they are only visible to the player who entered the trigger, essentially making a single player game)
  • Showing all of the UI components and updating/resetting their values
  • Shouting the level name and notifying the player of their previous best score (if it exists)
  • Setting the level to be “ready” (which enables the input detection)

Each time a player moves (if the level is ready to accept input), another process is started which includes:

  • Stopping input detection until the move has ended
  • Collecting all of the movable blocks and sorting them into a table based on their row/column and the direction of the input
  • Determining the nearest block in the given direction for each of those movable blocks and moving them
  • Incrementing the move counter if at least one block has moved
  • Checking to see if any blocks landed on a special space that requires additional movement (push blocks and teleporters)
  • Checking to see if the neon blocks are in the winning position. If so, the game records the score and plays the win sequence

That’s the overall process that governs this entire game.

🛠️ Level Creation And here's a deep look at how I made the levels (aka the cool part)...

I mentioned above that when a level is created the game “Runs through a table of numbers that correspond to the types of blocks listed above and spawns them in place” which sounds cool, but what does that actually look like?

There’s a script in the game that is full of tables that each define a level. Each of these tables contain exactly 220 items (one for each space on the board) and those items are numbers or letters that correspond to the blocks listed above. When a level is started, reset, or changed, the game increments through the table spawning the correct blocks for each space (or leaving them empty), assigns them a row number, column number, block type, and adds them to a table stored on the User. Then, for each move, we check and manipulate the table stored on the User to determine what should happen.

Here are the block definitions:

BLOCK KEY
	"B" - Black Player Block (aka red)
	"W" - White Player Block (aka blue)
	"C" - Black Objective (aka red)
	"W" - White Objective (aka blue)
	000 - Blank
	001 - Wall
	002 - Sliding Wall
	101 - Push Up
	102 - Push Down
	103 - Push Left
	104 - Push Right
	201 - Teleporter Start
	202 - Teleporter End
	301 - Sticky

And here is what Level 8 (from the gif above) looks like:

self.levelData[8] = {}
	self.levelData[8].map = {
		001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001,
		001, "X", 001, 001, 104, 000, 000, 000, "C", 001, "B", 000, 000, 001, 001, 001, 001, 001, 102, 001, 
		001, 000, 000, 001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001, 
		001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001, 
		001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001, 
		001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001, 
		001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001, 
		001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001, 
		001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001, 001, 001, 000, 001, 001, 001, 001, 000, 001, 
		001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001, 001, 001, "W", 000, 000, 000, 000, 000, 001, 
		001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001,
	}

Since each of the levels is defined as a table, there’s no additional building required to create levels. By duplicating this table and making slight changes, I was able to create completely new levels in a few minutes.

There are still a few limitations (bugs) in my movement system but if you’d like to try creating a level you can. Simply copy the “template level” below, modify it, and paste it as a comment in this thread. I’ll collect them periodically and add them to the game (with credit of course) if they’re beatable. If this becomes a popular idea, I may hold out until there are a bunch and release them as a whole “community made expansion”.

The known limitations so far are:

  • The outer spaces must be filled with walls
  • A level can only have one teleporter and it must have a corresponding end locator
  • A push block cannot point at another push block (game breaking bug) or a sticky block (minor bug)

Here’s the template level:

TEMPLATE LEVEL
self.levelData[] = {}
self.levelData[].map = {
	001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001,
	001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001, 
	001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001, 
	001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001, 
	001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001, 
	001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001, 
	001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001, 
	001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001, 
	001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001, 
	001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 001, 
	001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001, 001,
}

If you have any feedback or questions about the game, feel free to post them here or to find me on the Discord. I’m more than happy to share what I know and help however I can :slight_smile:

3 Likes