10K Apartに参加した経験、または10 KBで40 KBのコードを圧縮する方法

少し前まで、Habréですでに10K Apartコンテストについて書いていました。これは、クライアントテクノロジー(HTML、CSS、Javascript、SVGなど)のみを使用して作成された、最大10Kの総量を持つ最高のWebアプリケーションの競争です。



画像



private_faceが2週間夕方行ったこのコンテストの私たちの仕事にあなたの注意を紹介したいと思います:「Fontanero」( スペインの配管工)と呼ばれるダンジョンクローラーのスタイルのアドベンチャーゲーム。





合計10,230バイトの3つのファイルのこの多様性。 メザニンで1.44MBのディスクを見つけた場合、144個のそのようなゲームを記録できます。

アプリケーションの性質(アドベンチャー)、ジャンル(ネットハックスタイルのダンジョンクローラー)、および設定(配管工が地下に降りてパイプを修理し、地獄に行く)を決定したら、計画を実現できるかどうかを判断するときです。 10K以内に保ちます。



郵便番号



コードの最初のドラフト(マップジェネレーターとゲームフィールドテンプレート)は、ゲームの3分の1でも10Kでは十分ではないことを示しました。 すべてをドロップするか、何らかの方法で使用可能なスペースを増やす必要がありました。



私は、低レベルのプログラマーとして、すぐにjsをzipに固定し、実行時に解凍する機能に非常に興味がありました。 最初の考えは独自のLZSSを書くことでしたが、もう少し簡単な考えが少し後に生まれました。その中のデータは同じzipで圧縮されるため、jsをPNGに入れます。 (後で判明したように、 このアイデアを思いついたのは私たちが初めてではありませんでした )。



テクノロジーを研究した後、パレットpngからCanvasを介して任意のコードをロードし、カラーコンポーネントの1つで文字をエンコードする機能を確認しました。 IE 9プレビュー(現在はCanvasもサポートしています)を含む、必要なすべてのブラウザーでテストが正常に完了しました。 成功しました。 8ビットパレットには256色を保存できますが、難読化ツールの後にはコード32〜94、および\ n(10)の文字のみがあります。 それらを256ではなく64の値にエンコードすると、大幅に節約できます(奇妙ですが、PNGはパレットの圧縮方法を知りません)。



したがって、将来のアプリケーションの構造が明確になりました。すべてのゲームロジックを含むPNGからjavascriptを復元し、必要なすべてのHTMLとCSSを動的に作成するスクリプトを含むHTMLローダーページです。 プロジェクトの最終バージョンでは、ローダーはアラート(「キャンバスなし」)を含めて850バイトを占有しました。 (古いブラウザのユーザーを白い画面の前に置いておくことはできません)。



難読化



Zipは、余裕のある実際のコード量を増やしましたが、それでもまだ十分ではありませんでした。 したがって、サイズを最適化する次のステップは、JSの難読化ツールの選択でした。



市場に出回っている無料のソリューションのうち、yuiコンプレッサーとgoogleクロージャーコンパイラーを選択しました。 もちろん、競争はグーグルクロージャーコンパイラー(以下gcc)が勝ちました。これは、正直、圧倒的に最高で、さらに警告が表示され、そのほとんどが役に立ちます。



gccをアドバンスモードで使用しました。このモードでは、未使用のコードを破棄し、すべての識別子を1文字または2文字に変更し、ブランチを再構築し、関数をインライン化し、バイトを節約するためにあらゆる方法でコードを台無しにします。



ただし、gccを拡張モードで使用する場合でも、最適化の余地はまだあります。 まず、gccはフィールドの名前を標準の名前に変更することを恐れています。彼の意見では、名前left, right, top, bottom, name, type, width, height



などです。 第二に、難読化後、コードには頻繁に繰り返される多くの単語「function」と「this」が含まれます。 お金を節約するために、@と `の文字を置き換えました。 同時に、ローダーは逆置換によって少し成長しました: replace(/@/g, 'function').replace(/\`/g. 'this')



そしてそのような処理の後のコードはかなり怪しいように見えました:

;`.g=n;`.K=`.v=o;`.F=@(d){var c=`.e;





しかし、それは価値がありました:一般に、交換ごとに、50バイトが取得されました。



CSSは、yuiコンプレッサーを使用して圧縮され、閉じ括弧の前にセミコロンをカットした後、javascriptの最後に配置されました(60バイトの節約!)。



ゲームの外観を決定すると、 private_faceに対する意見が分かれました。 私は古典的な2Dビューを提案しました:





Vova-2は、次のようなアイソメ図を主張しました。





