7

OOP の知識を実践するために、JavaScript で Pong ゲームを作成しています (ギター ショップで Stairway to Heaven をプレイするようなものです)。プロトタイプ ベースの OOP や関数型スタイルなど、いくつかの異なる手法を実装することで、ゲームのいくつかの機能するバージョンを作成しました。ただし、機能的なゲームを取得するためにこれを行っているのではなく、学習するために行っています。

私は html5 キャンバスとプレーンな古い JavaScript を使用しています。ゲームを表す Pong オブジェクトがありました。Pongには、コンテキストctxへの参照を含む属性がありました。canvas.getContext("2d")また、何を知っているかを保持するためplayer1player2and属性もありました。ボールと 2 人のプレーヤーがインスタンス化されると、メソッドballで使用するコンテキストへの参照を保持できるように、コンテキストがコンストラクターに渡されました。draw(ctx)Pong には、draw()を使用して呼び出されるメソッドがありましたsetInterval(this.draw, 10)。Pong の draw メソッドは、2 人のプレーヤーとボールの draw メソッドを呼び出します。

2 人の選手とボールが属性としてコンテキストを持っているというのは、私には合いません。それらはコンテキストを所有していないため、属性であってはなりません。ただし、javascript とキャンバスを使用する性質上、これが最善の方法のようです。この状況では、誰または何がコンテキストを所有する必要がありますか? 理想的には、プレーヤーとボール オブジェクトに描画オブジェクトをまったく持たせたくないでしょう。ジオメトリと位置を記述する属性が必要であり、専用のオブジェクトがそれらを画面にレンダリングする必要があるように感じます。このようにして、将来、キャンバスの代わりに <div> を使用したいと決めた場合、レンダリング オブジェクトを変更するだけで、他のすべてのことを忘れることができます。

JavaScript Pong ゲームを必要以上に複雑にしていることはわかっていますが、テクニックを練習し、OOP の概念を本当に理解したいと思っていますが、それをクラックしたと思うたびに、私の「ソリューション」によって作成されたまったく新しい問題が発生します。 」が現れます。

編集:私のコードにうるさい人がいると助かる場合は、(ほぼ)完全に機能するバージョンを次に示します。

library.js - http://mikemccabe.me/tests/pong.archive.14.06.11/library.js

pong.js - http://mikemccabe.me/tests/pong.archive.14.06.11/pong.js

試してみてください - http://mikemccabe.me/tests/pong.archive.14.06.11/

4

4 に答える 4

1

あなたは物事を価値があるよりも複雑にしている。

専用オブジェクトは、それらを画面にレンダリングするタスクを実行する必要があります...

実行する必要のあるタスクがある場合、そのことを実行することで「オブジェクトにタスクが割り当てられている」と言うのは奇妙です。関数は物事を行います。オブジェクトはデータをカプセル化します。関数は、それらを画面にレンダリングするタスクを実行する必要があります。

この状況では、誰または何がコンテキストを所有する必要がありますか?

コンテキストを「所有」するものはありません。または、必要に応じて、キャンバスがコンテキストを所有しますが、なぜコンテキストを取得してどこかに配置するのかわかりません。ただ渡すよりも混乱するのではないかと思います。

編集:あなたのコードを一瞥して、あなたはPongクロージャーを「独自の」(つまり、参照を持っている)コンテキストにしました。これは十分に合理的と思われます。そのアプローチでどのような問題が予想されるのか、私にはよくわかりません。ただし、etcのコンストラクターに渡す必要があることに同意しません。さまざまなメソッドBallに渡す方がはるかに簡単だと思います。draw()

于 2011-06-15T19:26:44.580 に答える
1

コンテキストの使用に問題はありません。レンダリングをテクノロジに依存しないようにするという設計目標を達成するには、必要なレンダリング メソッドへの汎用インターフェイスを記述し、context代わりにこのインターフェイスを実装するために を使用するオブジェクトを作成する必要があります。次に、そのオブジェクトの別のバージョンを置き換えることができます。たとえば、Internet Explorer <9 で動作するようにすることができます。

Javascript では、スコープを使用して、アプリケーション内のオブジェクトが共有リソースに直接アクセスできるようにすると便利な場合が多いと思います。これは厳密には良い OO 設計ではありませんが、シングルトンと考えてください。例えば:

var Pong = (function() {
   var Graphics, graphics, Ball, ball1, ball2, play;
   Graphics = function() {
      this.context = ...
   };
   graphics = new Graphics();
   Ball = function() {
     // do something with graphics
   };
   ball1 = new Ball();
   ball2 = new Ball();
   // ball1 and ball2 will both be able to access graphics

   play =function() {
       // play the game!
   };
   return {
       play: play
   }
}());

これを一般化するには、直接Graphicsアクセスを提供するのではなく、オブジェクトに汎用メソッドをcontext持たせ、ブラウザに応じて正しいバージョンをインスタンス化して、複数のバージョンを持たせることができます。純粋主義を除いgraphicsて両方に明示的に割り当てることに比べて、マイナス面は実際にはありません。ほんの数個ではなく、数百個のオブジェクト (DOM 要素を表すなど) を扱う場合、利点が大きくなります。ball1ball2

于 2011-06-15T20:03:47.517 に答える
1

ポン特有ではありませんが、このオンラインブック

http://eloquentjavascript.net/chapter8.html

小さなゲームを構築する例があります。少し異なりますが、オブジェクト指向の原則の使用方法をうまく示しています。

コーディングはさまざまな方法で行うことができ、デザイン パターンを少し変更するのは簡単です。何でもそうですが、節度を守ってください。新しい言語で作業するときは、常に Nibbles/Snake を goto ゲームとして使用してきました。

于 2011-06-15T19:37:18.437 に答える
1

これは、MVC ( model-view-controller ) の原則を適用する素晴らしいケースかもしれません。

各ゲーム要素の状態を追跡するモデルを持つことができます。これらは、プレーヤー、パドル、ボールなどです。次に、現在の状態を描画するためのロジックのみを含むレンダラー (ビュー) を使用できます。ビューには、BallCanvasRenderer や PaddleCanvasRenderer などの名前を付けることができます。

ビューは適切にカプセル化されるため、キャンバス コンテキストへの参照を維持することは理にかなっていますが、レンダリングするたびに適切なコンテキストとモデルを渡すこともできます。

コントローラーは、ゲーム イベントへの応答とモデルの更新を担当します。

このパターンでは、任意のタイプのモデルに対して複数のレンダラーを維持するオプションも提供されることに注意してください。テキスト、ASCII アート、または OpenGL を出力するレンダラーを使用することもできます。

于 2011-06-15T19:47:45.190 に答える