» Mozilla Hacks ブログ翻訳

js13kGames:コードゴルフ型ゲーム開発大会

この記事は “js13kGames: Code golf for game devs” の抄訳です。

13KB。KB なんて最近では雀の涙ほどのデータ量ですが、ゲームの歴史を遡れば先駆者たちはとんでもない制約の中でゲームを作ってきたということに気づくはずです。

一例を挙げると、皆に愛されたアタリ 2600 の RAM は、ほんの 128 バイトしかなく、カセットをさしても 4 KB 増えるだけでした。ことわざにもある通り、制約は創造の母です。そんなゲームのコンペティション、js13kGames の季節がやってきました。これは zip 圧縮して 13,312 バイト以内であることを条件に、ゲームの創造性を競う大会です。

HTML5 ゲーム開発者向けの大会

js13kGames は HTML5 でゲームを作る開発者のための大会で、2012 年より毎年開催されています。作成するゲームのファイルサイズが 13KB に制約されている点が特徴的な大会です。8 月 13 日から 9 月 13 日の 1 月間で、与えられたテーマのもとにゲームを作成します。2015 年のテーマは「逆転」(Reversed)でした。

js13kGames のロゴ

旧友とスポンサーの助力により、多くの景品が用意されました。達人であることを示す盾や、無料の T シャツ、その他のグッズが世界中に無料で送られました。そうはいっても、参加者の唯一の目標は勝利そのものです。js13kGames コミュニティに参加することで得られるものはたくさんあります。詰まった時の助けや、ツールやワークフロー、TIPS、技巧といった知見が共有されるでしょう。そして限られた期間でゲームを完成させる体験は、あなたの腕を大いにあげることになるでしょう。

昨年の優勝作品

13KB は低解像度の作品であっても十分とは言えないファイルサイズです。登録されたゲームを紹介したページの小さいスクリーンショットでさえ、そこに登録されているゲーム自体より大きいなんてことはよくあります。それでも、その素晴らしさに驚くことになるでしょう。去年の優勝作品の中からいくつかを紹介します:

こんなものをどうやって実装したか不思議に思いませんか?私は優勝者にインタビューをして、その秘訣をいくつかを共有してくれるようお願いしました。そしての結果、極限まで制約された環境下でゲームを作るために、彼らが使ったツールやテクニックを共有してもらいました。全てのゲームは GitHub で公開されています。それらを見れば、彼らが何をしたかを詳細まで知ることができます。

RoboFlip

RoboFlip のプレー画面

Eoin McGrath が RoboFlip を作った際のワークフローについて、次のように述べています。

最終的には zip でゲームを提出します。複数のファイルを圧縮するより、単一のファイルの方が効率良く zip 圧縮できます。だから全画像をインラインで記述し、JavaScript をミニファイして、全部のスペースを除去するのが最も最善でした。Grunt や Gulp のようなタスクランナーのおかげで、このプロセスのほとんどの部分を自動化できました。詳細は Gulpfile を見てください。単に gulp buildと叩くだけで、面倒なことが全てすみ、どれだけのサイズが残されているかがわかるようになっています。

gulp build を実行して、ファイルが圧縮され、使用可能な容量が表示されている。

グラフィックス

最初に高解像度のスプライトを、アニメーションフレーム付きで利用することは諦めました。単純化が鍵です。多くのものはプロシージャルに生成されるか、SVG を利用しました。レトロなピクセル感が好きなので、まず Gimp で全ての画像を 6×6 ピクセル程度の低解像度で作成しました。それらを base64 でエンコードし、canvas に再描画することで拡大しています。

利用されているスプライト

他のすぐに使えるテクニックには、不透明な色を白に変える関数です。

通常状態の絵を、関数で白くすることでダメージを受けた状態を表現している

これで全てのスプライトに対してダメージを受けた状態のフレームを効率的に用意できます。

サウンド

音のないゲームはカフェインのないコーヒーみたいなものです。ファイルサイズの制限から、.mp3.ogg ファイルなんてただの1つも使えません。jsfxr という便利なライブラリを利用することで、ゲーム中で利用する 8ビットのようなビープ音を生成しています。

音楽という点では Sonant-X library を使ってサウンドトラックの基本を作ってもいいでしょう。どんなものかはこのすごいデモを見ればわかるでしょう(まず “Play Song” を押して初期化する必要があります)

Road Blocks

js13kGames が好きな理由の 1 つが、人工的に課せられた制約です。これは言い換えれば達成可能なものだからです。そうオーストラリア出身のゲーム開発者 Ash Kyd は書きました。

インディーの開発者として、終わりのないプロジェクトをやることで、どんどんはまってしまい、最後には見せるものが何もないという状態になってしまう可能背があることに気づきました。でも厳しい制約は何を成し遂げられるかという点で創造的にしてくれます。

Road Blocks のプレイ画面

ファイルサイズへの制限のおかげで、Road Blocks は本質的にシンプルなゲームになり、多量のコーディング作業を必要としませんでした。その結果として、期間中の多くを試遊とゲームの改良に費やせました。その結果、ひと月後にはとても質の高いゲームが完成しました。

Behind Asteroids – The Dark Side

js13kGames は WebGL や Web Audio のような優れたテクノロジーを見つけて実験し、スキルを磨くのにとてもよい機会です。13 kB の制限のおかげで、フレームワークの陰に隠れることもできません。また画像も使えないため、それらのプロシージャルな生成にトライしなくてはいけません。だから自分次第で、自分にあったやり方や技巧を見つけられるのです。すぐに技巧に走ってはいけません。まずプロトタイプを作ってから、最後にコードを圧縮するのです。

そうゲーム開発のベテランであり、js13Games の優勝者でもある Gaëtan Renaudeau はアドバイスしていました。

Behind Asteroids - The Dark Side のプレー画面

面白いテクニックの一つに、ファイルサイズを小さくするためにオブジェクト指向的な書き方を避けることがあります。その代わりに関数と、タプル型としての配列を利用しました。私はこのテクニックを、前身の js1k に参加するより前に使ったことがありました。

js13kGames に参加して 3 年になります。そして毎回 WebGL を楽しんできます。2015 年の作品は Asteroids のリメイクです。このゲームでは宇宙船をコントロールすることはできません。そのかわり小惑星を送ることがでいきます。これが私なりの「逆転」の解釈です。

デスクトップでは、このベームはタイピングゲームとなります。それぞれの小惑星に割り振られている文字を、適切なタイミングでタイプすることでゲームを進めます。モバイルではシンプルなタッチゲームとしてプレイできます。

このゲームは、初心者から熟練のプレーヤーまで、さまざまなレベルの人が楽しめます。プレーヤーは AI アルゴリズムによってコントロールされる宇宙船の乗組員ですが、実際には小惑星をコントロールしてその宇宙船を破壊しなければなりません。

ゲームの描画方法

このゲームの描画はハイブリッドで行われています。まず canvas 上に基本的な 2 次元グラフィックスを描画します。それを WebGL で複数の後処理を加えることで描画を行っています。

2 次元グラフィックスではパーティクルとなる円や、宇宙船や隕石となる多角形、プロシージャルなフォントとして利用する線を描画します。なおこのフォントで使える文字はハードコードされています。これらは赤、青、緑のいずれかの色をつかって描かれます。これは、例えば青で塗られた円に対してのみ特別なグレアイフェクトをかけるといったような、グループに分けての後処理を可能にするためです。これはモノクロなゲームで使える、異なるものを 1 つのテクスチャにまとめて最適化するための面白いテクニックです。

さまざまなイフェクトが WebGL を用いた後処理として実現されています。詳しくはこちらの記事に述べましたが、この最終ステップの最大の目的はオリジナルのアーケードゲームで使われていたベクターグラフィックスの再現です。

アーケードゲームのスクリーンを模して表示されるマップも、背景に追加されます。これは全てがフラグメントシェーダによって生成されています。

まとめ

コードを小さくするためのテクニックは比較的よく知られたものから、無名のものまで無数にあります。Turs+ Game Development に HTML5 ゲームをミニファイする方法のまとめが掲載されていますし、js13kGames Resources にもツールやマテリアルのまとめがあります。

この記事で js13kGames の概要と過去の優勝作品が使っていたコードゴルフテクニックがつかめましたか?今年のトーナメントに参加されたいですか?数日後の 8 月 13 日に始まります(訳注:元の記事は 2016 年 8 月 8 日に公開されました)。ぜひこちらから参加してください。コード書くのに遅すぎた、なんてことはありません。