したがって、さらに、単純な旧式のレンダラー(すべてはtextareaタグ内のテキストで描画されました)をスケッチし、ゲームロジックとマップジェネレーターを書き続け、Vovaは彼のアイソメをいじり始めました。 IE9が彼のために準備している驚きをまだ知りませんでした。 アハハハハハハハハハハ:((



情熱等尺性



private_face
アイソメの実装は次のように想定されていました:テクスチャが重ねられた長方形のブロックは、CSS変換のスキューとスケールによってアイソメ投影に転送され、その後、適切な場所に配置されました。



このソリューションでは、タイルごとに個別のDOM要素を作成する必要がありましたが、キャンバスに描画するよりもシンプルでコンパクトに見えました(そして最も重要なことは生産性が向上しました)。

さらに、DOM要素を使用することで、テクスチャを課すだけでなく、壁にテキストを簡単に書くことができ、これがゲームのキラー機能になる可能性があります。



しばらくして、プロトタイプの準備が整いました。 レンダリングは非常にコンパクトであることが判明しました(すべての描画はCSSでレンダリングされ、JavaScriptはブロックのみを配置しました)

そして、かなり良い画像を生成しました(Firefox 3.6では大幅に速度が低下しましたが):





人生は美しく、雲一つないようでした。 ただし、アイソメ図の概念に火をつけて、新しいInternet Explorer 9でCSS変換がサポートされていることを確認するために、1つの重要なことを忘れました。 IE9で変換を実装する唯一のオプションがマトリックスフィルターであることが判明したためです。 しかし、そのようなソリューションのパフォーマンスはまったくありませんでした。

一般的に、アイソメは放棄されなければなりませんでした。



基本に戻る



3Dバージョンが失敗した後、単純なタイルバージョンに戻すことにしました。



すべてのタイルは通常のGIMPで描画され、4ビット(16色)パレットでPNGスプライトに結合されます。その後、後者は-bruteスイッチを使用してpngcrushでつままれました。



壁と床のタイルにbox-shadowプロパティを設定することで、写真にボリュームを追加することができました。 ただし、これはInternet Explorer 9のパフォーマンスに予想外の悪影響を及ぼしましたが、他のブラウザーは通常の速度で動作しました。 IE9ユーザーをブレーキでイライラさせないために、このブラウザーではデフォルトで無効になっているゲームインターフェースに「シャドウを有効にする」オプションを追加する必要がありました。 IE9のbox-shadowパフォーマンスのリリースが修正されることを期待しましょう。



2Dへの移行には良い面がありました。レンダリングコードの総量はアイソメバージョンと比較して大幅に削減され、最終的には空き領域を使用して、パイプ修復ミニゲームをゲームプロセスに追加しました。



エピローグ



これは、このゲームをどのように作成したかの簡単な歴史です。 このプロジェクトに取り組み始めて、私たちは誰も、厳しい制限で作業して貴重なバイトを節約することがとても面白いとは思いませんでした。 私たちは膨大な数のファンを獲得し、10kはそのタスクで素晴らしい仕事をしました-ウェブを再活性化します。



物語以外にも、このプロジェクトの作業中に解決しなければならなかった他の多くのタスクがあります。 たとえば、接続チェック付きのレベルを生成するためのコンパクトなアルゴリズム、廊下に沿って歩くことができ、あまりに馬鹿に見えないモンスターを移動させるための超コンパクトなアルゴリズムなど。



そして、このトピックの最後に、約40Kのコードを10Kに詰め込むことを可能にする最適化の短いリストをもう一度示します。

CSS最適化:
  1. YUI CompressorによるCSSを文字列にパックして、結果をソース.jsファイルに追加します。
  2. 各ルールブロックの最後にあるオプションのセミコロンを削除します。
  3. 結果のスタイルシートをJSに挿入します(つまり、css + jsを1つのアーカイブブロックにパッケージ化します)。
JS最適化:
  1. 難読化の前:フィールドをleft、right、name、typeなどの名前に置き換えます。 他の人に(GCCはアドバンスモードでも名前を変更しないため)
  2. 拡張モードでのGCCコードの難読化。
  3. 難読化後:関数とこのキーワードを1文字の略語( '@'および '' ')に置き換えます。
  4. プロトンコンテナカプセル化 PNGパッケージ
画像の最適化:
  1. すべての画像は1つのスプライトに保存されました。
  2. パレットの色の数は16に制限されていました。
  3. 変更後、最適な圧縮を確保するために、-bruteオプションを使用してpngcrushでファイルをピンチしました。


小さな更新:今日、人気のある需要により、オペラのミニゲームの表示を修正しましたが、これは競争の要件ではありません。 10K Apartへの途中のパッチ。



ご清聴ありがとうございました。 コンテストページでゲームを評価していただければ幸いです。

PS クリック、続き。

PPSコンテストは終了しました。ありがとうございました!



All Articles