Developing Sokobubble


My latest PICO-8 game, Sokobubble, is now online on itch.io.

For those that are curious, you can find here how it was developed and some of the key design decisions.

Background

Development of this game started during this year's Global Game Jam. Unfortunately, during the weekend itself I was a bit under the weather, and couldn't join my game dev team on the jam site. The intense and long days and short nights would not be conducive to my recovery. I had been looking forward to the jam, and did not want to miss out entirely, so I decided to build something smaller scale from the comfort of my home instead.

By the way, my game dev team managed to do without me, and created a nice-looking multi-player game featuring rubber ducks: Bubble Bathle. Check it out!

Platform

With my team I would have been working in Unity, but for this one-person project PICO-8 was a logical choice: it is a platform I am more familiar with, I can develop games in it without requiring help from a graphic artist, and its built-in sprite, map, and sound editors allow rapid prototyping to explore ideas.

Game idea

The theme of this year's GGJ was "bubble". While brainstorming I thought "being inside a bubble"/"having a skewed/limited view" might be an interesting take. I once made a Pacman game (never released) where Pacman could change color by consuming colored pills, and Pacman's color affected the portals/doors inside the maze it could pass. Exploring that game-mechanic a bit more, I came up with a Sokoban bubble variant. The box pusher can change color by entering bubbles, and this impacts the boxes it can push. A quick, rough prototype showed that this idea had some promise.

 

Figure 1. First prototype, and the same level in the final version

Smooth player movement

From the start I knew I wanted smooth player movement. Although it is not required for game play, it makes the experience much nicer. The left animation shows basic movement, where the player sprite jumps from one unit to the next. The right animation shows movement where the player smoothly moves from one unit to the next.

 

Figure 2. a) Discrete movement, and b) smooth movement

Similarly, although it does not needed for the game mechanics, I wanted the player sprite to rotate. This is consistent with the top-down view of the levels. I decided on a vehicle with caterpillar tracks for the player sprite. This is fitting as caterpillar tracks enable in place rotation. It's also something that can be rendered using low-resolution sprites.

To allow room for rotation, there needs to be space around the player sprite. This also means that when it is next to a box, it needs to move forward a bit before it touches and can move the box. Afterwards it needs to retreat again. When pushing a box multiple units, you don't want to have mid-push retreats, as it makes movement look clunky.

  

Figure 3. a) Player rotation, b) gapless push, and c) smooth gapless push

Level sizes

PICO-8 sprites are 8x8 pixels in size by default, so that is also what I started with. PICO-8's screensize is 128x128, so the largest level that can fit on screen is 16x16 units. However, I wanted to see if I could stick to levels that are 8x8 units in size. As each level requires an outside wall, this means that the effective playing area is only 6x6 units [1].

Limiting levels to 8x8 has several benefits:

  • Smaller levels are more enticing. How hard can the puzzle be if the level is small? Bigger levels in contrast may look more like a chore.
  • It enables porting the game to Gamebuino, a handheld device with a small screen.
  • Sprite resolution can be increased to 16x16. This makes the levels much clearer, especially on mobile devices with small screen sizes. It also helps to (more clearly) show overlaps: box pusher on target, box on target, box under bubble, etc. See the screenshots below for a comparison.

 

Figure 4. a) 8x8 sprites, and b) 16x16 sprites

Once I had sixteen levels of size 8x8 I decided to switch to the bigger sprites. I then knew I would be able to release a game with enough interesting levels at this size.

Footnote 1: Not fully true. Showing only half of the outside wall sprites would allow a 7x7 inner square. Wrapping at the screen borders could also expand the play area a bit. Nevertheless, if we can do without these "hacks", all the better.

Level selection

The game obviously needed level selection. By default, the game should let you start at the first level you have not yet solved. However, it should be possible to replay levels you solved already: to show it to friends, to let them quickly try it, to try and beat your previous score, etc.

Initially level selection was possible via a static menu. This was changed to an animated menu with level preview. This looks better, it let's the player see the level before selecting it, and smoothens the transition to and from game play. A drawback is that navigation is slower, but the menu wraps and the number of levels is limited, so this is deemed acceptable.

 

Figure 5. a) Static selection menu, and b) animated menu with level preview.

More generally, throughout the game's development, many parts underwent small and bigger changes. This included sprites, the game's color scheme, the logo, the main menu. This is also reflected in the various versions of the game's cart label.

   

Figure 6. Evolution of the game's label image

Progress and scoring

The main challenge of the game is to solve each puzzle. After having done so, some players may enjoy the challenge of minimizing the amount of moves needed. For that reason, the game tracks and shows the number of moves you needed.

It's of course interesting to see how your score compares to that of other players and what the minimum amount of moves is for each level. Therefore the game also includes an online Hall of Fame.


Figure 7. In-game online Hall of Fame

This functionality is not supported by PICO-8 out of the box. However, I had developed something similar before so knew it was possible. The basic set-up is shown below.


Figure 8. The software stack

PICO-8's GPIO is used to communicate between the game and the custom IO code. The custom IO communicates using a REST API with serverless Python web services. These web services use a cloud database for storing the progress of each player. Not only the scores are stored, also the move sequence. This can be used to detect cheating should anyone decide to "hack" the score submission system.

I also extended the game with resume codes. These allow to resume the game on a different device, or on a different browser. These codes are tied to your player name to discourage sharing.

Final thoughts

When you come up with a new game idea, you are never sure how it will turn out. In this case, the game mechanics are simple but led to enough interesting, challenging and aesthetically pleasing puzzles. Some of the later levels require more than two hundred moves to solve even though they are small in size and look deceptively simple. That is considered a success in my book.

To wrap up, I had fun making the game. Hopefully you will enjoy playing it.

Links

Files

Sokobubble-v1.1.1.zip Play in browser
25 days ago

Leave a comment

Log in with itch.io to leave a comment.