Ankündigung

Einklappen
Keine Ankündigung bisher.

Frequenz von requestAnimationFrame ändern

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Frequenz von requestAnimationFrame ändern

    Ich habe eine Applikation mit Animationen. Diese werden mit requestAnimationFrame erzeugt.
    requestAnimationFrame hat ja in der Regel eine Frequenz von 60/s, bzw. richtet sich nach der Bildwiederholrate des Monitors.

    Auf meinem PC funktioniert das wunderbar, aber auf dem Raspberry Pi, wo die Applikation schlussendlich laufen soll ist die Frequenz deutlich niedriger. Warum das so ist weiss ich nicht; die Bildwiederholrate habe ich extra auf 60Hz festgelegt.
    Das problem ist, dass durch die niedrigere Frequenz ungewollte Effekte in der Animation auftauchen.

    Gibt es eine Möglichkeit, die Frequenz von requestAnimationFrame auf einen bestimmten Wert festzulegen?

  • #2
    Du bist hier bei Javascript, lauft mit Animationen gewöhnlich auf dem Client oder Browser und da hat der ausliefernde Server (Raspberry Pi) nichts mit zu tun.

    Wenn es anders ist, dann bitte mal mit lauffähigem Code damit sich das ansehen kann.

    EDIT:
    https://developer.mozilla.org/en-US/...AnimationFrame da muss nichts angepasst werden, da die Bildwiederholrate automatisch und passend eingestellt wird. Ab 30 sollte es eh flüssig laufen, zumindest für das menschliche Auge.

    Kommentar


    • #3
      Zitat von protestix Beitrag anzeigen

      Wenn es anders ist, dann bitte mal mit lauffähigem Code damit sich das ansehen kann.
      Das ist nun etwas schwierig, da das Ding nur als ganzes Projekt läuft und auf einem proprietären FrameWork basiert.
      Aber ich versuche das problem so gut es geht zu erklären. Ich habe eine Schlange, die aus mehreren Teilen besteht und bei jeder Wiederholung neu auf ein Canvas gezeichnet wird
      Code:
      paint: function () {
          var i,
          width,
          height;
      
          // Snake-Elemente mit Kollisionserkennung ermitteln
          if (this.snakeElementCount > 1) {
              for (i = 1; i < this.snakeElementCount; i++) {
                  if (i <= 6) {
                      this.snakeElements[i].testCollision = false;
                  } else {
                      this.snakeElements[i].testCollision = true;
                  }
              }
          }
      
          // Werte des Kopfelements bei Spielbeginn definieren
          if (this.snakeElements[0].x === null) {
              this.snakeElements[0] = {
                  x: this.x,
                  y: this.y,
                  testCollision: false
              };
              // this.grow() zwei Mal ausführen für Initiallänge(3)
              this.grow();
              this.grow();
          }
          this.directions[0] = this.direction;
      
          // Snake aussen zeichnen
          for (i = 0; i < this.snakeElementCount; i++) {
              if (this.directionChanges.length > 0 && i > 0) {
                  for (j = 0; j < this.directionChanges.length; j++) {
                      if (this.snakeElements[i].x === this.directionChanges[j].x &&
                          this.snakeElements[i].y === this.directionChanges[j].y) {
                          this.directions[i] = this.directionChanges[j].direction;
                          this.directionChanges[j].count--;
                      }
                      // nicht mehr benötigte Elemente aus directionChanges löschen
                      if (this.directionChanges[j].count === 0 && i === this.snakeElementCount - 1) {
                          this.directionChanges.splice(j, 1);
                      }
                  }
              }
      
              switch (this.directions[i]) {
              case 'R':
                  this.snakeElements[i].x += this.speed;
                  break;
              case 'L':
                  this.snakeElements[i].x -= this.speed;
                  break;
              case 'U':
                  this.snakeElements[i].y -= this.speed;
                  break;
              case 'D':
                  this.snakeElements[i].y += this.speed;
                  break;
              }
      
              this.context.fillStyle = 'black';
              this.context.beginPath();
              this.context.globalAlpha = 0.4;
              this.context.arc(this.snakeElements[i].x + (this.snakeElementWidth / 2), this.snakeElements[i].y + (this.snakeElementHeight / 2), this.snakeElementWidth / 2, 0, 2 * Math.PI);
              this.context.fill();
              this.context.globalAlpha = 1;
          }
      
          // Snake innen zeichnen
          for (i = this.snakeElementCount - 1; i >= 0; i--) {
              width = this.snakeElementWidth - this.border;
              if (width < 1) {
                  width = 1;
              }
              height = this.snakeElementHeight - this.border;
              if (height < 1) {
                  height = 1;
              }
      
              var grd = this.context.createRadialGradient(this.snakeElements[i].x + ((width + this.border) / 2), this.snakeElements[i].y + ((height + this.border) / 2), 3, this.snakeElements[i].x + ((width + this.border) / 2), this.snakeElements[i].y + ((height + this.border) / 2), 15);
              grd.addColorStop(0, this.borderColor);
              grd.addColorStop(1, this.newColor);
              this.context.fillStyle = grd;
              this.context.beginPath();
              this.context.arc(this.snakeElements[i].x + ((width + this.border) / 2), this.snakeElements[i].y + ((height + this.border) / 2), width / 2, 0, 2 * Math.PI);
              this.context.fill();
          }
      }
      this.speed hat auf dem Raspi den Wert 6. Auf meinem Rechner bewegt sich die Schlange mit diesem Wert aber viel zu schnell, weshalb ich ihn dort auf 2 gesenkt habe.
      Wie man sieht, kann mit den tasten L, R, U und D die Richtung geändert werden.

      Die Funktion grow() sieht so aus:
      Code:
      grow: function () {
          var lastElementX = this.snakeElements[this.snakeElementCount - 1].x;
          var lastElementY = this.snakeElements[this.snakeElementCount - 1].y;
          var lastElementDirection = this.directions[this.directions.length - 1];
      
          this.directions.push(lastElementDirection);
      
          for (i = 0; i < this.directionChanges.length; i++) {
              this.directionChanges[i].count++;
          }
          // Abstand zum nächsten Element festlegen
          // ACHTUNG! Abstand muss durch 'speed' teilbar sein!
          switch (lastElementDirection) {
          case 'R':
              lastElementX -= 12;
              break;
          case 'L':
              lastElementX += 12;
              break;
          case 'U':
              lastElementY += 12;
              break;
          case 'D':
              lastElementY -= 12;
              break;
          }
          this.snakeElements.push({
              x: lastElementX,
              y: lastElementY,
              testCollision: false
          });
          this.snakeElementCount++;
      }
      Die Animation läuft auf beiden Systeme flüssig, aber das Problem ist, dass sich die Schlange bei einem Richtungswechsel manchmal teilt, d.h. der Kopf bewegt sich in eine andere Richtung weiter als der Körper (manchmal teilt sich auch noch der Körper in weitere Teile auf). Dies passiert aber nur auf dem Raspi (dort ist Chromium installiert). Auf meinem Rechner habe ich die Applikation mit Firefox, Chrome, Chromium und Edge getestet (im Internetexplorer läuft die Applikation grundsätzlich nicht). Das Phänomen tauchte dort aber nie auf.

      Kommentar


      • #4
        Zusatz: ich habe die Bildwiederholungsrate meines Bildschirms versuchsweise auf 30Hz, bzw. 24Hz eingestellt. Das Problem taucht aber dennoch nicht auf.

        Kommentar


        • #5
          dir fehlt halt noch dein delta Wert

          https://coderwall.com/p/iygcpa/gameloop-the-correct-way

          du musst den unterschied zu deinen Positionen dazu addieren

          du siehst zb in der Demo http://jsfiddle.net/xDZa4/ dass da dx*delta gerechnet wird das gleiche musst du auch bei dir machen
          lastElementX -= 12 * delta;
          apt-get install npm -> npm install -g bower -> bower install <package> YOLO [URL]https://www.paypal.me/BlackScorp[/URL] | Mein Youtube PHP Kanal: [url]https://www.youtube.com/c/VitalijMik[/url]

          Kommentar


          • #6
            Zitat von BlackScorp Beitrag anzeigen

            du musst den unterschied zu deinen Positionen dazu addieren
            Das macht das Problem nur noch schlimmer.
            Zudem besteht das Problem ja nur auf dem Raspi. Wenn es am Deltawert liegen würde, würde das Problem ja auch auf meinem Rechner auftauchen.

            Kommentar


            • #7
              Zitat von MrChangelog Beitrag anzeigen

              Das macht das Problem nur noch schlimmer.
              Zudem besteht das Problem ja nur auf dem Raspi. Wenn es am Deltawert liegen würde, würde das Problem ja auch auf meinem Rechner auftauchen.
              Das Ding ist, requestAnimationFrame wird so oft es geht aufgerufen. Dein Raspberry PI ist langsamer also wird es nicht so oft aufgerufen wie auf deinem PC. Du musst also, damit es konstant bleibt. Deine Frames Per Second festlegen.

              Es gibt hier ein gutes gameloop tutorial https://www.koonsolo.com/news/dewitters-gameloop/ dort wird erklärt welche gameloops es gibt.

              Ich habe das ein wenig anders gemacht:

              https://github.com/BlackScorp/tiled2...me/game.js#L55 hier als Beispiel, da hab ich gesagt, ich will 25 FPS haben und bei jedem getAnimationRequest addiere ich ein frame dazu und gucke ob es durch 25 Teilbar ist, wenn nein dann mach ich nichts. Nachteil ist natürlich dass es bei schnellen PCs nicht flüssig ist

              Wie dem auch sei. Ich kann bei deinem Problem nicht direkt mit Beispielcode helfen weil ich deine Gameloop nicht gesehen habe. Du hast halt das Problem dass deine Geschwindigkeit abhängig ist von deiner PC leistung. deine x/y Werte aktualisieren sich so schnell es geht.
              apt-get install npm -> npm install -g bower -> bower install <package> YOLO [URL]https://www.paypal.me/BlackScorp[/URL] | Mein Youtube PHP Kanal: [url]https://www.youtube.com/c/VitalijMik[/url]

              Kommentar


              • #8
                Zitat von protestix Beitrag anzeigen
                https://developer.mozilla.org/en-US/...AnimationFrame da muss nichts angepasst werden, da die Bildwiederholrate automatisch und passend eingestellt wird. Ab 30 sollte es eh flüssig laufen, zumindest für das menschliche Auge.
                Ich habe die Applikation mittlerweile mehrfach überarbeitet. Die Schlange wird nun nach einem neuen Konzept erstellt und das "Splitting"-Problem existiert nicht mehr. Allerdings ist es nach wie vor so, dass ich auf dem Raspi die Bewegungsgeschwindigkeit 3-mal so hoch einstellen muss wie auf dem PC, damit sich die Schlange (für mein Empfinden) gleich schnell bewegt. Dabei ergibt sich leider eine Art Blinkeffekt; wohl weil die Schlange bei erhöhtem Speed mehr springt als gleitet.
                Aber wie BlackScorp sagt liegt das wohl an der (mässigen) Leistung des Raspi und ist kaum zu ändern.

                Kommentar


                • #9
                  Die Bewegungsgeschwindigkeit 3-mal so hoch einzustellen ist im Grunde eine Krücke.

                  Du weißt doch welche Bewegungsstrecke Du in 1 Sekunde zurücklegen willst. Nutze innerhalb Deiner "Draw" Routinen bspw. "DOMHighResTimeStamp", ermittle die Zeit die nach dem letzten Frame vergangen ist und passe Dein Bewegungsoffset entsprechend an. So hast Du, egal auf welchem Gerät, immer die gleiche Animationsdauer.

                  Kommentar


                  • #10
                    Vorab, hab die Beiträge nicht gelesen, nur die Überschrift.
                    Schon etwas älter, aber ich Glaube das die Diskussionsbeiträge zu "flüssige Animationen mit dem requestAnimationFrame" immer noch aktuell sind und das untermauern, was kaminbausatz #9 vorschlägt.

                    Kommentar


                    • #11
                      Zitat von kaminbausatz Beitrag anzeigen
                      So hast Du, egal auf welchem Gerät, immer die gleiche Animationsdauer.
                      Hab das mit dem Zeitunterschied mal getestet und habe festgestellt, dass die Animation so - selbst bei einem (theoretischen) Zeitinterval von 1ms - auf beiden Systemen extrem langsam läuft.

                      Kommentar


                      • #12
                        Ich habe das Gefühl, dass Du das nicht richtig verstanden hast. Ein Zeitintervall von 1 ms ist viel zu kurz.

                        Kommentar


                        • #13
                          Zitat von kaminbausatz Beitrag anzeigen
                          Ein Zeitintervall von 1 ms ist viel zu kurz.
                          Ist mir auch bewusst. Ein Zeitinterval von 16ms (für eine Frequenz von ~60Hz) macht die Sache aber auch nicht schneller.

                          Kommentar


                          • #14
                            Zitat von MrChangelog Beitrag anzeigen

                            Ist mir auch bewusst. Ein Zeitinterval von 16ms (für eine Frequenz von ~60Hz) macht die Sache aber auch nicht schneller.
                            60 Hz sind für den cinematographischen Effekt nicht notwendig.
                            Zu Deinem "Raspi"
                            https://www.heise.de/ct/artikel/Selb...n-4176097.html

                            ich nutze für so spielntests ab und an ein odroid mit emmc.

                            Kommentar


                            • #15
                              tomBuilder sehr interessanter Artikel!

                              Momentan nutze ich auf dem Raspi ein Raspian ohne GUI mit nachinstalliertem Matchbox Window Manager und Chromium. Ich frage mich, ob Raspian mit GUI eine bessere Performance hätte
                              Auf jeden Fall hilfreich wären eine schnellere Speicherkarte und eine Kühlung (was ich meinem Chef schon Monaten immer wieder sage). Allerdings hat meine Meinung als Lehrling erfahrungsgemäss wenig gewicht.

                              Kommentar

                              Lädt...
                              X