Bokosan – a reverse Sokoban

Bokosan is a reverse Sokoban where boxes are on a goal position and the player needs to pull them away while avoiding deadly spikes and falling into pits.

The game has 20 levels, single player mode, time challenge mode with online leaderboard, customizable player appearance, sound, 4 music tracks (6 in full version) and a few more features.

It is an entry for the js13kgames gamedev competition, where the goal is to create a web browser game using only JavaScript/CSS/HTML, with final size (after ZIP compression) below 13 kB, in a month. It was created for the 2015 jam for the theme “reverse”.

This year I worked together with my brother, Zsolt, he composed the music and created most of the levels.

Play it here.


I’ve decided to go with raster graphics, stored in PNG with low color count and replacing colors in code if needed. I’ve tried several other methods to store graphics (putting each sprite in a string, etc.) but the overhead for decoding was just too big.

(The image is scaled down, click here for full version.)

The final PNG contains the Jostix font by Ray Larabie (only uppercase letters, numbers, punctuation marks), 13 tiles, 9 character animation frames and 3 other graphics; it is 700×48 pixels, 20 colors and the final size is 1600 bytes after TinyPNG compression.

It might worth to note that for character animation I used oldschool tricks of mirroring and rotating to reduce the frames. I have only drawn the standing and step with right foot frames and then “stand, step, stand, mirrored step” sequence. Also, I just rotated the “walking up” frames for the “walking right”, as well as the “walking down” for “walking left”. For pulling I did the same but used one frame only and played the sounds of steps.

The colors of customizable parts of the character (hard hat, shirt, pants) are replaced during render (and not on the sprite sheet) as each entry in the challenge leaderboard can be different.

Quick note: when opening an HTML from local disk and accessing its contents in JavaScript, like reading pixels of an image (rather than putting in DOM and showing to user, or using drawImage()) the Cross Origin protection kicks in and prevents the operation. Although when opening from a web server there is no such problem, this feature can be disabled but it’s strongly not recommended. Worth to note that JS engines track the data they handle so reading a canvas where a drawImage() copied a portion of a protected image will result in an error as well.

Sound effects

For the sound effect we used jsfxr to generate them.

I have added a few minor optimizations for jsfxr before compressing the source via Closure Compiler, and after that manually edited the compressed code to be more suitable for ZIP.


The music was created entirely by my brother, Zsolt.

I have created a small tracker that implements the basic features of an XM, handles only one pattern and loops it, but also have a map that describes which channels should be played on which loop (and also an option for intro that will be only played once at the beginning) – this way a song can be made up of a short period of music but can be dynamic and changing on each loop. Also created a converter that reads an XM file and creates the JavaScript arrays for the player, so Zsolt could use MilkyTracker to compose.

The samples were produced using jsfxr just like the sound effects (they are actually in the same array) and are altered on the fly for player needs (changing playback speeds to create the notes).

I have also created a frontend for playback later, check it out.

Level design

The levels were by designed mostly by Zsolt, with a few exceptions.

They are stored as simple strings – ZIP is really good at compressing text.

The levels are locked by default. Only the already solved and the next two unsolved are unlocked, as an attempt to prevent the player from getting stuck on one level.

And as the steps are counted for each level it is just natural that achievement hunters appear, so we added an “A+” badge for them for completing the level with at most the minimal steps we completed them during development, displayed in the level selector.

Challenge mode

There is a challenge mode with online leaderboard showing the name, time and character profile picture for each record.

There are 6 challenges, each consist of 3-4 already completed levels, the player plays them one after the other and the time is recorded and shown on the leaderboard.


The game collects statistics about each play: play time, moves made, pulls done, levels started, levels finished.

The statistics is stored on the server side, the games recevies the current snapshot of the statistics and the one from a minute before, and then interpolates them during the next minute – this makes the display much more active.

I loved to see the numbers rolling during the vote period, unfortunately the statistics are no longer available on the jam website. [Although I made a few screenshots, but I could not find them yet.]

Server side

The server keeps track of challenge leaderboards and statistics. It does not do anything more, really.


I basically go with the idea of writing readable code and leaving the low level optimization and compression to the tools.

Most of the time this works just fine as for a really simplified example…

if (x == 3)
    return true;

return false;

… is exactly…

return x == 3;

… but the former can be read more easily and the tool will rewrite it to the latter anyways.

For code compression I used Google Closure Compiler in two phases: first is the advanced optimization without whitespace removal, then the whitespace removal. This leaves a chance for (easier) manual/scripted optimization to be more suitable for the next tool (ZIP in this case).

The spritesheet is compressed using TinyPNG.

I used as few files in the compiled version as possible, as each file adds at least 130 bytes to the final ZIP file – this can be a lot and it increases with file name length.

For the final ZIP file the rules dictate to be a standard ZIP file, so no 7zip or other advanced formats are permitted.

To optimize the final ZIP I used AdvanceCOMP’s AdvZIP which basically recompresses an existing ZIP file but keeps compatibility.

