8KB JavaScriptマリオもコードリーディングしたけど……

14KB JavaScriptマリオを作ったJacob Seidelinさんが自らの記録を更新しました。今度は8KBです。
 8 kilobytes of Mario


JavaScriptPNGに埋め込んでるそうです。何を言ってるのかまるで分かりませんね。とりあえず前回と同じように読んでいきましょう。
 m.js 324B
 m.png 7.7KB


JavaScriptのソースは3行です。頭がおかしくなりそうです。読みやすいように適当に改行とインデントを入れるとこんな感じ。これで全文です。

var o = new Image();
o.onload = function() {
  var r = "", s = 119,
  c = document.createElement("canvas");
  c.width = c.height = c.style.width = c.style.height = s,
  t = c.getContext("2d");
  t.drawImage(o,0,0);
  var d = t.getImageData(0,0,s,s).data;
  for(var i = 0; i < d.length; i += 4) {
    if(d[i] > 0)
      r += String.fromCharCode(d[i]);
  }
  eval(r);
  Mario(true,1)
};
o.src="m.png";


まずImageオブジェクトを作ってます。

var o = new Image();


キャンバスの縦横サイズを設定するだけの処理ですが、変数s(=119)の値を一気に代入して文字数を節約しています。

  c.width = c.height = c.style.width = c.style.height = s,


今回のキモはここです。画像データを端から読んでいって文字列として連結します。すべて終わったらその文字列を実行(eval)しちゃいます。つまり本来ピクセルデータを格納するところにJavaScriptのプログラムを無理やり突っ込んでるわけです。

  var d = t.getImageData(0,0,s,s).data;
  for(var i = 0; i < d.length; i += 4) {
    if(d[i] > 0)
      r += String.fromCharCode(d[i]);
  }
  eval(r);


ちなみにこの時の連結文字列を表示してみると、おなじみの(?)14KB Marioのソースが現れました。めでたしめでたし。

var Mario=function(AF,P){var Y=parseInt,U=setTimeout,AH=function(c){return(省略)


そんなわけで前回の14KBのプログラムを画像として圧縮したら8KBになったよ、というのが実状なわけで反則技ではありますが、ちょっと面白いアイデアですね。