2016-08-01 9 views
0

Ich arbeite an einem Raumschiff Shooter Stil Spiel. Im Spiel gibt es sich langsam bewegende Raketen, die ich auf verschiedenen Aufgaben leite.Wie viele Aufgaben sind zu viele

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

Sie tun nicht viel; Bewegen Sie einfach eine kleine Bitmap über den Bildschirm. Normalerweise ist es eine for-Schleife mit 30 Iterationen. Das Problem ist, dass das Timing ausgeschaltet ist und einige Aufgaben Vorrang vor anderen haben. Ich bin auch wichtig zu beachten, dass ich Thread.Sleep (100) verwende, um die Geschwindigkeit der Raketen zu steuern. Wegen dieser Verlangsamung wird die Methode für einige Sekunden ausgeführt.

I C# verwenden, .net, Windows Form Anwendung

Ich habe Stunden damit verbracht, darüber nachzudenken, wie diese neu zu formulieren, und ich denke, es ist richtig formuliert ist. Das Problem, das ich hatte, war breit; Ja, die Frage ist vielleicht ein bisschen breit. Ich habe eine tolle Antwort bekommen! Bedeutet das nicht, dass die Frage richtig gestellt wurde?

+0

Sie sollten keine Aufgabe für jedes Objekt im Spiel hochziehen. Tatsächlich gibt es normalerweise eine einzige Schleife, um alle Änderungen im Spiel zu steuern. Aus Gründen der Einfachheit sieht die Schleife so aus: while (isGameRunning) { Update (DateTime.UtcNow); Rendern(); } Sie sollten nur den tatsächlichen Geschwindigkeitsvektor für jedes Objekt im Spiel kennen und die neue Position in der Update-Methode berechnen. Dann zeichnet die Render-Methode den aktuellen Zustand - egal wie viel Zeit seit der letzten Aktualisierung vergangen ist, da die Entfernung angepasst wird. – Artak

Antwort

2

Da Sie bereits Task s (gut) verwenden, können Sie sie einfach und await Task.Delay(time) verwenden.

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

Auf diese Weise werden Sie nicht 1 Faden für jedes Geschoss binden. Höchstwahrscheinlich sind Ihre Aufgaben derzeit langsam, weil Sie das Limit Ihres Threadpools erreicht haben, das sollte also viel schneller sein. Sie sollten aber auch prüfen, ob Task.Delay mehr als die von Ihnen vorgeschlagenen 100 ms beansprucht hat. Wenn dies der Fall ist, zeichne die Kugel 2 Punkte weiter anstatt 1, und verschiebe sie entsprechend neu.

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); 
     } 
    } 

Schließlich könnte es eine gute Idee sein, nicht mit neuen Anrufen für jede Kugel Ihre Zeichenfunktion hämmern, sondern kombiniert alle Kugeln/Änderungen in eine einzige Funktion machen, der alle Änderungen berechnen und sendet sie in einem aus gehen. Aber das hängt davon ab, wie Ihre Zeichenfunktion selbst implementiert wird.

+0

Dies wird einfach nicht gut genug skalieren, um Animationen für ein Spiel zu tun, noch gibt es genügend Präzision in 'Task.Delay' – Servy

+0

@Servy' Task.Delay' ist genauso genau wie 'Thread. Schlaf ". Beide basieren auf der Systemuhr und sind in der Praxis bis zu 15ms genau. Diese Lösung wird zumindest keinen Faden für jede Kugel binden. Sie können Tonnen von zusätzlicher Logik hinzufügen, um zu berechnen, wie lange wir schlafen müssen, wie lange wir geschlafen haben (und Iterationen überspringen, wenn es über 100 ms war) usw. Aber das würde den Rahmen dieser Antwort sprengen. – Dorus

+0

Sie haben recht, dass 'Thread.Sleep' auch ein unzulängliches Werkzeug für Timing-Animationen ist; Dies wird durch das OP belegt, das eines seiner Hauptprobleme erwähnt, nämlich dass die Zeitabläufe alle ausgeschaltet sind und dass es sich um ein Kernproblem handelt, das er beheben muss, auf das Sie nicht eingehen.Es ist in der Tat viel besser, keinen ganzen Thread für jeden animierten Gegenstand zu binden, aber es ändert nichts an der Tatsache, dass es zwar besser ist, aber immer noch weit genug davon entfernt ist. – Servy

-1

Es hängt von der Maschine und der Anzahl der Gewinde ab, die es unterstützen kann. Auf der anderen Seite glaube ich nicht, dass es eine gute Übung ist, Thread.Sleep zu verwenden. Warum ändern Sie nicht einfach die Entfernung in Pixel, die das Objekt jede Millisekunde zurücklegt?

+1

Ich habe versehentlich hier geklickt –