bilder pro sekunde, scolling logik(verständnis)problem ?

  • Antworten:27
Sascha D.
  • Forum-Beiträge: 74

14.02.2012, 15:50:58 via Website

hallo leute,

ich habe folgendes problem:

ich lass einfach einen ball per surfaceview anzeigen in einem thread.
per currenttimemillies errechnet er einen wert von 1000 bilder pro sekunde die gerendert werden.
nun schicke ich den ball +1 pixel, heisst bei 800px displaybreite müsste der ball in ner 3/4sek durchschiessen, der bewegt sich aber gefühlt in zeitlupe.
warum ist das so ?

wie mache ich das, dass sich der ball auch die 1000 bilder pro sekunde bewegt oder eben per thread sleep 30 bilder pro sekunde bzw. 30 pixel/sekunde

Antworten
Sascha D.
  • Forum-Beiträge: 74

14.02.2012, 16:46:06 via Website

hab eben was festgestellt, wenn ich die fps so ermitteln lasse, wie siehe code, schafft der emulator mal gerade 6fps-
warum ist das so ? wenn die cpu nicht mal per anschlag ausgelastet ist. wie kann man den emulator schneller stellen oder sowas

public void run() {
while (running) {
if (!holder.getSurface().isValid())
continue;

zeit1=System.currentTimeMillis();
try {
Canvas canvas = holder.lockCanvas();
//Thread.sleep(1000/30);
ballX++;
canvas = RenderStrecke(canvas);
holder.unlockCanvasAndPost(canvas);
} catch (Exception e) {

}
zeit2=System.currentTimeMillis();

try {
fps = 1000 / (zeit2 - zeit1);
} catch (Exception e) {
// div durch 0
fps = 1000;
}
}
}

Antworten
Sascha D.
  • Forum-Beiträge: 74

15.02.2012, 08:50:17 via Website

hast du mal nen link zu der methode ?

Thread.sleep(1000/30);

müsste doch eingentlich alle 33ms ein bild generieren oder nicht ? sprich 30 bilder/sek.

Antworten
Gelöschter Account
  • Forum-Beiträge: 281

15.02.2012, 09:09:40 via Website

Bevor du dich hier in was versteigst, solltest du mal überlegen, ob du die Framerate wirklich vorgeben willst. Schau doch einfach, wie viel Zeit seit dem letzten Durchgang vergangen ist, rechne aus, wie weit das Objekt sich in deiner Spielewelt bewegt hat und zeichne es dann am neuen Ort - das bringt dir auf allen Devices immer die optimale Geschwindigkeit.

Antworten
Sascha D.
  • Forum-Beiträge: 74

15.02.2012, 09:22:57 via Website

das sleep war nur als test auskommentiert, weil der eh keine 30 gemacht hatte.

heisst also, wenn ich nen autorennen machen will und der soll sagen 200 fahren, dann rechne in x sek hat der x pixel zurück zu legen.
und an der stelle wird der dann neu gezeichnet. sprich auf nem langsamen siehts dann eher ruckelnd aus und auf nem schnellen flüssiger.

was geht eigentlich besser (schneller), die canvas geschichten oder lieber opengl in 2d benutzen ?

ich will quasi nen autorennen in draufsicht fummeln und wenn da die bilder eben nicht flüssig sind oder so wie ich mir das vorstelle, ist nicht so prickelnd.

Antworten
Sascha D.
  • Forum-Beiträge: 74

15.02.2012, 09:56:35 via Website

scheint so. in meinem buch stehts auch mehr oder weniger so. wenn man performance braucht, dann sollte mal opengl nehmen.
also werd ich mich mal einlesen.

Antworten
Sascha D.
  • Forum-Beiträge: 74

16.02.2012, 17:24:55 via Website

hab mal mit opengl gespielt. auch da eigentlich zu langsam.

wie bekommt man es hin, dass der eben in 1sek sauber 30 einzelne pixel setzt ohne ruckeln ?
irgendwie steh ich aufm schlauch.
wäre für nen tutorial dankbar.

damals bei j2me hab ich einfach thread.sleep genommen und damit sah es recht sauber aus mit 15fps.
jetzt kommt es mir irgendwie so vor bei android, dass der zu wenig bilder pro sekunde macht, wo doch die ondraw 120fps schaffen würde.

— geändert am 16.02.2012, 17:25:34

Antworten
Sascha D.
  • Forum-Beiträge: 74

16.02.2012, 17:41:59 via Website

mal nen beispiel wie ich das meine. warum kommt da 11 pixel pro sekunde raus und nicht 30 ?