Andrezej Mazur について

HTML5 ゲーム開発者で、Enclave Games のファウンダー。Gamedev.js という週間メルマガの発行人で、HTML5 ゲーム開発者向けのコーディング大会である js13kGames の発起人。新しいオープン Web 技術について技術講演を行い、WebVR に夢中になっている。

Andreij Mazur による他の記事はこちら

Firefox マルチプロセス化の今後

[この記事は米国 Mozilla Future Releases ブログの記事 “What’s Next for Multi-process Firefox” の抄訳です。]

Electrolysis とは Firefox のプロセスを複数に分割することによりブラウザのレスポンス性、安定性、そしてセキュリティを向上させる Mozilla のプロジェクトのコードネームです。この取り組みの最初のフェーズは、 Firefox のプロセスを UI の処理とコンテンツの処理とへの分離です。

このマルチプロセス化を可能にするアーキテクチャの第1段階が、Firefox 48 を利用している一部ユーザに今週から提供されます。これは Firefox 史上最大の変更でもあるため、ゆっくりと行う必要があります。 Firefox 48 では、テスト段階で正常な動作が確認されているユーザクラスを対象にし、その中の 1% のユーザに対して Electrolysis を有効にします。対象者のデータで安定性とエンゲージメントを確認し、問題がないか様子を見ます。この初期段階で問題が起きなければ、このユーザクラスの100%にまで徐々に対象者を拡大していきます。これは、全 Firefox 48 ユーザの約半数となります。

index2

アドオン

Electrolysis のベータテストに問題がなければ、 Firefox 49 ではマルチプロセスとの互換性が確認されている一部アドオンを利用しているユーザに対象を拡大します。 このテストでも問題が起きなければ、 Firefox 50では対象を更に拡大させ、 Electrolysis との互換性があると表示しているアドオン、あるいは互換性を保証する新しいバージョンの WebExtensions add-on API で制作されたアドオンを利用しているユーザも範疇に含めます。ゆくゆくは全ユーザを対象に Electrolysis を有効化しますが、これに伴い互換性のないアドオンは機能しなくなる可能性があります。そのため、アドオンをアップデートし常に最新版を利用することが非常に重要になります。

アクセシビリティとタッチスクリーン

マルチプロセスに関する次の大きなアップデートは Firefox 51 を予定しています。ここでは Firefox をタッチスクリーンで利用しているユーザ、アクセシビリティ機能と併せて利用しているユーザ、そして RTL (右から左へ記述する)言語環境で利用しているユーザを対象に Electrolysis を有効化します。これで重いページのロード途中でもレスポンス性を失わない UI を可能にする Electrolysis 展開の第一フェーズが終了します。

しかし、これで終わりと言う訳ではありません。

コンテンツのマルチプロセス化

第二段階では、コンテンツのマルチプロセス化を行います。第1段階でコンテンツと UI の処理を分割することで、コンテンツの読み込みが UI の反応性に影響が出ないようになりました、次の段階ではコンテンツのプロセスを更に分割します。これにより、たとえば一つのページが重くても、他のタブでのページの読み込みが遅くなることがなくなります。この機能は既に開発を進められており、2017年の前半にリリースされる予定です。

並行してコンテンツ処理のサンドボックス化も進めています。 サンドボックス化によって、 Web コンテンツからのブラウザや OS へ対するアクセスを制限できます。これはFirefox ユーザを様々な危険性から守ることになります。テストが正常に進めば、この機能を今年中にお届けできる見込みです。

 index1

アドオンのプロセス分離

マルチプロセス化に関するプロジェクトの最終段階は、アドオンの別のサンドボックスへの分離です。 コンテンツのマルチプロセス化やサンドボックス化がパフォーマンスやセキュリティの向上に繋がるのと同様に、アドオンを別のプロセスに分離することで、アドオンに起因するブラウザや Web の速度低下や、エクステンションを通して起こる Firefox への一部攻撃を防げるようになります。これは、まだプロジェクトの初期段階にあります。

index

Electrolysisは膨大なプロジェクトであり、完了にはまだいくつものリリースが必要となります。しかし作られた土台は強固なものです。エンドユーザにリリースされ始めたこの第一段階をベースに、さらなるレスポンス性とセキュリティの強化を向こう数カ月に渡り開発を続けていきます。そしてこれは、競合である他のブラウザに比べて Firefox の優位性である メモリ消費の抑制を保ったまま行っていきます。

Firefox 史上最大のアップデートに関しては、今後もこのブロクや他の Mozilla 関連のブログにてお知らせしていく予定です。

Firefox に組み込まれた Rust

この記事は “Shipping Rust in Firefox” の抄訳です。

まとめ:Firefox 48 には、Rust で書かれたコードが初めて含まれます。以降のバージョンにも Rust での実装が予定されている部分があります。

Mozilla ❤ Rust

Mozilla リサーチが Rust の開発をサポートしてから 7 年が経とうとしています。当時は小さくも献身的なコミュニティに支えられる、野心的で実験的な研究プロジェクトでした。長期の開発と研究にもかかわらず、Rust の基本原理は変わっていません。ステムプログラミングの生産性を上げ、ミッションクリティカルなソフトウェアにおけるメモリ由来の脆弱性を低減し、さらには並列アルゴリズムをより扱いやすくするためには、安全な C++ の代替物が必要である、というコアチームがもともと抱いていたビジョンこそ Mozilla が Rust プロジェクトを支援し、それを製品に利用する主な理由です。

コミュニティの盛り上がりも理由の一つです。Rust の提供する安全性と、モダンな機能は新たに人々をシステムプログラミングへと向かわせています。コミュニティによる開発をミッションとする Mozilla にとって、その輪を広げることは極めて重要です。

そして重要なマイルストーンを達成しました。それは Firefox 48 です。これには Mozilla による最初の Rust を利用した全デスクトップ環境向けのコンポーネントが組み込まれています。Android 版でもすぐにサポートされます。

メディアスタックへの組み込み

Mozilla で Rust を最初に使い始めたグループの 1 つがメディア・プレイバック・チームでした。動画や音声といったメディアは、Web 体験の中核であることに疑問を持つ人は少ないでしょう。興味のない人にとっては明白ではないでしょうが、例えばこのシャボン玉をはじくカメレオン、みたいな動画を再生するたびにブラウザの内部では何が起きているでしょうか。動画のデータは複雑なフォーマットでやってきます。そしてそのデータは、信頼できない第三者によって作成されています。そのためメディアデータを利用して、 Web ブラウザのメモリ管理に関するバグに対する攻撃も存在します。

このような背景により、Rust のようなメモリ安全なプログラミング言語が必要とされました。Rust によって、悪意をもっている可能性のある Web 上のメディアコンテンツから守るための術が追加され、Ralph Giles と Matthew Gregan によって Mozilla 初の Rust メディアパーサが作成さ入れました。そしてこれこそが、Firefox に導入された最初の Rust コンポーネントなのです。Rust コミュニティにとっても、これは大きな業績となります:Rust で書かれたプログラムが億人単位でいる Firefox ユーザに利用されるのです。先立つ調査で、Rust コンポーネントは置き換え対象である C++ のコンポーネントと全く同じ振る舞いをしていることがわかりました。しかもメモリ安全に。

Rust コードに問題が1件もなかったことを示すデータ
10 億人以上が利用したにも関わらず、Rust で書かれたコンポーネントには 1 件も問題が起きなかったことを示す統計

今後にご期待ください!

コンポーネントを実装した Ralph Giles と Matthew Gregan、Rust が組み込まれた Firefox をビルドするためのツールや環境構築を行った Nathan Froyd、Nick Nethercote、Ted Mielczarek、Gregory Szorcm、Alex Crichton。 この到達点に達するために働いた彼らに、大きな感謝をしたいと思っています。

Rust は、それ自身が活発で素晴らしいコミュニティの産物です。問題の発見設計実装これらに代表されるすべてのことに対する世界中の Rusticean の貢献なくして、今日はありえませんでした。私自身も Rusticean として、Rust を使う人を増やしたいと思っています。始めるなら今です。そして可能なら Rust を使った Mozilla のプロジェクトに参加してください

Rust が Mozilla の製品に使われる。これは長い旅の最高点のように見えるかもしれません。でもこれは第 1 歩なのです。今後にご期待ください!

