Framerate?

Jutschin

Mitglied
Hallo!

Folgendes Problem:

Ich habe eine Sidebar gebaut, die auf Knopfdruck in den Bildschirm slidet (und wieder raus, aber im Prinzip gleicher Code).

Das Problem: Je nach Wille des Computers gibt es Haker, Lags, Animation rennt nicht flüssig ab.

Nun ist die Frage, wie kann ich dieses Problem beheben, damit er gleichmäßig den Slide durchführt.

Zum Code: Anfangs geht die Animation bisschen schneller (bis 300px, dann wird sie zunehmend langsamer, damit ein "Smooth" entsteht, gewollt). "windoh" ist ein JWindow, ausgelöst wird die Animation durch ein JFrame (ein Pfeil an der rechten Kante des Bildschirms).

Problem hierbei wird das sleep sein, weil es nicht immer genau gleichmäßig ausgeführt wird. Doch welche Alternative gibt es dafür?

Java:
   for (int i = 0; i < 430; i++) {
                windoh.setLocation(x - i, y);
                windoh.repaint();

                if (i < 300) {
                    try {
                        Thread.sleep(0, 1000);
                    } catch (InterruptedException ex) {
                    }
                    continue;
                }
                if (i >= 300 && i < 350) {
                    try {
                        Thread.sleep(3);
                    } catch (InterruptedException ex) {
                    }
                    continue;
                }
                if (i >= 350 && i < 400) {
                    try {
                        Thread.sleep(5);
                    } catch (InterruptedException ex) {
                    }
                    continue;
                }
              if (i >= 400 && i < 430) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException ex) {
                    }
                    continue;
                }
}

Wäre nett, wenn mir jemand helfen könnte
 

Ark

Top Contributor
Ich bin mir gerade nicht sicher, wie die Frage gemeint ist.

Soll die Sidebar mit konstanter Geschwindigkeit eingeblendet werden, aber je nach Geschwindigkeit des Rechners sieht man nur wenige Schritte, und deshalb soll die Schrittweite der Rechenleistung angepasst werden?

Oder soll (unabhängig von der Rechenleistung) die Sidebar mit nicht konstanter Geschwindigkeit eingeblendet werden, z.B. sich langsam zum Ziel hin abbremsend?

Ark
 

bERt0r

Top Contributor
Falscher ansatz. Du brauchst konstante Sleep Zeiten um eine flüssige Animation hinzubekommen. Was du benötigst ist eine Formel, mit der du die aktuelle Position deiner Sidebar abhängig von der verstrichenen Zeit erhältst.
Das bedeutet es wird z.B alle 50 ms ausgerechnet wo die sidebar grade sein soll und dann gezeichnet.
 
Zuletzt bearbeitet:

Jutschin

Mitglied
Das ist mir schon klar, falls ich eine durchgehend flüssige Animation will, dass ich konstante Sleep zeiten brauche.

Es geht mir aber um den "Smooth", damit er bei fast erreichen der Position langsamer wird. Es funktioniert auch prima.

Das Problem dabei ist, wenn die CPU ausgelastet ist, dann kommen Hänger, Ruckler rein und das Frame slidet viel zu langsam. Das ist das Problem. Darum frage ich, wie man dies konstant halten kann, egal welche Auslastung herrscht.
 

bERt0r

Top Contributor
Nochmal: Dein Ansatz ist falsch. Nochdazu hast du so viele kleine sleeps, die deinen Rechner ausbremsen. Dadurch entstehen deine Ruckler. Wenn du das schon unbedingt so machen willst, zähle in deinen ifs die sleepdauer zusammen und mach dann ein sleep.
 

Jutschin

Mitglied
Ich glaube du verstehst mich nicht.

Es wird nur ein Sleep zeitgleich aufgerufen, nicht einige hintereinander, wenn du den Code genau anschaust.

Die Ruckler kommen davon, dass die CPU nicht immer sofort nach der Sleepdauer auf die Nanosekunde genau den Code weiterabarbeitet, da die CPU in der Millisekunde beschäftigt ist und nicht von zu vielen Sleeps.

Jetzt ist die Frage, wie kann ich einen festen Teil der CPU für mein Java Programm beanspruchen, der nur für mein Programm bereitsteht.
 

Ark

Top Contributor
@Jutschin: Ich glaube, du verstehst was nicht. ;)

Je "smoother" die Bewegung sein soll, desto mehr CPU-Last erzeugst du. Das wiederum bringt Ruckler rein, und dann ist die Bewegung doch wieder alles andere als "smooth".

Das heißt, du musst dich (je nach Prozessorlast, die das Zielsystem verträgt) auf eine bestimmte fps-Zahl festlegen. 25 fps sollten fürs menschliche Auge eigentlich reichen, das macht 1/25 s = 0,04 Sekunden oder 40 Millisekunden Pause zwischen jeder Bewegung:

Java:
final int SLEEP_TIME = 40; // Millisekunden, gleichbedeutend mit 1/fps
final int STEPS = 25; // Anzahl der verschiedenen Stellungen

for (int i = 0; i <= STEPS; i++) {
    windoh.setLocation(x - (int)Math.rint(430 * function((double)i / STEPS)), y);
    windoh.repaint();

    if(i < STEPS) { // Wenn wir am Ende sind, brauchen wir nicht noch zu warten.
        try {
            Thread.sleep(SLEEP_TIME);
        } catch (InterruptedException ex) {
        }
    }
}
Mit
Java:
private static final double function(double x){
    return x;
}

Wenn du SLEEP_TIME oder STEPS erhöhst, dauert's länger, bis die Bewegung komplett durchgeführt wurde. Je mehr STEPS du in der gleichen Zeit durchgeführt haben möchtest, desto "smoother", aber auch desto CPU-lastiger wird die Lösung.

[c]function()[/c] ist eine Methode, mit der du die Bewegung als solche beeinflussen können solltest. Wenn du da statt x z.B. [c]Math.sin(x * Math.PI / 2)[/c] zurückgibst, sollte das schon etwas anders aussehen. Das x, das da reinkommt, ist eine Zahl zwischen 0.0 und 1.0, wobei 0.0 die Anfangsposition bedeutet, während 1.0 bedeutet, dass wir nun am Ziel angekommen sein sollten. Entsprechend solltest du da nur was zurückgeben, das 0.0 ausgibt, wenn 0.0 eingegeben wurde, und 1.0 ausgibt, wenn 1.0 eingegeben wurde. Die Werte dazwischen kannst du nach belieben steuern. Beachte aber, dass, wenn deine Funktion nicht monoton steigend ist, das Ding zwischendurch wieder zurückfährt. :D

Ach, ja: mein gesamter Code ist komplett ungetestet. Aber ich hoffe, er zeigt in etwa, wo die Reise hingeht. ;)

Ark
 
Zuletzt bearbeitet:
Ähnliche Java Themen

Ähnliche Java Themen


Oben