📜 ⬆️ ⬇️

How to get the most out of code minification

Have you thought about the fact that if you use a variable instead of this in the constructor and methods, then after minification, the saving of bytes will start from the fourth this ?


 //     this.this.this.this. var s=this;ssss 

I used this and some other hard-hitting ways to participate in the js13kGames contest, the purpose of which is to write a game, the size of which will not exceed 13 kilobytes.



The game is almost ready, it remains only a couple of days not to sleep ...



What kind of competition?


js13kGames, it seems, is not yet very popular in Russia, therefore, briefly:



To the detriment of readability


The above example with this does not add beauty to the code, but in constructors and methods, where this used intensively, this approach saves 3 bytes on each conversion, starting from the fifth. For example, in one of the designers was 39 pieces this . Replacing them with self turned out to save more than 100 bytes.


I think in the whole project only these replacements saved more kilobytes.


Another method, suitable, perhaps, only for such small sports projects is a large number of global variables and functions. Almost all of the general-purpose tools ( random() , getUniqueID() and so on), as well as many specific things (like the function that turns off anti-aliasing when scaling in the Canvas context) are in the global scope. Here, of course, you should pay special attention to the names of these tools so that the code is as self-documented as possible.


 tr() // tools.random r() //   

When minifying, all these functions will occupy one character (instead of, for example, three, if we put them in an object), which gives quite impressive savings: the random() function alone occurs in the code 77 times, and its “globality” saves 150 bytes .


Quite a specific situation: I decided to store the sprites in the gifs encoded in base64, and noticed that all the resulting lines begin with R0lGODlh . There were a total of 14 sprites (although, according to the original idea, there should have been more), and by carrying out this initial piece of string to a function that turns lines into Image objects, I was able to save approximately 100 more bytes.


The last nuance, which, perhaps, even helps a little with the perception of the code - it is a hard need to follow the principle of DRY . Why is it possible? Because the code sometimes gets too fragmented. Almost every few lines of code that repeat at least twice become candidates for selection into a function.


Biting off the gameplay


Some amount of code was avoided by simulating the surface on which the character runs: in fact, this is the boundary of the level, and the texture of the earth is simply “off-screen”. Unfortunately, because of this decision, the platformer, in fact, almost ceased to be a platformer, but there was no time to correct this fundamental oversight.


Some units, which, although they took very little space, turned out to be too inadequate, fall into the category of "minus to playability".


The main example: a stone, designed to diversify the landscape, could not become a surface on which to jump. Instead, it pushes the player away and deals damage. I had to go for a quick hack to get out: the stone turned into a rat's lair, and if you start beating on it, then a rat appears every five blows from there.


Animation


As I said, all sprites are stored in GIF files wrapped in base64. They are the minimum size, and when creating an animation, they increase by a factor of 16 (this is the size of the in-game “pixel”). The object with the description of the sprite is also used by the unit designers for sizing; that is, it’s not the animation that fits the size of the unit, but the other way around.


Unused


At the very beginning of one of the ideas, it was everywhere to replace true and false with 1 and 0 , but, in the course of development, I completely forgot about it, and remembered only at the end. Fortunately, I didn’t have to do this: by the time the work was sent to the competition, it was of a size, and I can’t even imagine how much horror I would have to go through using such an unreliable tool.


To create music, I used the notation, where every two characters represent a sound: a line is a note, a number is the denominator of its duration (zero instead of a line is a pause). The actual duration in milliseconds is calculated by dividing the duration of the whole note by the denominator of the duration of the note.


 notes: [ 'A4', 4, 0, 8, 'G4', 8, 'A4', 8, 'A4', 16, 'G4', 16, 'C5', 8, 'D5', 8, 0, 4, 'A4', 8, 'A4', 16, 0, 16, 'A4', 8, 0, 8, 'G4', 8, 0, 8 ] 

The plans were to reduce the recording volume of the soundtrack by introducing “samples” - re-used musical phrases, but this didn’t come to that, since writing the music had to be done at the last hour before clicking on the Submit button, and there could no longer be any sound variety.


Conclusion


No matter how ridiculous, most of these optimizations for compression turned out to be superfluous: even with the original names of global variables, the game file turned into a zip-archive of 10.1 KB in size (with the index.html size of 31.9 KB). What really was not enough is time. Especially it was not enough for level-design, intelligible soundtrack and at least a small number of playtests.


I already participated in js13kGames last year, but that time I started working two days before the deadline. Therefore, and also because of smaller experience, the first pancake left a lump. This year I even have something to be proud of , although, of course, gamedev is far from the present heights.


For the minification enthusiasts: the code is available on GitHub .


It is interesting to learn about your tinycode projects, share in the comments!


')

Source: https://habr.com/ru/post/310830/


All Articles