7

私は、ヘルスバー (アニメーション) と、プレーヤーが持っている爆弾の数を示すアイコンのように視覚的に表されるその他の情報を含むゲームを作成中です。現在、これは両方のキャンバスで行うことができます (情報用に別のキャンバスを作成することにより)。メイン キャンバス上に配置するか、多数の div とスパンを使用して絶対配置で実行できます. ブラウザ ベースのゲームを作成するのはこれが初めてなので、経験豊富な人がこれを見た場合は、あなたの推奨事項を教えてください.どの方法がより速いかを知ってください。

ゲームはモバイル デバイスでも実行されます。ありがとう!

4

4 に答える 4

6

率直な答えはありません。ユースケースでどのように機能するかを、さまざまなブラウザーで FPS テストを行うことをお勧めします。それほど深く掘り下げたくない場合は、単純に要素をキャンバス内に描画し、要素を非表示にする必要がある場合は、レンダリング ループから drawHUD() 呼び出しを除外することをお勧めします。

HTML HUD オーバーレイについて<canvas>は、次の要因を考慮する必要があります。

  • キャンバス上に DOM 要素がある場合、Web ブラウザー コンポジターはハードウェア アクセラレーションを<canvas>適切に実行できますか

  • <canvas>HTML / DOM 操作は、DOM 要素を処理する継承された複雑さにより、操作よりも常に遅くなります。

  • <canvas>ピクセル空間は内側にとどまり、キャンバス自体の外側に<canvas>要素を描画しようとすると、ピクセル単位で完全に配置するのが難しい場合があります<canvas>

  • HTML はキャンバス drawString() よりもはるかに多くのテキストの書式設定オプションを提供します - HTML 書式設定が必要ですか

于 2012-07-08T16:40:00.503 に答える
3

キャンバスを使用します。必要に応じて 2 つのキャンバスを使用し、一方を他方の上に重ねますが、キャンバスを使用してください。

DOM にまったく触れるのは遅いです。移動した DOM 要素のサイズが非常に遅いため、ドキュメントのレイアウトをやり直します。キャンバスの上に物理的に DOM アイテムがあるため、さらに多くのイベントのキャンセル (またはキャンセル) を処理するのは面倒な場合があります。

HUD があまり頻繁に更新されない場合は、変更時にメモリ内キャンバスに描画し、フレームを更新するときに常にそのキャンバスをメイン キャンバスに描画するのが最も速い方法です。そうすれば、 drawHud メソッドは次のようになります。

function drawHUD() {
  // This is what gets called every frame
  // one call to drawImage = simple and fast
  ctx.drawImage(inMemoryCanvas, 0, 0);
}

もちろん、HUD 情報の更新は次のようになります。

function updateHUD() {
  // This is only called if information in the HUD changes
  inMemCtx.clearRect(0, 0, width, height);
  inMemCtx.fillRect(blah);
  inMemCtx.drawImage(SomeHudImage, x, y);
  var textToDraw = "Actually text is really slow and if there's" + 
                   "often repeated lines of text in your game you should be" +
                   "caching them to images instead";
  inMemCtx.fillText(textToDraw, x, y);
}

HUD にはテキストが含まれることが多いため、使用している場合はキャッシュすることを強くお勧めします。テキスト パフォーマンスの詳細については、こちら をご覧ください

于 2012-07-08T19:57:59.663 に答える
2

他の人が言ったように、普遍的に最適なアプローチはありません。それは、レンダリングする必要があるものの詳細、頻度、およびグラフィック コンポーネント間で発生する必要があるメッセージングに依存するためです。

確かに DOM リフローはコストがかかりますが、この包括的な警告が常に当てはまるとは限りません。たとえば、position:fixed; を使用します。要素は、ページのリフローのトリガーを回避します (固定されていない子がある場合、必ずしも要素内にあるとは限りません)。再描画は (これが間違っている場合は訂正してください) ピクセルのプッシュであるためコストが高く、同じ数のピクセルをキャンバスにプッシュするよりも本質的に遅くはありません。ものによっては、より高速になる場合があります。さらに、それぞれには、他の操作よりもパフォーマンス上の利点がある特定の操作があります。

考慮すべき点を次に示します。

多くの A グレードのブラウザーで、WebGL で高速化されたキャンバス要素を使用することがますます可能になっています。これは 2D では問題なく動作し、描画操作が GPU に送信されるという利点があり、これは 2D コンテキストよりもはるかに高速です。ただし、これは一部のターゲット プラットフォームでは利用できない場合があります (たとえば、この記事の執筆時点では、iOS Safari では利用できますが、ハイブリッド モバイル アプリケーションをターゲットとする場合に使用される iOS UIWebView では利用できません)。キャンバスをラップするライブラリを使用すると、これを抽象化できます。利用可能な場合は WebGL を使用します。pixi.js を見てください。

