Encryption algorithms and sharing levels on a tweet

4
skymen's avatar
skymen
  • 15 May, 2018
  • 955 words
  • ~4-6 mins
  • 1,532 visits
  • 1 favourites

The catch

A very cool member of the Construct community named LootBndt (go follow his twitter, he's truly amazing: twitter.com/LootBndt ) came on the discord server asking a pretty simple question:

Now encrypting level data and sharing it is fairly easy. Construct already allows you to save tilemap information as JSON. The key word here was "Twitter".

As we all know, twitter has a limit for how many characters you can post in a single tweet. It's not as bad as a few months back, because now Twitter allows you to post up to 280 characters in a tweet. So we need to make sure that the whole data doesn't take more than 280 characters.

Saving tilemap data as JSON has two main issues:

  1. The JSON format has characters for syntax and delimitting data which takes up space
  2. Saving as JSON saves everything about the tilemap, including data that we may not use, like tile state (rotated, flipped etc)

I found it a cool exercice to think about how we could save as much space as possible while still allowing for quite some room to save different things.

Of course, I need to create a lossy algorithm because I want to remove every bit of data that I know won't be needed and only keep what is really important.

This means that within some boundaries, if we don't use the lost data, the algorithm acts just like a lossless one.

The TackerTacker solution

Before I start talking about what I did, I'd like to point out what another great developer of the community said.

Follow his twitter as well, he's really cool and regularly gives great tips for Construct: twitter.com/2xTacker

Now this dude made a pinball game a few months ago with a similar level sharing technique. However his approach was extremely different:

Instead of trying to encrypt data and post it on a tweet, he decided not to encrypt it at all, and put it inside the link that opens his game as a link parameter that you can then retrieve using the Browser plugin.

Why do that? Well first it's much easier to set up, and twitter automatically shortens any link to about 20 characters no matter how long the original link is.

Why I decided not to do that? Well cause I really wanted to make an ecryption algorithm. Also really long links can be a problem when sharing outside of Twitter: Not every platforms shortens link.

The algorithm

The algorithm is fairly simple.

First I needed to know the minimal information that I needed on the tilemap.

I decided that all I needed to make it work properly was the map's width (in tiles) and the tile IDs.

The first limitation

I wanted each tile to take a minimum amount of space. So I figured that a character per tile could work well.

That meant that there would not be more than 255 different tiles or the algorithm would break.

Well...

There are non printable characters.

And there are special characters.

And there are characters that can't really work well inside strings (unless they're escaped which means that I need to add another layer of processing on it).

In the end I decided to add an ALIGN variable that would define which ASCII character would define the 0. I went with 65, aka 'A'.

That leaves us with 190 different tiles, which is fairly large for a level based game.

The second limitation

Because I remove all the data about tile states, that means that I cannot use anything that involves flipping or rotating tiles. This is not a problem as most people forget about them anyway.

The implementation

This is simple, the algorithm encrypts the tilemap in this format:

The number represents the tilemap's width, aka when to wrap

The string is the data for the tiles.

Encrypting and decrypting is pretty easy at this point:

You just need to go through the string of characters character by character, add the right tile by getting its ASCII value and removing the ALIGN value from it, and wrapping when the X counter reached the width.

The whole process took about 1h to implement and it's not the most interesting part. The coolest part about encryption is the logic and research behind it. Understanding how to make it work more than actually making it work.

How to make it better

Now the algorithm is far from perfect. It could be better by running a huffman encryption algorithm on top of the final result. This would shorten the final string even more and allow for way bigger levels. Now this wasn't used because LootBndt's style is fairly minimalist and he doesn't use as many information as someone else would.

Encrypting it on a picture?

LootBndt did something pretty nice with my capx. He put the final string inside a picture and tried having it contain all the data

twitter.com/LootBndt/status/995461313504608256

The main issue he encountered was that Twitter (and pretty much any image uploading service) compresses the picture to save some place, so the data was lost in the process. Now this works as long as he finds a way to force Twitter not to compress the picture, but I find it interesting to try and encrypt the string in a picture to survive JPEG and PNG compression. However I doubt that this will be an easy task using only Construct 2.

The capx for those interested

Here's the link for the capx if you wanna take a look at it:

cdn.discordapp.com/attachments/225550155531812865/444878984837333002/LootTilemapSave.capx

Subscribe

Get emailed when there are new posts!

  • 6 Comments

  • Order by
Want to leave a comment? Login or Register an account!
  • Great blog post and thanks for the shout-out <3 ... I did however encrypt my data as well :P

    • Btw if someone wants to check it out here is a link with attached level data t.co/PYNRzRYAwI

      If you click the link and look in your browsers adress bar you'll see something like this

      https://nativepixels[dot]itch[dot]io/super-pinball-maker?ver001_M4FwpmA2DGCGDWYg_AwOgjMCsBsIExmq... etc, i couldn't post the full link because its too long :(

      the "?ver001_" is the version indicator and what i'm looking for in my code to know if someone is coming from a link with an attached level or not.

      The long gibberish after that is the entire level in encrypted form.

      If you'd go to the same page without the gibberish ( nativepixels.itch.io/super-pinball-maker ) then the game would start with an empty default level and you can press M for menu to create your own level, have fun :)

    • Haha well perfect, I didn't know! Very nice :D

  • I´ve been tinkering with this idea around a bit (in C3 tho)

    First things first: You can prevent Twitter from compressing the image by uploading a png that contains transparency (even if it´s just 1 pixel that has 99% opacity)

    Further what I did is to write a little js (with the javascript plugin) that loads the image into an offscreen canvas, then parses the individual pixels. Each pixel holds the information for 4 tiles (RGBA values), so an image with just 100x100 pixels would hold the information for a whopping 40.000 tiles (or a 200x200 tilemap)

    Also since each RGBA value takes 0-254 this means there´s 255 possible different tiles (actually 254, since Alpha at 0 removes also the RGB values) OR one could use it to also store the 8 different tile configurations (flipped, rotated,....) for 31 different tiles.

    Using rbga values is pretty neat, since tiles in construct are referenced by a number and we can directly use that number instead of having to use encryption.

    • Running out of characters, lul.

      What is left to do is to create something that parses the tilemap and generates an image based on it, that then can be shared. It´s a very raw prototype, but generally I´d say the idea is entirely possible.

      In C2 there´s also the canvas plugin (from R0j0hound) that has this option to pick a color from the canvas and also draw to a canvas, makes things a little bit easier I guess but haven´t tested it.

      Fun thing, one could even go ahead and load in random images to generate maps, though that would require a bit of tweaking so it isn´t completely unplayable. You could snap a picture of your cat and check out what level it generates.

      • Thank you for the comment!

        Indeed it's really interesting to save and load levels using pictures.

        I thought of using canvas to process image data or create one based on a level.

        I never used the Javascript plugin so it's really interesting to know that it works so well!

        And generating levels based on images is an amazing idea, I'd love to see an experiment based on that :D.