Dave Herman について

Mozilla リサーチの主任研究員。戦略ディレクターも兼ねる。

Webサイト:calculist.org

Dave Herman による、その他の記事はこちら。

JavaScript エラーを簡単に調べられるようになりました

この記事は Helping web developers with JavaScript errors の抄訳です。

プログラミングをしていてとてもイライラするのがエラーです。エラーを表す短いメッセージがコンソールに出ると、それまでの午後全て、いやその日 1 日、ひょっとするとその週全てが台無しになってしまいます。例えば “undefined is not a function” と表示されたら、イライラを鎮めにコーヒーを淹れにいくといいかもしれません。

真に正しくそして唯一の JavaScript のエラー処理を実現していたとしても、また神速で $search_engine にコピペができたとしても、エラーに関する役立つ情報を探すことは面倒なものです。

本当はそんなことをする必要はないんです。いくつかのプログラミング言語、例えば Rustなどは、ただエラーが起きたことを報告するだけではなく、それ以上の情報をエラーレポートとして表示します。

このたび MDN コミュニティの力を借りて、Firefox の コンソールにそのエラーを解説するページへのリンクを表示する機能を追加しはじめました。

コンソールに表示されたリンクをクリックすると、そのエラーを解説する MDN のページが表示される

この機能をつかえば、より高速にデバッグができ、知識が少なくても JavaScript のエッジケースについて多くのことを学べるようになります。とくに JavaScript 初心者の方にとって役立つ機能になれば、そして解決策がわからないままコーヒーブレークを取りつづけることが減れば、と思っています。

JavaScript、DOM、その他のエラーについて、全て解説するのは量も多く、とても大変な作業です。そのため、いまのところは最も良く見るエラーのみ注力しています。この機能の充実に助力いただける方は、ぜひ MDN のコミュニティをご覧になってください。エラーに関する解説を書くことは、JavaScript の興味深い側面に詳しくなる良い機会となるでしょう。

この機能は Firefox の Nightly ビルドでご利用になります(訳注:Developer Edition の最新版でもお使いになれます)。また MDN の JavaScript エラーのページでも、エラーに関する説明をご覧になれます。

Florian Scholz について

Florian は MDN のテクニカルライター兼、WiKi を直す小人です。2010 年に Mozilla に参加。ドキュメンテーションとオープン Web 技術を広く届ける活動に従事。ドイツのブレーメン在住。

Florian Scholz によるその他の記事はこちら。

Morgan Phillips について

Morgan は JavaScript エンジンのハッカーで、自称インターネットフーリンガン。オレゴン州ポートランド在住。コンパイラ、OS、linuxpoetry.com にできの悪い詩を書くことに興味がある。

Morgan Phillips によるその他の記事はこちら。

Developer Edition 49:ネットワークモニタでのスタックトレース表示、など

この記事は Developer Edition 49: Network Request Stack Traces and more の抄訳です。

今週(訳注:2016/06/15 の週)Firefox Developer Edition 49 がリリースされました。この記事では、このリリースに含まれる大きな変更点について解説します。

ネットワークモニタでのスタックトレース表示

ネットワークモニタには新しく “Cause” 欄が追加されました。ここには、そのリクエストの種類が表示されるとともに、送出したドキュメントがツールチップで表示されます。またリクエストが JavaScript によって送出されている場合、そのスタックトレースが吹き出しとしてポップアップ表示されます。

スタックトレースが最も有用なのは XHR に対してですが、JS による script 要素 や img 要素 のページへの挿入といった直接的でないものに対しても表示されます。

この機能は、特定の HTTP リクエストが送出される理由と、そのリクエストを送っている箇所の発見に有用です(bug 1134073 を参照してください)。

ネットワークモニタに表示されたスタックトレース

インスペクタでのアニメーション性能情報の確認

インスペクタを利用すると、CSS アニメーションと DOM アニメーションを詳細に調査できます。Firefox 49 では、アニメーションのパフォーマンスに関する情報が詳細に表示されるようになりました。ハードウェアアクセラレーションを使用できない場合が典型例ですが、アニメーション属性がコンポジターで処理できない場合、そのアニメーションには下線つきで展開されたアニメーションビューに表示されます。またその理由はツールチップに表示されます。

下記の例では、transform と width の属性に対して、同時にアクセラレーションが効かせられないことが示されています。このように性能の低いアニメーションを観察し、パフォーマンスを向上するために何をすれば良いのかを知ることができます。

アニメーションの Gecko 内部における最適化に関しては、David Baron のブログ記事に詳細が述べられています。そちらをご覧ください。また bug 1254408 には、より詳しい記述があります。こちらもご参照ください。

アニメーションが遅い理由が示されている例

マークアップビューで使えるコンテキストメニューの再構成

インスペクタ中で利用できるコンテキストメニューからは、いろいろな機能を呼び出せます。その結果、メニューが長大で使いにくいものとなっていました。Moaaz Sidat の貢献によって、メニューがいくつかのサブメニューを持つように再構成され使いやすくなりました。

再構成されたコンテキストメニュー

インスペクタに対するその他の変更

今バージョンより #rrggbbaa と #rgba 文法が利用できるようになりました。これにあわせて、インスペクタでもこの文法が利用できるようになりました。詳細は bug 1271191 をご覧ください。

新しくサポートされた文法で背景色を表示している

CSS ルールエディタの補完機能も改善され、スクロール可能なリストに従来よりも多くの候補が表示されるようになりました。これにより使いたい属性を簡単に探せるようになりました。また馴染みのない属性をを見ることで、それらについて学ぶ良い機会ともなるでしょう。この変更に関する詳細は bug 1260419 をご覧ください。

CSS属性候補の表示方法の比較

マークアップビューにも変更点があります。<br> のようなから要素は、doctype が XHTML の場合にのみ <br></br> のように表示されるようになりました。HTML の場合は、より正確で冗長性の少ない書式で表示されます。詳しくは bug 820926 をご覧ください。

コンソールに表示される JavaScript のエラー表示から MDN へのリンク

コンソールに馴染みのないエラーが表示された時、これまではエラーメッセージをコピーして、そのメッセージで検索することで、そのエラーに関する解説を探していたと思います。このバージョンからは、そのエラーについて解説する MDN のページへのリンクがコンソールに表示されるようになりました。この機能の詳細は @floscholz@mrrrgn記事をごらんください。同記事には、この機能を改善するための方法についても解説されています。また bug 1179876 もあわせてご覧ください。

エラーを解説する MDN ページへのリンクが表示されているコンソール

シンタックスハイライトのカラースキームの追加

シンタックスハイライトに利用している色が少しばかり古めかしく感じていました。そのためカラースキームを、よりコントラストが高く、可読性が高いものへ更新しました。 Developer Edition の light-theme および dark-theme の両方のカラースキームが変更されています。

light theme 向けの新しいカラースキーム

dark-theme 向けの新しいカラースキーム

アクセシビリティの向上

アクセシビリティに関しては、いくつかの重要な改善が行われました。開発ツールの UI のほとんどで、フォーカスがより分かりやすくなりました。またキーボードでの操作ができるようになり、インスペクタパネルのアクセシビリティも向上しています。詳しくは、bug 124269412427151242851 をご覧ください。

その他の特記すべき変更点