逆に、DOM には CSS3 アニメーション/トランジションがあり、通常は GPU によって自動的にハードウェア アクセラレーションされます (WebGL に依存しません)。アニメーションの種類によっては、キャンバスを使用するよりもこの方法の方がはるかに高速な結果を得ることができ、多くの場合、より単純なコードを使用できます。

最終的には、ソフトウェア パフォーマンスの原則として、使用されるアルゴリズムを理解することが重要です。つまり、どのアプローチを使用するかに関係なく、アニメーション フレームをどのようにスケジューリングするのでしょうか? どの処理に最も時間がかかるかをプロファイラーで確認したことはありますか? このプラクティスは、何がパフォーマンスに影響を与えているかを理解するのに優れています。

私は複数のアニメーションを含むアプリに取り組んでおり、各コンポーネントを DOM とキャンバスの両方として実装しています。最初は、DOM バージョンがキャンバス (KineticJS でラップされた) バージョンよりもパフォーマンスが高いことに驚きましたが、これはすべてのアニメーション化された要素が position:fixed であり、CSS (jQuery UI を介してボンネットの下で) を使用していたためであることはわかっています。 GPU パフォーマンスを取得します。ただし、これらの要素を管理するコードは扱いにくいと感じました (私の場合は ymmv)。キャンバス アプローチを使用すると、よりピクセル パーフェクトなレンダリングが可能になりますが、CSS でスタイルを設定する機能が失われます (技術的にはピクセル パーフェクト レンダリングも可能になりますが、実現するのは多かれ少なかれ複雑になる可能性があります)。

最も複雑なアニメーションをより低いフレームレートに調整することで大幅な速度向上を達成しました。これは、私の場合は 60fps バージョンと見分けがつきませんが、古い iPad 2 ではバターのようにスムーズに動作します。希望のフレームレートよりも。これを DOM 上の CSS アニメーションで行うのは困難です (繰り返しますが、多くの場合、これらは本質的に高速です)。私が次に見ているのは、複数のキャンバスベースのコンポーネントを同じ requestAnimationFrame ループに同期することです (おそらく個別に調整されるか、各コンポーネントがフレームレートの設定された割合を取得するラウンドロビン アプローチで、2 ~ 3 回は問題なく動作する可能性があります)。要素 (ちなみに、

また、プロファイリングを行い、GUI とは関係のないコード内の 1 つのクラスが、プロパティを計算するために非常に頻繁に呼び出される特定のメソッドを持っていることを確認することで、大幅な速度向上を実現しました。問題のクラスは不変だったので、メソッドを変更して値をメモすると、CPU 使用率が半分に低下しました。Chrome DevTools とフレーム チャートに感謝します。いつもプロフィール。

ほとんどの場合、更新されるピクセル数が最大のボトルネックになる傾向がありますが、GPU でそれを行うことができれば、コードのすべての CPU を効果的に取り戻したことになります。DOM リフローは避けるべきですが、これは DOM を避けるという意味ではありません。一部の要素は、DOM (テキストなど) を使用してレンダリングする方がはるかに簡単であり、キャンバスよりもブラウザー (または OS) のネイティブ コードによって最適化される場合があります。最後に、いずれかのアプローチ (DOM またはキャンバス) を使用して特定のコンポーネントで許容できるパフォーマンスを得ることができる場合は、そのタイプのコンポーネントを管理するためのコードを最も単純にする方法を使用してください。

最良のアドバイスは、さまざまなアプローチで分離された部分を試し、プロファイラーで実行し、テクニックを使用してオーバードローするか、制限をプッシュして、どのアプローチが最も速く実行できるかを確認し、必要になる前に最適化しないことです。このルールの警告は、あなたが尋ねている質問です:どの技術的アプローチが最高のパフォーマンスを可能にするかを事前に知るにはどうすればよいですか? 答えの仮定に基づいて 1 つを選択すると、基本的に時期尚早に最適化することになり、これが引き起こす恣意的な痛みに耐えることになります。代わりに、アプリケーションのニーズに焦点を当てたラピッド プロトタイピングまたは (さらに良い) 制御された実験によって選択している場合は、R&D を行っていることになります:)

于 2014-03-26T14:09:24.937 に答える
1

Browserquestは HTML 要素を使用して HUD を表示します。これには、再描画などについて心配する必要がないという利点があります (そして、DOM をかなり高速にレンダリングするようにブラウザー エンジン全体が最適化されているため、パフォーマンスはかなり良くなります。

彼ら (browserquest) も、さまざまなゲーム要素に複数のレイヤー化されたキャンバス要素を使用します。正確な構造はわかりませんが、要素がどのキャンバスに表示されるかは、再描画が必要な頻度に依存すると思います。

于 2012-07-08T17:00:27.360 に答える