About 90% of the build process – starting from readable code to entry ZIP – was automated in a build script. This way I could track the effect of each changes on the final size. The rest was manual editing of code just before Closure Compiler whitespace removal.

Fun fact: the last ZIP before the submitted one was 13313 bytes, 1 byte over the limit. I saved that byte by changing the player name input from “Player name:” to “New name:”.

Final thoughts

I think Bokosan is the most polished game I’ve created until today (alone or in a team), it has the most content and feels the most complete. It also got a lot of positive feedbacks and it was really fun to catch my collagues playing it, trying to get the “A+” badge on all levels.

However, the game has not ranked in the Top 10 in Desktop nor Mobile category, in Server category it finished at 6th place and in Facebook special on 3rd place.

A huge thank you to Andrzej Mazur for organizing js13kgames competition once again, Ray Larabie for the Jostix font, and Markus Neubrand for Jsfxr!

101hero: Assembling the printer

The first part covers the short story of the printer, the contents of the box, a few tips and warnings about the ways you might damage your printer unintentionally (if you have not read these you should).

This part is about assembling the printer step by step.

First connect only the PSU to the controller and switch it ON and OFF, the red LED should light up when it is ON.

Now connect the motors and end-stops to the controller (do not assemble anything yet) and attach the SD card slot. The intended order of the pylons as well as the motor-end-stop pairings are below:

After connecting these put a simple “go home” file on your SD card and then power it up. The motors should start moving the carriages (all three at the same time) until one hits its end-stop. Then the other two should stop and only that should move back and forth triggering the end-stop a few times. After this the remaining two should do the same one by one.

If all three carriages hit the end-stops then congrats, you have working motors and end-stops, this is a good start! If not… well then you are in the unlucky group of quite a few people, including me. In this case check out the 101 Hero (Unofficial) Facebook group.

You can restart the procedure by pushing the reset button or power cycling the controller board.

Now on to assembling the printer!

At the top of the pylon arrange the red-black cable of the end-stop so it goes through the shaft:

At the bottom of the pylon the red-black cable should go through the shaft just like above and arrange the cables of the motor like on the picture:

Make sure for each pylons that the spring on the belt is tight to provide tension…

… the belts are properly on the wheel at the top…

… and the bottom:


If the belts are off the wheels try to put them back carefully. If that is not enough then you can loosen the motor a bit by loosening the two screws holding it in place (3mm Hex Socket aka Allan heads). If you have to remove the belt tensioner spring here’s a video how to put it back.

Next, assemble the bottom plate and the three pylons (4 pcs of M4x12 self-tapping screws (PH1 head) for each pylon):

And then add the top plate (2 pcs of M4x12 self-tapping screws (PH1 head) for each pylon, NOTE: the two inner holes remain empty on each end on the top):

And now fix the effector to the rods. The facing of the head does not matter but it can be useful to see the fan (to see if it is working) and the door (for change filament) from the front. The first screw…

… the second screw (you can safely leave it hanging)…

… and the rest:

Now stick some painter’s tape to the glass plate (you don’t need to cover the whole glass just make sure you have no overlaps of the tape) put it on the bottom plate and fix it in place using the paper clips like this:

Now connect the rest of the cables to the controller box:

Next step is to load the filament. The extruder assembly has a door you can open, this door pushes the filament to the extruder motor which is supplying the filament to the heated nozzle. Open up the door and put the filament in at the top of the extruder assembly, guide it into the tube after the motor, like this:

When completed close the door and tighten the screws (2 pcs M3x12 self-tapping screws (PH1 head)).

After completing this step the printer should look like this:

Which is a mess. The cable management is pretty much non-existent for the 101hero by default. People use different cable organizing methods, the most popular is the spiral wrap but personally I like the zip tie method which is nothing special just zip tying the cables at a few centimeters interval, like this:

After completing this step you should cut the ties short, of course. One more thing I did was fixing the bunch of extruder cable to the top plate to an unused hole like this:

You need to leave about 25 cm (10 inches) of cable between the fixing point and the extruder assembly so the hot end can reach the farthest point safely.

And that’s all about assembling the printer. The next post will be about how to calibrate the 101hero.

101hero: Hello

The 101hero is a pylon 3D printer that had a campaign on both IndieGoGo and Kickstarter with early bird prices of US$ 49 and retail price of US$ 99 on

First of all, the 101hero team’s goal was to create “The World’s Most Affordable 3D Printer” as they said and not the the printer you should start your 3D printing adventures with and this can be seen in a few places. Nevertheless, the printer is functional and the prints can turn out surprisingly nice if one is willing to spend enough time and don’t mind the hassle but if you’re new to 3D printing and you want a printer that works out-of-the-box, this one is not the best choice.

I backed the IndieGoGo run and have received the printer in January, 2017. I am new to 3D printing this is the first one I bought and the first one I ever printed with, In these posts I will share my experiences, tips I find useful and caveats.
The printer comes in two versions: the CV (Consumer Version) and DV (Developer Version). The only difference is that the DV has a USB port and can be connected to a computer while the CV can only print from SD card (which is not part of the package).