上記に以外の変更点で、特記すべきものをはこちらになります:

  • プライベートブラウジング、もしくは設定によって service worker が無効になっている場合、about:debugging に警告が表示されるようになりました(bug 1266415
  • ストレージインスペクタで編集できる項目が増えました。今回のリリースでは、IndexedDB のデータベースをコンテキストメニューから削除できるようになりました(bug 1205123
  • ネットワークインスペクターで、1 KB より小さい場合でも正確なレスポンスサイズが表示されるようになりました(bug 1263945
  • インスペクタパネルで、’h’ のキーを押すことで選択している要素を非表示にできます。このときマークアップパネル中の該当要素もグレーアウトされます(bug 1127572

Developer Edition のリリースにご貢献いただいたすべての方に感謝します。最新版をインストールして、フィードバックをお寄せください。

Jarda Snajdr について

Firefox への貢献者。ブラウザの内部構造を学ぶことと、複雑な問題を解くことを好む。

Twitter: @jsnajdr

Jarda Snajdr によるその他の記事はこちら。

Web 向けの 3D ゲーム作成の基礎

この記事は “Basics of building 3D games on the Web” の抄訳です。

「3D ゲームは、2D ゲームよりも作るのは難しい。だって管理しなきゃいけない次元が 1 つ増えているし。」

そう考えている人もいるでしょう。実際のところ、3D のゲームは私たちが想像しているよりも簡単に作れます。私たちは最近 MDN のゲームに関するコーナーを更新し、3D ゲームに関するチュートリアルを追加しました。このチュートリアルはフレームワークの利用に焦点をあてており、WebGL に不案内な Web ゲーム開発初心者でも 3D ゲームが作れるような内容になっています。

WebGL を利用したコンテンツの例

WebVR と 3D ゲーム開発

ブラウザ上での VR コンテンツは、今年に入って大きな進歩を遂げています。また WebVR として知られる JavaScript API の開発も進み、その仕様は バージョン 1.0 に向けての策定が行われています。これはブラウザ上での VR 技術にとって、大きなマイルストーンとなるでしょう。WebVR API が成熟してくると、コンテンツのレベルも「実験的なデモ」から商用ゲームや商用アプリケーションなどの「製品レベル」へと変わってくるでしょう。

Three.js を利用して作られている WebVR フレームワークである A-Frame も大きく進化しています。Cardboard Dungeon や SECVRITY のような興味深いケーススタディも行われ、またフレームワーク自身もバージョン 0.2.0 がリリースされ、コミュニティから早くも興味を寄せられる存在となっています。マークアップによってプラットフォームやデバイスで利用可能な VR コンテンツを作成する、という A-Frame のアプローチは単純ながら強力です。その結果として、チュートリアルやデモ、プラグインが毎日のように制作されるようになりました。

WevVR コンテンツが並ぶカタログサイト

現在は、最先端の VR を実験するにはとても良い時期です。しかし私のような 2D ゲームのファンにとっては、3 次元へと飛び出すのは、とてもハードルが高く感じられることでしょう。だから 3D の基本を一緒に学び、フレームワークを使えば印象に残るゲームやデモを作成するという目的を、より素早く達成できることを確認しましょう。

3D の Web ゲームは、リッチで、インタラクティブなアニメーションを Canvas へ、いかに ハードウェアアクセラレーションの効かせて WebGL でレンダリングするかにかかっています。それには作成物の情報を管理し、画面上への描画を行っているレンダリングパイプラインについて理解する必要があります。基本理論ではそのレンダリングパイプラインの動作について概観しています。

3D画像のレンダリングパイプライン:頂点を処理することでポリゴンを作成し、ポリゴンをラスタライズすことでフラグメントを作成、そのフラグメントを処理し画面に描画することで表示される。

3D ゲーム開発のためのフレームワーク

ゲーム開発を全て生の WebGL によって行うこともできますが、フレームワークを使うことで開発を簡単に、高速に行え、ゲームのアイディアに集中できるようになります。MDN に掲載されているチュートリアルでは以下のフレームワークを紹介しています:

Three.js は最も有名な WebGL アニメーションを作成ツールです。PlayCanvas はゲームエンジンである PlayCanvas Engine だけを利用することもできますが、オンラインエディタを利用して開発をすることも可能です。Babylon.js は強力な機能をもったシンプルな API を提供します。A-Frame は仮想現実における 3D 世界のプロトタイプ作成を高速に行うためのフレームワークです。またシェーダーの基本的な概念を理解するためのチュートリアルも用意しました。フレームワークの裏側で行なわれている勝利を理解することで、フレームワークによる処理が行われた後の結果を、より思い通りにコントロールできるようになります。

フレームワークを利用することの利点

ゲーム開発におけるフレームワーク利用の利点は何でしょうか?それは時間の短縮です。どのように短縮されるかを、見てゆきましょう:

PlayCanvas の Web サイト

まず、アセットのロード、シーンやスクリーンの描画といった、ゲーム制作の他の部分と比べて退屈な作業を減らせます。カメラ、光源など、それぞれ個別に設定が必要なものの管理もしなくてよくなります。ジオメトリを作成して、アニメーションを追加するだけで、後のことは何もしなくても、作品をすぐに見られるようになります。

ブラウザ実装の違いについても気にする必要がなくなります。ただフレームワークの提供するハイレベルでシンプルな API だけ知っていればよくなります。

フレームワークは多くのものを抽象化するので、開発者が書かなくてはならないコード量は少なくなり、また作業量も減ります。その結果、ゲームの核となる仕組みに注力できるようになるでしょう。フレームワークでは数行のコードで実現できる機能を JavaScript だけで実装しようとすると、最悪の場合は何十行にもわたることもあります。

PlayCanvas のオンラインエディタ

フレームワークが変わると、体験も変わります。Three.js はアニメーション作成によく用いられる一方、Babylon.js はゲーム開発に向いており、アンチエイリアスも行います。どちらもゲーム作成に耐えます。好みとプロジェクトのゴールにあわせて使い分けてください。

いくつかのフレームワークは機能レイヤーを追加し、物理エンジンや、衝突判定、パーティクルシステムが組み込まれているものがあります。このようなインフラを利用することで互換性に悩まなくてすみ、プラグインをカスタマイズしたり、一から書いたりする必要もなくなります。

シーンのプロトタイプ作成も簡単になります。複雑なコードを書かなくても、複雑なものを作成できるからです。こちらに JavaScript だけで実装されたシンプルなブロック崩しゲームがありますが、Phaser を利用して作成されたものと比べると、随分複雑になっていることがわかります。フレームワークを使うことで、時間が節約され、その時間を個性を出すために利用できるようになるのです。

PlayCanvas の GitHub レポジトリ

まとめ

フレームワークがどのように作成されているかを学ぶことは、良いプログラミング言語の学習になります。そしてフレームワークを拡張し、自分の望むように振舞わせることができるようになります。フレームワークには流行り廃りがありますし、フレームワーク固有の文法を追加で学ばなくてはなりません。結局、JavaScript だけで単純な機能を実装できるようになっているべきです。それは強力なスキルです。

それぞれのツールでシーンをどのように作るのかについては、私の GitHub レポジトリをみてください。これらの動作しているデモも公開しています

これだけは覚えておいてください。特定のフレームワークを使わなければゲームを作れない、ということはありません。同じことを JavaScript と WebGL だけで実現できます。紹介したデモは、現在よく使われているツールの使い方を示すためのものです。足りないツールがある場合は、ぜひデモを作成して GitHub の方へ追加してください。いつでも歓迎します。またデモに含まれないツールがあれば、こちらにコメントを残すか、紹介を書いてください。多くの人知ってもらえるようになるでしょう。

上記で紹介したソースコード、ば新しい 3D ゲームのテンプレートにするといった感じで、自由に使っていただけます。使ったら、作ったものを教えてください。こちらにコメントをする形でも、GitHub のレポジトリにコメントする形でも、フィードバックはいつでも歓迎です。

Andrezej Mazur について

HTML5 ゲーム開発者で、Enclave Games のファウンダー。Gamedev.js という週間メルマガの発行人で、HTML5 ゲーム開発者向けのコーディング大会である js13kGames の発起人。新しいオープン Web 技術について技術講演を行い、WebVR に夢中になっている。

Andreij Mazur による他の記事はこちら

Unity で作ったインディーゲームの WebVR 出力

この記事は “Exporting An Indie Unity Game to WebVR” の抄訳です。

ツールをダウンロードしたりインストールをすることなく VR コンテンツをすぐに楽しめる WeVR は、未来における VR コンテンツアクセスの鍵を握っています。少なくとも、私たちはそう考えています。私たちは Jump と呼ばれるマルチプラットフォームなデジタルゲームの定額サービスを構築しています。Jump では、デスクトップやモバイル、ゲーム機、そして VR デバイスに向けた Web 技術のみで作られ「Web ネイティブ」ゲームを配信しています。私たちはビジネスを Web ネイティブな技術、HTML5、WebGL、JS、そして早晩リリースされる WebAssembly に賭けたのです。そしてWeb がバーチャル・リアリティに対して、いかに強力な存在であるかを示すことにしました。そのために Oculus Rift の WebVR ゲームを Jump に向けて作成しました。作成したゲーム SECCVRITY の開発期間は 1 月でした。短期間での開発だったため、WevVR API を深く理解して Web ネイティブなものとして作成することはできませんでした。そこで Unity 5 を利用して開発を行いました。

SECVRITY で遊ぶ

SECVRITY はコンピュータウィルスをモチーフにした、モグラ叩きゲームです。コンピュータセキュリティの専門家として、たくさんのモニタを監視しつつ、次々にやってくるコンピュータウィルスの侵入を阻止します。推測されている通り、スクリーンを見つめて、クリックすることでウィルスを無効化してゆきます。首がむち打ちになる可能性も非常に高いゲームですが、楽しさも非常に高いものになっています。その証拠に GDC Mozilla ブースでの試遊には多くの人が押し寄せました。

GDC での Mozilla ブース

技術の話題に戻りましょう。Unity は WebGL と VR の両方に対応していますが、その 2 つへ同時に対応できるようにはなっていないことに気づきました。また WebVR は彼らの直近のロードマップには載っていません。このギャップを埋める方法を探すこととしました。Unity の WebGL 出力を利用することでゲームを Web サイト向けに出力できるため、WebVR API と Unity のゲームエンジンとをつないで、WebVR をゲームエンジンから利用することもできるにちがいありません。調査とゲーム作成を 1 月で行うことにならないよう、強く願ったものでした。

幸いにも、gtk2k によってこのブリッジの開発が 1 年前に開始されていました。彼のやり方は極めて直裁的なものでした:WebVR からの入力を API 経由で受け取る JS ファイルを含む Unity のWebGL テンプレートを作成しました。そのコードと Unity とは、 1 つのシンプルなスクリプトによって接続されます。スクリプトを Unity 上で適切に実装するために、通常の Unity カメラである standard view カメラと、視野角と X 座標が合うように調整され、隣り合って表示される画面用のステレオカメラの 3 つの異なるカメラを持つカメラプレハブが作成されました。 開発者はシーン内のメインカメラをこのプレハブに置き換え、StereoCamera.cs をアタッチするだけで、ゲームを WebVR 対応させられます。gtk2k のブリッジは、ユーザーが テンプレートに含まれる “Enter VR” ボタンを押すと standard カメラをステレオカメラに置き換えます。

Oculus Rift

Unity WebVR プロジェクトのサンプルか、UnityPackage をダウンロードすることで、必要なファイルをプロジェクトにインポートできます。

テンプレートの利用方法は以下の通りになります:

  • Oculus Rift を手に入れます。外部からのアプリを実行できるようにしておきましょう。
  • Firefox Nightly をダウンロードし、インストールします。
  • WebVR enabler をインストールします。
  • サンプルプロジェクト全体か、UnityPackage 単体をダウンロードします。
  • Unity 5 をインストールして、”WebGL Build Support” と “Windows Build Support” を有効にします。
    インストールする Unity コンポーネントの選択画面。WebGL Build Support と Windows Build Support にチェックを入れている。
  • サンプルプロジェクトか、UnityPackage を追加した自信のプロジェクトを Unity で開き、MainCamera を WebVRCameraSet プレハブに置き換えます。
    WebVRCameraSet を利用する
  • StereoCamera.cs がプレハブの親ノードにアタッチされていることを確認します。
    StereoCamera がアタッチされていることを Inspector で確認している。
  • File から Build Settings を開き、WebGL をビルドプラットフォームに設定します。なお Development Build にはチェックしないでおきましょう。
    Build Settings で WebGL を出力プラットフォームに選択する
  • Edit → Project Settings → Player を開き、Player 設定を開きます。Resolution and Presentation で、WebGL テンプレートを WebVR に設定します。
    Resolution and Presentationの設定画面
  • 同じ Project Settings で、WebGL Memory Size を最低でも 512 MB に設定します。これは out-of-memory エラーを避けるためです。SECVRIY では 768 MB に設定しています。WebGL Memory Size を 512 に設定している
  • ビルドして、Firefox Nightly で起動します
    • 手元で、もしくはWeb サイトにアップロードして、テストできます。

Unity で WebVR ビルドを試してもいいと思っていただければ幸いです。エディタ内でテストするには、デスクトップ VR ビルドのための標準機能を有効にします。Edit → Project Settings → Player を開き、Standalone タブ(下向き矢印アイコンのタブ)を選択します。Resolution and Presentation が表示されていますが、Other Settings まで移動し、Stereoscopic Rendering と Virtual Reality Supported にチェックを入れます。これらは WebVR ビルドそのもには必要ありませんが、エディタ内でテストするためには設定しておく必要があります。

エディタ内でテストするために必要な設定

デザインの点でテンプレートを補完するために、ブラウザウィンドウを VR モードにするための手順を追加しました。また VR もしくはマウスでの操作を選択できるようにもしました。これは物事をややこしくすることとなりました。

SECVRITY の操作説明と、操作方法の選択画面

ブラウザの中で動作するのだから、VR を利用しないデスクトップ環境のユーザにも SECVRITY をプレイして欲しいと考えていました。VR をサポートする以前より、マウスによる操作ができるようになっていたため、マウス操作自身は単純でした。しかし VR からの入力が可能な状態でのマウス操作は、非常に悪い結果をもたらしました。マウスの動きと VR ヘッドセットの視点とは、本質的に何の関係もありません。そのため A:ユーザが完全に迷子になり、B:とても酔ってしまうこととなりました。そのため VR を使用しているかどうかを検知し、マウス操作を on / off する必要がありました。

メインメニューで明示的にマウス操作が選択されない限り、VR からの入力の有無に関わらず、マウス操作を無効にすることが私たちの解決策です。プレイ前に、ユーザに矢印キー、もしくはジョイスティックで入力方法を必ず選択させるようにしました。ちなみに WebGL/WebVR 出力は Gamepad API をサポートしています。そのため通常のビルドに追加して行わなければならない作業はありません。もしユーザが VR ヘッドセットを利用した状態でのマウス操作を選択した場合、酔いが誘発される問題が発生します。プレーヤーにはこのように警告します:このゲームは 1 月でつくられました。将来追加されるであろう、自動検知によってこの問題は解決します。

SECVRITY のイメージ

Unity で WebVR コンテンツを作るための価値ある知見を得ました。主には VR / 非VR を組み合わせた場合の体験に関するものでした。トラブルの多くはエンジンが WebVR に正式対応することで解決されるべきです。しかし正式対応されたとしても、ユーザが何をすると、もしくは何をしないとゲームが楽しめないかという点、特に操作方法が大きく違う場合についての理解が重要であることは変わりません。最近行われた Firefox Nightly の変更に対応するため、gtk2k のテンプレートに対して若干の修正を加えましたが、その点を除けばうたわれている通りに動作し、ゲームの移植に必要な作業はほとんどありませんでした。まさに彼はヒーローです。

Web はゲームにとっての未来であり、SECVRITY のようなゲームを持つ Jump はそれを世界に証明しようとしています。デスクトップ、モバイル、ゲーム機、VR ヘッドセット、他のデバイスでも、Web ゲームはユーザにゲームのインストールをさせなくても、すぐにプレイしてもらえるようになります。動作スピードもネイティブに迫るものがありますし、WebGL 2.0 や WebAssemmbly も実用に近づきつつあります。近い将来のグラフィックスも見えはじめています。Jump は Web の革命を進めて、どの端末のゲームでも Web が究極のホームとなるのを後押ししたいと考えています。Jump の進捗にご興味をお持ちの方は、http://www.jump.game からニュースレター配信にご登録ください。また SECVRITY のライブデモは mozvr.com にて公開されています。信じてください。Web はゲーム業界に変革をもたらすでしょう。そしてブラウザを使って美しい仮想現実へすぐにアクセスできるようになる、WebVR は Web の力を開発者とユーザに対して示す重要な役割を担うことになるでしょう。

Anthony Palma について

2016 年にローンチされたデジタルゲーム配信サービスである Jump の CEO。ベータ版へのユーザ登録や、ゲームをサービスに登録されたい場合は、ご連絡ください。

Anthony Palma による他の記事はこちら

JavaScript の並列処理機能を味見してみる

この記事は “A Taste of JavaScript’s New Parallel Primitives” の抄訳です。

まとめ:複数の Worker と共有メモリを利用して、本当の意味で並列アルゴリズムの JavaScript 実装を可能にするために、JavaScript の基本機能を拡張しようとしています。

複数コアを用いた計算

JavaScript (JS) は成熟しました。モダンな Web ページのほとんど全てで、大量の JavaScript が利用され、それらが動作するのは当たり前のことになっています。また JS の適用領域も拡大しています:クライアントサイドでは、Facebook や Lightroom が行っているように画像処理が JavaScript で実装されていますし、Google Docs のようなブラウザで動作するオフィススイートも JS で実装されています。PDF ビューワ(pdf.js)のような Firefox のコンポーネントや言語分類器も JS で実装されるようになっています。それらのうちの幾つかは、C++ コンパイラによって出力される単純化された JavaScript サブセット、asm.js を利用しています。例えば C++ で書かれているゲームエンジンも JS にリコンパイルされ、asm.js のプログラムとしてブラウザ上で動作させられます。

これらに代表される JS の適用範囲の拡大は、パフォーマンスの驚異的な改善によって可能となりました。それは JS エンジンに実装された Just-in-Time(JIT) コンパイラや、より高速な CPU によってもたらされました。

しかし、JIT による実行速度向上のスピードは低下しつつあります。また CPU 速度の改善はほとんど頭打ちになっています。CPU の高速化に代わる手法として利用されているのは、複数の CPU(実際は CPU のコア)の利用です。これは携帯電話からデスクトップにいたるまで広く利用され、ローエンドの環境を除けば、最低でも 2 つ以上の CPU が利用できるようになっています。このような状況でプログラマがプログラムの性能を向上させたいなら、複数のコアの並列利用を選択するでしょう。これは Java、Swift、C#、C++ のようなマルチスレッドプログラミングが可能な言語で書かれたネイティブアプリの話ではありません。Web Worker と、その遅いメッセージパッシング機構、そしてデータコピーの回避手段がほとんどないという、複数の CPU を利用するには極めて制限された機能しか持たない JavaScript での話です。

つまりは JS には問題があるのです:Web 上の JS アプリケーションが、ネイティブに代わる有力な選択肢であり続けるためには、JS を複数 CPU の上で動作させられるような機能を JS に持たせなければなりません。

JS の並列計算:共有メモリ、不可分性、Web Worker

これまでの 1 年程度、Mozilla の JS チームは標準化活動を主導して、並列計算を可能にする機能を JS に加えてつづけてきました。他のブラウザベンダの協力を得て、私たちの提案JS の標準化プロセスへと進みました。Mozilla の JS エンジンになされたプロトタイプ実装は、並列計算を可能にする機能に関して情報を得るのに役立ちます。また Firefox のいくつかのバージョンでは利用可能です。ここではそれらを利用した実験をおこなっていゆきます。

Extensible Web の精神に基づいて、可能なかぎりプログラムを書かずに利用できる低水準な機能を用意することで、複数の CPU を利用可能にすることを選択しました。用意されたのは、新しい共有メモリ型、共有メモリ上のオブジェクトに対する不可分操作、そして共有メモリ上のオブジェクトを標準的な Web Worker に受け渡す方法です。これらの考えは目新しいものではありません。これらの高レベルな背景と歴史に関しては、Dave Herman のブログポストを参照すると良いでしょう。

SharedArrayBuffer と呼ばれる新しい共有メモリ型は、ArrayBuffer とよく似ています。大きな違いは、SharedArrayBuffer として表現されているメモリは、複数のエージェントによって同時に参照されうる点です(ここでのエージェントとは、Web ページのメインプログラムや、Web Worker のことを指します)。SharedArrayBuffer は、あるエージェントから他のエージェントへと postMessage を通じて受け渡されることで共有されます:

let sab = new SharedArrayBuffer(1024)
let w = new Worker("...")
w.postMessage(sab, [sab])   // Transfer the buffer

Worker は、メッセージから SharedArrayBuffer を取得します:

let mem;
onmessage = function (ev) { mem = ev.data; }

上記のプログラムにより、メインプログラムと Worker とが同じメモリを参照するようになります。この状況を図示すると以下のようになります:

Main と Worker の 2 つのエージェントが、同じ SharedArrayBuffer を参照している

共有された SharedArrayBuffer に対して TypedArray を作り、そのビューに対して配列操作を行うことで、共有メモリ領域に対するデータの読み書きが可能になります。操作例は以下のようになります:

let ia = new Int32Array(mem);
ia[0] = 37;

これでメインプログラムは、Worker によって書き込まれたデータを参照できるようになります。上記の例では、Worker の書き込みが終了していれば、37 を得られます。

この「Worker がデータを書き終わるまで待つ」というのは、メインプログラムにとっては実に難しい問題です。複数のエージェントが同じ領域に対して調整することなく読み書きを行うとすると、その結果は悲惨なことになるでしょう。新しく追加した不可分操作によって、操作が割り込みによって中断することなく、予期した順番で処理されるようになり、上述のような協調動作が可能になります。この不可分操作は、新しく追加されたトップレベルオブジェクトの Atomics の静的メソッドとして実現されています。

速度と応答性

Web の性能に関して、複数コア計算によって向上が見込まれるものには 2 つあります。それは計算速度と応答性です。前者は単位時間当たりの仕事量であり、後者は計算中のブラウザに対してユーザが可能な操作の範囲です。

仕事を複数の Worker に割り振り、並行に実行すると速度を向上させられます:1 つの計算を 4 つに分割し、それぞれを 4 つの Worker に割り当て、それぞれの Worker に 1 つずつコアを占有させることができたら、計算が 4 倍速くなることが期待されます。また仕事をメインプログラムから Worker へと移動させることで、応答性を向上させられます。これにより計算途中であっても、UI イベントに対してメインプログラムが応答できるようになります。

共有メモリは 2 つの理由から、並列計算の基本要素となりました。データコピーのコストを削減できることが、1 つ目の理由です。描画を複数の Worker に任せていて、その結果をメインプログラムから表示しなくてはならないといった場合、描画されたシーンはメインプログラムに対してコピーされます。このコピーの分だけ描画時間が増加し、メインプログラムの応答性は低下します。処理の調停コストが低いことが、そして postMessage と比較すると相当低いことが、2 つめの理由です。通信に必要な時間と、エージェントが処理をしないで待っている時間を短縮できます。

良いことだけでなく、悪いこともある

複数の CPU コアを利用することが、簡単でない場合もあります。シングルコアを仮定して作成されたプログラムを複数コアで動作させる場合、大きな変更を余儀なくされる場合がとても多くあります。また変更後のプログラムが正しく動作していることを検証することも難しなります。また Worker 間の調整が頻繁に必要になるようなプログラムは、複数コア利用による計算スピードの向上は難しくなります。すべてのプログラムが並列計算の恩恵を被れるわけではありません。

付け加えるなら、並列プログラムには新しい種類のバグが発生します。プログラムのミスから 2 つの Worker が、お互いの仕事が終わるのを待ってしまった場合、それ以上プログラムが進まなくなります。このような状態をデッドロックと呼びます。複数の Worker が調整なしに同じメモリセルを読み書きした場合、その結果は正しくないものとなるでしょう。このことをデータ競合と呼びます。データ競合のあるプログラムは不正確で、信頼性に欠けるものとなってしまいます。

利用例

注意:以下のデモを実行するためには、Firefox 46 以降が必要です。また Firefox Nightly を利用していない場合は、about:configjavascript.options.shared_memorytrue に設定する必要があります。

複数コアを利用して並列に計算してスピードを向上させるために、どのようなプログラムを書けば良いかを見てゆきましょう。例として単純なマンデルブロー集合のアニメーションを利用します。これはピクセルの値をもとにグリッドを計算し、そのグリッドを拡大率を上げながら canvas に描画します。なおマンデルブロー集合の計算は「驚異的並列」として知られています。つまり簡単に高速化が行える種類の計算なのです。他の例ではこれほど簡単には高速化できないのが通常です。また、ここでは技術的に深入りはしません。詳しくは文末にある関連情報を参照してください。

Firefox で共有メモリ機能が標準で利用できないのは、この機能が JS 標準化団体での議論の途中にあるからです。標準化は、その団体のプロセスに則って行われ、その過程で機能が変更されることもあります。そのような API に依存したコードを書きたくはありません。

並列化されていないマンデルブロー集合

最初に全く並列化されていないマンデルブロー集合の計算を見てみましょう。計算はメインプログラムの一部分として実行され、その結果は直接 canvas に描画されます。なおデモは途中で止められますが、後のフレームほど描画が遅くなって行きます。信頼できる結果をえるなら、最後まで実行してください:並列されていないマンデルブロー集合アニメーション

ソースコードはこちらで参照できます:

並列化されたマンデルブロー集合

並列化されたバージョンでは、ピクセルの計算が共有メモリと Worker を利用して並列に行われます。元のプログラムに対する適用は、概念的にはシンプルです:mandelbrot 関数を Web Worker に移します。そして複数の Web Worker を動かし、それぞれの Worker で出力の横一列の計算を担当します。メインプログラムは canvas への描画を担当します:並列化されたマンデルブロー集合アニメーション

使用するコア数とフレームレート(Frame per Second, FPS)との関係をグラフすると、次のようになります。測定に使用したのは、hyperthreading が有効になったコアを搭載した MacBook Pro late-2013 上の Firefox 46.0 です。

コア数とFPSの関係。1コアでは6.9FPS程度だったものが、4コアでは25.4に、8コアでは39.3FPSにまで増加している

1 コアでは 6.9 FPS でしたが、4 コアでは 25.4 FPS へと、プログラムはほぼ線形に高速化しています。その後は新しいコアではなく、すでにプログラムが動作しているコアでの hyperthread 上でプログラムが動作するようになったため、速度の伸びは緩やかになっています。同じコアで動作する hyperthread は、コア上のいくつかのリソースをきょうゆうします。そのためそれらの間での競合が発生しているのではないかと推定されます。それでも hyperthread を追加するたびに、3・4 FPS 高速になり、Worker 数を 8 にした場合は 39.3 FPS となりました。これはシングルコアに比べて 5.7 倍の高速化を達成しています。

この種類の高速化はとても明らかに良い結果になります。一方、並列化されたバージョンは、そうでないものと比べて極めて複雑なものとなっています。この複雑性は様々なものに起因しています:

  • 並列化バージョンを正しく動かすためには、Worker とメインプログラムとを同期させる必要があります:メインプログラムは各 Worker に何を計算するべきか伝えなくてはなりません。また各 Worker はメインプログラムに、計算結果をいつ描画するべきかを伝える必要があります。どちらの場合も、postMessage を利用してデータが渡されますが、通常は共有メモリを通じて渡したほうが良い(つまり高速)です。正しく、効率的にこれを行うは極めて複雑です
  • 性能を向上させるためには、各 Worker に対して計算を分割し、ロードバランスを行って効率的に Worker を利用するための戦略が必要です。その結果、例として利用したプログラムでは、出力される画像は Worker の数よりもずっと細かく分割されています
  • 共有メモリが整数値のフラットな配列であることも、複雑さを増す要因となっています。共有メモリ上の複雑なデータ構造を手動で管理しなくてはならないためです

同期について考えてみましょう。新しい Atomics オブジェクトは、waitwake の 2 つのメソッドを持っています。どちらも Worker 間でシグナルを送るために利用できます:ある Worker は Atomics.wait を呼ぶことで、シグナルが送られてくるのを待ち受けます。そして他の Worker は Atomics.wake を呼んでシグナルを送れます。これらは柔軟だが低水準の要素です。同期を実現するためには、Atomics.loadAtomics.storeAtomics.compareExchange といった、共有メモリ中の値を読み書きするための機能が必要となるでしょう。

また Web ページのメインスレッドは Atomics.wait を呼ぶことができないことも、複雑さに拍車をかけています。これはメインスレッドを block してしまうのは良くないためですが、Worker 間は Atomics.wait と Atomics.wake を利用して通信を行っているのにも関わらず、メインスレッドを起こすためには postMessage を利用してイベントを送出しなくてはなりません。

これらの機能を試そうと考えているなら、Firefox 46 と Firefox 47 では wait と wake のことを futexWait、futexWake と呼んでいることを知らなくてはいけません。詳しくは MDN の Atomics のページを参照してください。

複雑性の大部分を隠蔽するような良いライブラリをつくることは可能です。またプログラム、通常はプログラムの重要な部分、を複数のコア上で動作させて性能が非常に向上するなら、複雑になっても並列化する意味はあります。それでも並列化は性能を向上させる特効薬ではありません。

上記のディスクレーマーを踏まえた上で、下記の並列化バージョンのコードを参照してください:

より詳しくは

利用可能な API に関しては、提案されている仕様を参照してください。大部分は安定しています。またこの提案を収めた GitHub レポジトリ上での議論も有用です。

また Mozilla Developer Network (MDN) にも SharedArrayBufferAtomics に関する文書があります。

Lars T Hansen について

Mozilla の JavaScript コンパイラエンジニア。以前は Adobe で ActionsScript3 の、Opera で JavaScript とブラウザ開発に携わる。

Web サイト:https://github.com/lars-t-hansen

Lars T Hansen による、その他の記事はこちら

Developer Edition 48 – Firebug 由来の機能、ストレージの編集、インスペクタの改良、etc

この記事は “Developer Edition 48 – Firebug features, editable storage, inspector improvements and more…” の抄訳です。

Firefox Developer Edition 48 がリリースされました。このバージョンでは、Firefox のマルチプロセス化と Firebug の統合のため、Firebug の機能が開発ツールに組み込まれました。これ以外にも小さな変更がありました。それらをまとめてお伝えします。

Firebug テーマ

Firebug 統合の一環として、Firebug のテーマが選択できるようになりました。Firebug を使ってきた方には馴染みある見た目になることと思います。このテーマにはまだ改善の余地がたくさんあります。バグやご要望などありましたら、こちらまでご連絡ください。テーマを利用すると以下のような画面になります:

Firebug テーマに変更した開発ツール 

DOM パネル

Firebug から移植した機能の 2 つ目は DOM パネルです。これはページの DOM の構造を可視化することで、ページの調査を助けてくれる機能です。利用イメージは次のスクリーンショットをご覧ください:

DOMパネルを利用したページの調査例

ストレージの編集

ストレージインスペクタに保存内容の編集機能が追加されました。今回のリリースでは、Cookie、ローカルストレージ、そしてセッションストレージの編集と削除が可能になっています。ストレージ中の要素ををダブルクリックすることで、その要素を編集できます。削除はコンテキストメニューから行います。

ストレージインスペクタで、データを編集している様子

コンテキストメニューから、ストレージに保存されているデータを削除する様子

ジオメトリエディタ

絶対的、もしくは固定的に配置された要素の調整を助ける機能も追加されました。このツールを使うと top、left、bottom、right それぞれの属性値を、その結果を確認しながら編集できます。ジオメトリエディタを利用するには、インスペクタのボックスモデルタブをクリックした後に、ジオメトリエディタ起動ボタン をクリックします。

ジオメトリエディタの利用例

メモリツールの改善

メモリツールには、ツリーマップ表示が追加されました。このビューでは、メモリの使用状況を素早く、そして直感的に理解できます。オブジェクトを種類に基づいてグループ化され、「canvas 上の線を描いている配列」や「スクリプトのロードが遅い Web サイト」のような、同じような要素のメモリ使用量が確認できるようになっています。また使用されているメモリのバイト数に応じて、それぞれの要素の大きさは決まるため、メモリを多く使用しているものは何か一目でわかるようにもなっています。

メモリの使用状況をツリーマップで表示している様子

総計表示でもオブジェクトの種類ごとにメモリ使用量を表示させられますが、今回のリリースから ⁂ アイコンをクリックしてそれぞれの要素を別のビューで表示できるようになりました。以前のバージョンではGC ルートからの保持パスで表示されていた、それぞれのオブジェクト間の参照関係も表示できます。この機能を使うと、メモリリークの原因となっているオブジェクトをピンポイントで見つけることができます。

個別の要素のメモリ使用量を調査しているスクリーンキャスト

スナップショットを個別に削除する機能も追加されました。サイドバーに削除用のボタンが追加されています。

インスペクタの改良

インスペクタも改良され、よりスムーズに、より簡単に使えるようになりました。ルールビューでルールを変更する際に、良く使う属性が自動補完の最初の候補として表示されるようになりました。例えば backface-visibility ではなく、background が最初の候補となっています。これにより高速に調整ができるようになります。

ルールビューでの自動補完

また長い値の取り扱い方も改善されました。編集する値を簡単に選択できるようにするため、長い値は複数行で表示されるようになりました。

値が複数行にわたっている background-image 属性の編集画面

マークアップビューでは、DOM ツリーの親子関係が強調して表示されるようになりました。選択されている要素の子要素を強調するために、線が引かれるようになりました。これでマークアップが複雑でも、子供の要素が何かがわかりやすくなりました。

マークアップビューで、選択中の要素の子要素がハイライトされている様子

角度の単位を切り替える機能も追加されました。色の表示を切り替える機能と同じように、角度の横に表示されているスウォッチをクリックすることで、単位を切り替えて表示できます。この機能は貢献者である Nicolas Chevobbe によって実装されました。

角度の単位を切り替えている様子

マークアップビューの検索結果を見るためのキーボードショートカットも追加されました。Shift+Enter で 1 つ前の検索結果へとジャンプできます。また Ctrl/Cmd+G と Ctrl/Cmd+Shift+G も追加されました。これは Enter と Shift+Enter と同じ振る舞いをします。このショートカットは Steve Melia によって追加されました。

コンソールの改良

コンソールもいくつかの点で改良されました。いずれも開発を楽しくするものです。最初の改良点は、Firebug の機能移植です。これによって、通信ログを開いて詳細を Firebug のフォーマットで見られるようになりました。

コンソールで通信の詳細を表示している様子

Map や Set オブジェクトを利用している場合、サイドバーで個別の要素を確認できるようになりました。この機能は Jarda Snajdr によって追加されました。

Map オブジェクトの要素をコンソールで確認している様子

console.clear() も実装されました。これを呼ぶことで、コンソール出力を消去できます。

about:debugging

WebExtensions のリリースを見据えた機能として、アドオン開発者向けの機能を追加しました。それは about:debugging の画面から、
アドオンの再読み込みです。これを利用すると、アドオンを再インストールすることなく開発を続けることが可能です。

about:debugging に追加されたアドオンの再読み込みボタン

また ServiceWorker を開発する際に有用な、ここのワーカの削除機能も追加されました。

登録された ServieWorker の削除

その他の主な変更点

上記以外の変更点の中で、主要なものを以下にあげます:

  • ::before と ::after の疑似要素におけるアニメーションがインスペクタで調査できるようになりました (Bug 1206420)
  • パンくずリストがインスペクタパネルの下部へ移動しました (Bug 1256422)
  • 新しくノードを作成するボタンがインスペクタに追加されました (Bug 1261781)
  • デバッグするファイルの切り替えが高速になりました (Bug 1233927)
  • ストレージインスペクタで、巨大な値を選択する際の性能が向上しました (Bug 1156720)
  • ブレークポイントの表示方法が改善され、よりわかりやすいものとなりました (Bug 1245030)
  • タブバーのアイコンが更新されました (Bug 1225184)
  • 消去アイコンが更新され (Bug 1251256)、ツールごとに異なっていた表示位置が同じになるよう変更されました (Bug 1220208)

Developer Edition 48 に貢献いただいた皆様に、感謝します!ぜひ最新のものを試して、その感想や考えを共有してください。移植された Firebug の機能面での違いに関する建設的なフィードバックも歓迎します。こちらへまでご提案、コメントをお寄せください

Tim Nguyen について

Firefox の開発ツールのコントリビュータ。Web 開発と Web デザインに情熱を持つ。

Twitter アカウント

Tim Nguyen による他の記事

Brian Grinstead について

Firefox の開発ツールを開発するエンジニア。

Tim Nguyen による他の記事

WebExtensionを書いてみよう

この記事はhttps://hacks.mozilla.org/2015/09/lets_write_a_webextension/の翻訳です。

WebExtensionを書いてみよう

By Blake Winton

Posted on September 21, 2015 in Add-ons, Featured Article, and Web APIs

あなたはMozilla’s WebExtensionsについて聞いたことがあると思います。
マルチプロセス(e10s)に対応した新しいブラウザ拡張の実装です。
たぶんあなたは「それは何?私は使えるの?」と思ったでしょう。まあ、私は助けるためにここにいます! たぶんMDN’s WebExtensions docsが開発を始めるのにとても適している場所だと思います。

WebExtensionはFirefox extensionを書く新しい方法です。

このテクノロジーはクロスブラウザ互換性の為に開発されました: 膨大な量のAPIがGoogle ChromeやOperaがサポートしているextension API と互換性を保っています。 他のブラウザの為に作られたアドオンは大抵の場合、少しの変更を加えるだけで動きます。APIもまたmultiprocess Firefoxとほぼ互換性を保っています。

一つだけ付け加えると、MozillaはChrome and OperaのサポートしているおおよそのAPIを実装している間、私たちはそれらAPIだけに制限されるわけではありません。それが理にかなっている場合、私たちは新しく機能を追加して、他のブラウザベンダーとこの機能を同様にを実装するかどうかという話をします。最後に、WebExtension APIはまだ開発途中です。Firefox Nightlyを使用する場合、最新のものを得られるため標準準拠の動作になります。よってこのチュートリアルを行うにはたぶんFirefox Nightlyを使用するのがベストでしょう。しかし覚えておいてください、これはまだ実験的な技術です  –  もしかしたら、なかったことになるかもしれません(訳注:もう正式機能になりました)。

始めてみる

よし、じゃあまずはシンプルなアドオンから始めてみようか。ボタンを追加して、クリックされたとき、私の一番好きなサイトが新しいタブで開くようにしよう。

まず最初のファイルとしてFirefoxに私たちのアドオンを伝える manifest.jsonが必要だ。

<code>{
  "manifest_version": 2,
  "name": "Cat Gifs!",
  "version": "1.0",
  "applications": {
    "gecko": {
      "id": "catgifs@mozilla.org"
    }
  },

  "browser_action": {
    "default_title": "Cat Gifs!"
  }
}</code>

よし!これで完了!たぶんあなたのアドオンはこのようになったと思います。もちろん、私たちはまだそれが動くかどうかわからない。なのでFirefoxにインストールしてみよう(最新のFirefox Nightlyを使います)。ディレクトリからFirefoxに manifest.jsonをドラッグしてみてください。しかし実際にはあなたが望んだとおりに動かなかったと思います。

The directory listing

インストール

Firefoxがあなたの拡張をアドオンとして認めるには拡張子を.xpiとしてzipファイルを与える必要があります。なので最初に7-Zipをインストールして(訳注:win7,win10以降は標準でzip圧縮できます。)、7z a catgifs.xpi manifest.jsonと入力します。(もしあなたがMacやLinuxを使っているならzipコマンドが標準で入っています。なのでzip catgifs.xpi manifest.jsonとタイピングするだけで大丈夫です)。そうしたら、 catgifs.xpiをFirefoxにドラッグします。そうするとエラーが表示されます。なぜなら私たちのアドオンはまだ署名されていないからです。

The first error

about:configに行き、xpinstall.signatures.required と検索ボックスに入力し、エントリーをダブルクリックし、falseに設定し、タブを閉じます。その後、もう一度 catgifs.xpi をFirefoxにドラッグしてみてください。新しいアドオンをインストールするかどうかの選択画面が現れるはずです!

ここで重要なことは、Firefox44(年内にリリース)で始める場合、Firefox Betaやリリースバージョンアドオンのブラウザにインストールするためには署名を要求します。なのでもしあなたが上の設定をセットした場合でも、このチュートリアルを行うためにはまだFirefox NightlyやDeveloper Editionが必要になります。

Success!!!

もちろん、私たちのアドオンはまだほとんど動きません。

I click and click, but nothing happens.

なので修正してみましょう!

機能を加える

最初に、下のコードを manifest.jsonの browser_action:という記述が含まれている行の上に記述します。

<code>  "background": {
    "scripts": ["background.js"],
    "persistent": false
  },</code>

もちろん現在、上に出てきたbackground.js ファイルはまだ存在していませんので作成しましょう。下のjavascript をbackground.jsの中に貼り付けます。

<code>'use strict';

/*global chrome:false */

chrome.browserAction.setBadgeText({text: '(ツ)'});
chrome.browserAction.setBadgeBackgroundColor({color: '#eae'});

chrome.browserAction.onClicked.addListener(function(aTab) {
  chrome.tabs.create({'url': 'http://chilloutandwatchsomecatgifs.com/', 'active': true});
});</code>

そうするとこんな風になるはずです。 もう一度7z a catgifs.xpi manifest.json background.js (もしくは zip catgifs.xpi manifest.json background.js)とタイピングしてアドオンを再生成し, catgifs.xpiをFirefoxに再度ドロップします。そしてボタンをクリックする新しいタブが開くようになりました!