2016-07-03 9 views
5

私はそうのような更新方法でゲーム(MonoGame/XNAに基づく)を持っています。私の現在の解決策は次のとおりです:ポーリングシステムをRx.Net IObservableにするにはどうすればよいですか?私は、反応性のパターンにこれを変換したい</p> <pre><code>public void Update(GameTime gameTime) { component.Update(gameTime); } </code></pre> <p>:

public void Initialize() 
{ 
    updateSubject = new Subject<GameTime>(); 

    component = new Component(); 

    updateSubject.Subscribe((gameTime) => component.Update(gameTime)); 
} 

public void Update(GameTime gameTime) 
{ 
    updateSubject.OnNext(gameTime); 
} 

私はまだ仕事をする最善の方法を学んでいます。私は、Subjectは避け、Observable.Createは代わりに使うべきだと読んでいます。

ここではSubjectが適切ですか?

この場合、どうすればObservable.Createを使用できますか?

答えて

6

あなたがここで直面している重要な問題は、観測可能なソースが必要なことです。一般に、イベント、デリゲート、タスク、観測可能な拡張の多く(.Intervalまたは.Generateなど)、および件名からさまざまなソースからオブザーバブルを作成できます。

あなたの場合は、観測値の外部にあるプッシュ値をコードにすることができるソースが必要です。この場合、サブジェクトは完全に問題ありませんが、代理人だけでも使えます。

件名を使用する場合、コードは問題ありません。唯一の欠点は、updateSubject.OnCompletedと呼んで観察可能な状態に仕上げることができることです。

あなたは、デリゲートを使用したい場合は、あなたのコードは次のようになります。

あなたが updateGameTimeで行うことができる唯一のことは、新しい GameTimeに渡している。このように
private Action<GameTime> updateGameTime = null; 

public void Initialize() 
{ 
    component = new Component(); 

    Observable 
     .FromEvent<GameTime>(a => updateGameTime += a, a => updateGameTime -= a) 
     .Subscribe((gameTime) => component.Update(gameTime)); 
} 

public void Update(GameTime gameTime) 
{ 
    updateGameTime(gameTime); 
} 

- あなたがすることができません「偶然"シーケンスを終了します。

ここでは、被験者を使用した場合の問題点はObservable.Createとなり、状態の1つです。あなたのコードでは状態が必要なので、件名はOKです。一般的には可能ですが、可能であれば状態をカプセル化することをお勧めします。これがObservable.Createです。

(1)

 
0 
-4 
16 
-48 
128 
-320 
768 
-1792 
4096 
-9216 

(2)

 
0 
-4096 
16384 
-49152 
131072 
-327680 
786432 
-1835008 
4194304 
-9437184 
:私は二回、この観測可能に購読している場合、私はこれら二つの配列を取得し

var i = -1; 
var query = 
    Observable 
     .Range(0, 10).Select(x => 
     { 
      i = -i * 2; 
      return x * i; 
     }); 

この例を見てみましょう

シーケンスが変更されました私は州(すなわち、 var i = -1;)。

私はこの状態を避けることができObservable.Createでコードを書いていた:

var query = 
    Observable 
     .Create<int>(o => 
     { 
      var i = -1; 
      return 
       Observable 
       .Range(0, 10).Select(x => 
       { 
        i = -i * 2; 
        return x * i; 
       }) 
       .Subscribe(o); 
     }); 

それはまだ同じクエリですが、状態がカプセル化されているので、私は今、二回購読している場合、私は得る:

(1)

 
0 
-4 
16 
-48 
128 
-320 
768 
-1792 
4096 
-9216 

(2)

 
0 
-4 
16 
-48 
128 
-320 
768 
-1792 
4096 
-9216 

複雑なクエリを書くときに、ある件名を使うとずっと簡単になると思うかもしれないし、一般に間違いが起きることもあります。この場合、主語を使用する前に、常に純粋なオペレータのアプローチを見つけようとするべきです。そうでない場合は、Observable.Createに件名の使用をカプセル化することができます。

外部の状態が必要なため、件名を使用することは問題ありません。

0

あなたがコードしているのは、Rxを使用していることだけです。

public void Initialize() 
{ 
    //updateSubject = new Subject<GameTime>(); 

    component = new Component(); 

    //updateSubject.Subscribe((gameTime) => component.Update(gameTime)); 
} 

public void Update(GameTime gameTime) 
{ 
    //updateSubject.OnNext(gameTime); 
    component.Update(gameTime) 
} 

は、ここで私は Subjectを削除しただけのポイントを説明するために、 componentUpdate方法を介して直接呼び出します。

おそらく、プライベートなポーリング方法をお探しですか?この場合、Observable.Intervalを起動するのが良いかもしれません。

+1

私はSOの最小限の例を示しました。実際のコードはこれより複雑です。 – sdgfsdh

+0

それは良いことです。しかし、これが完全な最小限の検証可能な例であれば、Subject(したがってRx)は冗長です。私はあなたが賢明な答えを提供するのに十分な情報を提供しているとは思わない。 –

+1

私の 'IObservable 'が役に立つ入力の例です。 'IObservable 'を持っていれば、' GameTime'ストリームを使ってウィンドウを開くことができます。 – sdgfsdh

関連する問題

 関連する問題