public void run() {
long zeit1 = System.currentTimeMillis();
long pixelprosekunde = 0;

while (running) {
try {
if (!holder.getSurface().isValid())
continue;
Canvas canvas = holder.lockCanvas();
canvas.drawColor(Color.BLUE);
Thread.sleep(1000 / 30);
x++;
canvas.drawRect(x + 0, 100, x + 10, 100 + 10, paint);
canvas.drawText("PPS: " + pixelprosekunde, 50, 50, paint);
holder.unlockCanvasAndPost(canvas);
long zeit2 = System.currentTimeMillis();
// sekunden errechnen
long p = (zeit2 - zeit1) / 1000;
pixelprosekunde = x / p;
} catch (Exception e) {
}

}
}

Antworten
Florian B.
  • Forum-Beiträge: 284

16.02.2012, 18:51:56 via Website

Also korrigiert mich wenn ich falsch liege, aber im Moment schaut das doch bei dir so aus.

Du willst eine FPS von 30 Sekunden. D.h. ein Schleifendurchlauf darf max 1000/30 = 33.33333 Millisekunden dauern. Du lässt deinen Thread aber schon für 33.33333 Millisekunden schlafen und hast dann aber noch nichts gezeichnet und die FPS berechnet. Dafür brauchst du ja auch Zeit. Somit kannst du nie auf die 30 FPS kommen.

Antworten
Sascha D.
  • Forum-Beiträge: 74

16.02.2012, 19:03:41 via Website

ja schon, aber das problem ist eigentlich mehr, wenn ich den sleep weg nehme.
das handy zeigt es kann 115 fps berechnen. also müsste bei ner pixelbewegung + 1 das kästchen in 8 sek übern bildschirm geflogen sein.
aber der braucht locker gefühlte 2 min.

warum ist das so ?

wie stelle ich das an, dass der eben pro sekunde bei +1 sauber 30 pixel weiter setzt.

bzw. wie bekommt nen flüssige bewegung für autorennen hin ala sowas z.b. :
https://market.android.com/details?id=com.measuredsoftware.android.pocketracinglite&feature=search_result#?t=W251bGwsMSwxLDEsImNvbS5tZWFzdXJlZHNvZnR3YXJlLmFuZHJvaWQucG9ja2V0cmFjaW5nbGl0ZSJd

und das sieht für flüssig aus, ala um schneller das auto fährt um so mehr fps erzeugt der mit +1 pixel.
oder ist meine rangehensweise total falsch ala bei 10kmh macht der ehen 10pixel/sek und bei 200 wegen mir 80pixel/sek oder so.
oder fps.

irgend einer ne idee wie es flüssig geht ?

Antworten
Florian B.
  • Forum-Beiträge: 284

16.02.2012, 20:26:49 via Website

Ja irgendwie gehst du das komisch an. Irgendwie hab ich den Eindruck du hast das mit den FPS noch nicht so ganz verstanden. Sorry falls ich mich täusche aber irgendwie scheint mir das so.

FPS heisst Frames per second und gibt an, wie oft pro Sekunde der Inhalt des Bildschirms neu gezeichnet wird. Das ist letztendlich nur dafür wichtig, dass Objekte die sich bewegen, für das menschliche Auge flüssig erscheinen und nicht ruckeln. Mit der Geschwindigkeit wie schnell sich das Objekt von Punkt A nach B bewegt, hat das gar nix zu tun.

Wie Thomas M gesagt hat, ist es für den Anfang am einfachsten, die FPSs FPSs sein zu lassen und sich nicht darum zu kümmern, dass man eine bestimmte Anzahl schafft oder nur eine bestimmte Anzahl hat.


Probier das mal. Ich hab es jetzt nicht getestet, sondern aus dem Kopf zusammen geschrieben. Du lässt die Loop so schnell laufen wie es geht und misst bei jedem Durchgang wie viel Zeit vergangen ist, seit dem du das letzte mal die Position des Rechtecks aktualisiert hast. Dann wird berechnet wie viele Pixel sich das Rechteck in dieser Zeit bewegt hat und diese Anzahl wird auf die x-Position drauf gezählt.

Dann wird das Rechteck gezeichnet und der Frame Zähler eins hochgezählt. Am Ende wir dann noch überprüft ob eine Sekunde vergangen ist, wenn ja, dann wird der Counter ausgelesen und an die FPS übergeben und alles wieder zurück gesetzt.


// Position des Rechtecks
private int xPos = 0;
private int yPos = 0;