Assembling the 101hero is pretty straightforward but before getting started check all the components that should be in the box:

  • 3 pylon assembly – they are identical except for the length of the wires and labels, there should be an end-stop microswitch (to detect that the carriage reached the top of the pylon), two slide rods, a belt, a carriage (fixed to the belt, sliding on the two slide rods, fixed to effector rods) and a motor
  • 1 controller box
  • 1 SD card slot
  • 2 plates – one for the base and one for the top
  • 1 extruder assembly with effector – the “head”
  • 1 bunch of filament – the printer comes with black or white, I bought the green separately
  • 1 roll of painter’s tape – to help adhesion of the first layer printed
  • 1 glass plate
  • 3 paper clips – to fix the glass plate to the base
  • 6 pcs M3x10 machine screws (PH1 head) – for the carriage-straw/strand and straw/strand-extruder assembly
  • 18 pcs M4x12 self-tapping screws (PH1 head) – for pylon-base and pylon-top
  • 2 pcs M3x12 self-tapping screws (PH1 head) – for door fixing on extruder assembly (identical to the ones used for end-stops in early editions)

In early editions the end-stops are hitting against M3x12 self-tapping screws with PH1 heads, I have read that later they switched to Hex Socket (aka Allen) types.

Before assembling the printer I would like to tell you some basics and recommend to do further checks.

When the printer is powered it looks for a file called “101hero” on the SD card and starts to execute it (i.e. printing, moving, etc.). The file is a G-code file and has no extension, it is just “101hero” (when saving the file using Notepad on Windows to prevent it appending “.txt” change the “File type” drop-down to “All files (*.*)” or put the file name between quotes).

The button on the controller box simply resets the printer that causes it to re-initialize and looking for the file and execute it.

The pylons are identical except for the cable lengths and the labels that are on them, that is you can have them swapped and even replaced from a different package, they will work. One important note however – the end-stops are used to detect when the carriages reach the top of the pylon so the motor-end-stop pairs need to be kept consistent, if they are not then the controller will keep moving the carriage until you turn the power off.

A big warning: the power is not only sourced from the power connector but from USB as well – that is as long as your printer is connected over USB it will power the board – regardless of the power switch! Yeah, if you slide the switch to OFF the board will still be powered, although the printer will not operate properly due to the low current but you can damage the printer if you short something.

One more big warning: the controller has no flyback diodes to protect itself from inductive spikes. Simply put: only move the carriage slowly by hand because the motor generates current that will be fed back to the controller. If the current is too high (due to moving fast) it might damage your controller. Although I have not tested it yet, it might also be fed back over USB damaging your computer as well.

The printer has basically no customer support. As of March, 2017 the 101hero team is still busy shipping packages and really unresponsive to support questions, however there is a really active group on Facebook, the 101 Hero (Unofficial) and a forum at

Now it is time to start connecting things, meet me in part two.

Fun with Planets and a DSLR camera

I have a cheap fully manual Dörr Danubia f8/500mm lens that I bought back in 2012 for shooting the Venus transit. Since then I used it to take some Moon pictures also and when I am doing so I tend to use stars to find the correct focus – the smaller the star appears the better the focus.

In June I was out for shooting again. I mounted the lens, found some bright spot but despite all attempts I could not focus it into one point. I was wondering about what could I possibly do wrong until… no, that couldn’t be, could it? Could that spot not be a star at all?

A few pictures and corrections later I was astonished by the fact that I could capture a planet (other than our own, of course) with my DSLR and a cheap lens. Of course, the image quality was bad but, that spot was Saturn.


These pictures were taken directly from the camera, they are only cropped and stitched into one file. A few days later I spotted Saturn again:



And then I checked out Venus…


… and then Jupiter.


And I will not tell you what this is in the last picture:


Actually it is not just the Sun but Venus as well from the Venus transit on 6th June 2012.

All images above were just cropped but not scaled, therefore the size of the bodies can be compared to each other.

And since then I have a new hobby… :)


Pillow fight day 2015, Budapest

On 4th April, 2015 the 7th International Pillow Fight Day was held all around the world. In Hungary the Budapest UP! has organized the event to the Heroes’ Square which was a huge success in my opinion.

I have visited earlier Pillow Fight Days and have shot a few photos there, but now I thought creating a video would be more fun.

When I am making a photo or video I like to in the middle of the crowd. Given this, my 8 mm fish-eye lens and a try at recording the videos at 50fps, this is the result:

When watching it in full-screen with the default HTML5 player the “720p50” option should come up. If that’s not the case try this link or try to download the original video and watch it with your dekstop/mobile player.

This was the first time I used Kdenlive for video editing and I immediately loved its straightforward interface and workflow, also its ease at rendering to file – it is a really powerful yet simple editor, I can only recommend it.

Personally I like the outcome and I think I will experiment further.