2016-08-01 13 views
0

私は宇宙船のシューティングゲームに取り組んでいます。ゲームでは、私は別のタスクを実行する低速移動ミサイルがあります。タスクの数が多すぎます

Task t4 = new Task(() => fireShipCannons()); 

これらはあまり効果がありません。小さなビットマップを画面全体に移動するだけです。通常は30ループのforループです。問題は、タイミングがずれており、いくつかのタスクが他のタスクよりも優先されるように見えるということです。また、私はThread.Sleep(100)を使用しているミサイルの速度を制御することに注意することが重要です。このため、メソッドは数秒間実行されます。私はC#を使用しています

、.NET、Windowsフォームアプリケーション

は、私はこれを言い替えるする方法を考える時間を費やしている、と私はそれが正確に言葉で表現されると思います。私が抱えていた問題は幅広いものでした。そう、はい、その質問は少し広いかもしれません。私はすばらしい答えを得ました!それは質問が正しく尋ねられたことを示していませんか?

+0

ゲーム内のオブジェクトごとにタスクをスピンアップしないでください。実際には、ゲーム内のすべての変更を制御するために通常は1つのループがあります。簡単にすると、ループは次のようになります。 while(isGameRunning) { Update(DateTime.UtcNow); Render(); } ゲーム内の各オブジェクトの実際の速度ベクトルを知り、Updateメソッドで新しい位置を計算するだけです。次に、Renderメソッドは、現在の状態を描画します。距離が調整されるため、最後の更新からどれだけの時間が経過しても問題ありません。 – Artak

答えて

2

すでにTask(good)を使用しているので、async Tasksとし、await Task.Delay(time)とするだけです。

async Task fireShipCannons(CancellationToken ct) 
    { 
     for (int i = 0; i < distance; i++) { 
      await Task.Delay(100, ct); 
      drawBitmap(i); 
     } 
    } 

この方法では、すべての箇条書きに1つのスレッドを割り当てることはありません。あなたのスレッドプールの限界に達しているため、あなたのタスクは現在遅い可能性が高いので、これはずっと速くすべきです。しかし、さらに、Task.Delayがあなたが提案した100ミリ秒を超えているかどうかを確認する必要があります。それがあった場合は、弾丸を1の代わりに2つの場所にさらに描画し、それに応じて再スケジュールします。

async Task fireShipCannons(CancellationToken ct) 
    { 
     var start = DateTime.Now; 
     while (bullet.isOnscreen) { 
      drawBitmap(bullet); 
      var sleep = (start.Add(TimeSpan.FromMilliseconds(100.0)) - DateTime.Now); 
      if (sleep.Milliseconds > 0) { 
       Task.Delay(sleep, ct); 
      } 
      iter = (int)((DateTime.Now - start).TotalMilliseconds/100 + 0.5); 
      bullet.moveSteps(iter); // move it iter steps. 
      var start = start.AddMilliseconds(100 * it); 
     } 
    } 

最後に、すべての弾丸のための新しいコールを使用して描画機能をハンマーではないために良いアイデアが、代わりにすべての変更を計算し、1でそれらをオフに送信し、単一のレンダリング機能にすべての弾丸/変更を組み合わせることかもしれません行く。しかし、それは描画関数自体がどのように実装されているかによって異なります。

+0

これはちょうどゲームのアニメーションを行うのに十分にスケールアップされず、 'Task.Delay'に十分な精度もありません – Servy

+0

@Servy' Task.Delay'は 'Threadと同じくらい正確です。睡眠。両方ともシステムクロックに基づいており、実際には15msまで正確です。この解決策は、少なくともすべての弾丸のためのスレッドを結びつけません。追加のロジックを追加して、次にスリープするまでの時間、スリープしていた時間(そして100msを超えると繰り返しをスキップするなど)などを計算することができます。しかし、これはこの回答の範囲を超えています。 – Dorus

+0

あなたは 'Thread.Sleep'もタイミングアニメーションのための不十分なツールであることは間違いありません。これは、タイミングがすべてオフであり、彼が修正する必要がある、あなたが対処していないという重大な問題であるという彼の主要な問題の1つを述べているOPによって証明されています。アニメ化されている各アイテムに対してスレッド全体を結び付けないのは確かにはるかに優れていますが、それでも、それでもまだ十分に足りないという事実は変わりません。 – Servy

-1

マシンとサポートできるスレッドの数によって異なります。一方、私はThread.Sleepを使用することは良い習慣ではないと思います。オブジェクトがミリ秒ごとに移動する距離をピクセル単位で変更するのはなぜですか?

+1

私は誤ってここをクリックしました –

関連する問題