// Geschwindigkeit mit dem sich das Rechteck bewegt in Pixel pro Sekunde
private float xSpeed = 200;

// Variablen zum Brechnen der vom Rechteck zurückgelegten Strecke.
private long lastUpdate;
private long deltaTime;

// Variablen zum Berechnen von FPS
private int counter = 0;
private int fps = 0;
long startTime;

public void run() {
startTime = System.currentTimeMillis();
lastUpdate = System.currentTimeMillis();

while (running) {
if (!holder.getSurface().isValid()){

Canvas canvas = holder.lockCanvas();
deltaTime = System.currentTimeMillis() - lastUpdate;
updateModel(deltaTime);
draw(canvas);
holder.unlockCanvasAndPost(canvas);
counter++;

if(System.currentTimeMillis() - startTime > 1000){
// eine Sekunde ist rum
fps = counter;
counter = 0;
startTime = System.currentTimeMillis();
}
}
}
}

private void updateModel(long deltaTime) {
xPos += (deltaTime/1000f) * xSpeed;
lastUpdate = System.currentTimeMillis();
}

private void draw(Canvas canvas) {
canvas.drawColor(Color.BLUE);
canvas.drawRect(xPos, yPos, xPos + 10, yPos + 10, paint);
canvas.drawText("FPS: " + fps, 50, 50, paint);
}

— geändert am 16.02.2012, 20:36:03

Antworten
Sascha D.
  • Forum-Beiträge: 74

16.02.2012, 21:28:07 via Website

irgendwie klappt das nicht, der meckert die draw an,
dann hab ich einfach alles oben reinkopiert, dann schaltet der kurs auf vollbild um und beendet das programm gleich wieder.

Antworten
Florian B.
  • Forum-Beiträge: 284

16.02.2012, 21:35:48 via Website

Ich sagte ja, dass ich das aus dem Kopf zusammen geschrieben habe. Das sollte dir ja auch nur eine Idee davon geben, wie du das umsetzen kannst. Ich will dir ja hier auch nicht alles vorkauen.

Antworten
Sascha D.
  • Forum-Beiträge: 74

16.02.2012, 21:46:25 via Website

ich schau mir das morgen noch mal genauer an.
ich sag erstmal danke.

Antworten
Sascha D.
  • Forum-Beiträge: 74

16.02.2012, 22:28:22 via Website

achja, hat mal einer nen link, wo man sich das verfahren genauer durchlesen kann ?

Antworten
Sascha D.
  • Forum-Beiträge: 74

17.02.2012, 10:08:34 via Website

scheint, das zu sein, was ich gesucht habe.
danke.
jetzt muss nur noch durchlesen und kapieren warum das so ist.

Antworten
Sascha D.
  • Forum-Beiträge: 74

01.03.2012, 22:55:44 via Website

ach du schreck, ich habe mir mal youwave für android runtergeladen. das teil ist ja mal megaschnell.
da ist ja das orginal emu von google ne frechheit und schnecke gegen.
das das schon eher im speed nem realen device nahe kommt, bin ich schon am überlegen das teil zu kaufen.
spart ne menge zeit dem hin und her schieben der dateien und starten des emulators.

Antworten
reiti.net
  • Forum-Beiträge: 339

02.03.2012, 00:13:04 via Website

der original emulator emuliert ja auch das GESAMTE device exact .. das braucht schon ziemlich rechenleistung .. auf nem Q6600 ist aber für normale activites erträglich, muss aber zugeben, dass das starten am emulator auch wirklich schneller geht als gleich am handy zu starten .. :-)

für games gibts ja dank libgdx bessere möglichkeiten ... nutze den original emulator aber gerne um zu sehen wie ein spiel performed haha

aber mal im ernst: mit dem eigentlichen thread hat das nichts zu tun oder?

Antworten
Sascha D.
  • Forum-Beiträge: 74

02.03.2012, 09:11:20 via Website

nur indirekt. weil die game loop hat ja auch was mit geschwindigkeit zu tun.
und wenn ich sehe das der emu ne schnecke ist und aufm handy läufts wies soll, ich weiss ja nicht.
merkwürdig ist eher, dass der emulator ja die cpu überhaupt nicht ausreizt.

Antworten
Gelöschter Account
  • Forum-Beiträge: 281

02.03.2012, 09:29:55 via Website

Moment einmal - Games entwickeln in einem EMULATOR?

Antworten
Sascha D.
  • Forum-Beiträge: 74

09.03.2012, 15:17:18 via Website

so hab mir das mal durch den kopf gehen lassen und irgendwie klappt das nicht so, wie ichs mir vorstelle.

also wenn ich das richtig verstanden habe, dann verschiebt man nicht pixel pro bild in der sekunde sondern pixel auf die laufzeit, damit alles gleich schnell läuft.

also mal nen beispiel. sagen wir ich will das das spiel 30 fps fest hat und da soll es eben 1 pixel pro bild verschieben.

jetzt ermittelt man die echten bilder pro sekunde und es kommt z.b. 60 raus.
also 30/60 = 0.5 pixel/bild verschieben.
solange das so ist, is alles in ordnung, ich habe das problem, wenn die bilder zusammen sacken sollten, dann wäre z.b. rechnerisch bei 10 bilder pro sekunde 30/10 = 3 pixel/bild verschieben. was für ne gescheite erkennung von genzen zu grob ist. wobei das noch nicht in aber in meinem fall
finde ich fahren die autos schnell genug bei momentan angezeigten 60 fps und 4 pixel/bild oder so.
würde das jetzt wie im emulator auf 10 zusammen sacken, dann würde der pro pixel 60/10*4 = 40 pixel/bild schieben und das ist definitv zu grob.

sprich bei allem über 30 fps gehts, aber bei unter 30 fangen die probleme an.
oder hab ich da was falsch verstanden ?
ist der trick irgendwie anders.

Antworten
Gelöschter Account
  • Forum-Beiträge: 281

09.03.2012, 16:20:04 via Website

Du hast es immer noch nicht richtig verstanden. Du gibst nicht vor: Ich will 30 Frames pro Sekunde und will bei gegebener Objektgeschwindigkeit pro Bild eine Verschiebung um x Pixel haben. Das Prinzip heisst Frame-independent-Movement oder manchmal auch Time-based-Movement. Heisst: Du durchläufst jede Iteration des Game-Loop so oft es geht, berechnest die neuen Positionen deiner Objekte in deiner Spielwelt und zeichnest sie dort. Auf einem schnellen Handy schaffst du das 40 Mal in der Sekunde und hast dann 40 Frames, auf einem langsamen vielleicht nur 20 Mail und im Emulator 3 Mal. Und wenn du dann - egal wo ausser dem Emulator - zu wenig Frames für deinen Geschmack hast, musst du schauen, wo du beim Berechnen der Welt und beim Zeichnen (oder Simulieren und Rendern, wie die Freaks sagen) optimieren kannst, um dein FPS-Ziel zu erreichen.

Dieses Verfahren ist genau das, womit Ruckeln von Games auf langsamen Rechnern zu erklären ist: Die Zeit für einen Durchlauf des Game-Loop ist so lang, dass sich die Welt in der Zeit bis zum nächsten Durchlauf so weit verändert hat, dass der User keine flüssige Bewegung mehr wahrnimmt. Dennoch ist es das einzige Verfahren, dass eine Echtzeit-Darstellung von Bewegung ermöglicht - das was da versuchst, ist genau der umgekehrte Ansatz: Du willst auf jeden Fall erzwingen, dass alle Bewegungsphasen dargestellt werden, das hiesse im Ergebnis: Die Bewegung wäre flüssig im Sinne von "es fehlt keine dargestellte Position", würde aber wirken wie in Zeitlupe, je langsamer das Device, je mehr... Oder verstehe ich deine Vorgehensweise falsch?

— geändert am 09.03.2012, 16:21:24

Antworten
Sascha D.
  • Forum-Beiträge: 74

10.03.2012, 09:17:42 via Website

anscheinend hab ich das nicht.

also um es mal kurz zu sagen. sagen wir nen autorennen und das auto braucht bei nem gerät mit 60 bilder/s 1.
dann soll es j auf nem gerät mit 30 bilder/s auch 1 minute brauchen und nicht 2 min.
sprich er lässt ja zwischenframes aus.
also wo das gerät mit 60 fps da vielleicht noch 5 pixel/sen setzt muss das mit 30 fps ja schon 10 pixel/s setzen um anzukommen.
wenn ich jetzt aber ne randerkennung von 1 pixel genauigkeit haben will, wie stell ich das am besten an ?
als ne wand geht ja noch, da kann man ja zurück rechnen. aber hat man nen objekt was sagen wie 5x5 pixel hat.
das würde ja das gerät mit 30 fps übersehen, weil es mit 10 pixel übersprungen wird.

Antworten
Sascha D.
  • Forum-Beiträge: 74

20.04.2012, 11:48:46 via Website

entwickel jetzt auch direkt aufm handy. vorteil geht alles viel schnell und man sieht gleich was draus wird.

Antworten