dani93 hat geschrieben:LOL während ich gerade noch eine Frage dazu stellen wollte, hatte ich einen Geistesblitz
Nur gibts da das selbe Problem wie bei meinem Code (wenn ich das richtig verstanden habe):
Wenn ein Frame länger dauert als "max_fps_frametime", bekommt "frametime" nicht den gewohnten Wert und die Bewegung wird unregelmäßig.
Was heißt "gewohnter Wert"? Wenn ein frame länger dauert als max_fps_frametime, dann nimmst du einfach die Zeit die der letzte Frame gebraucht hat (unter der annahme dass der jetzige Frame genausolang brauchen wird) und multiplizierst diese Zeit damit, ist doch nicht so kompliziert,oder? Wenn deine Framerate hin und her springt kommst du nicht drumrum, dass es ruckelt. So viel vertrauen in den Rechner muss sein.
dani93 hat geschrieben:In dem Bruchteil einer Sekunde wird vielleicht der verhältnismäßig gleiche Weg zurückgelegt, aber trotzdem ist die Schlange dann nicht mehr in einem "Gitter".
Wieso denn nicht? Wieso speicherst du die Position der Schlange nicht
kontinuirlich in einem float ab, und veränderst diese auch korrekt mit der Zeit.
Das zurückrechnen ins "Gitter" ist dein geringstes Problem, das kannst du immer noch jedes mal dort machen wenn der Wert gebraucht wird, z.B. in der Move und Render Funktion. Das ist eine einfache Operation: %. Oder Wenn du deine Pixel in einem int speicherst brauchst du überhaupt keine Operation, sondern nur "position_discr = position_cont;", und der compiler erledigt dein Gitter für dich.
dani93 hat geschrieben:Ich weiß nicht, ob du dir den Code angesehen hast. Die Schlange bewegt sich konstant mit 10 Pixel pro Frame.
Ich glaub langsam kommen wir dem Problem näher:
Wieso bewegt sie sich denn konstant mit 10 Pixel pro Frame? Wieso bewegt sie sich nicht konstant mit v * t Pixel pro Frame, wobei v die geschwindigkeit ( z.B. 10 px/s) und t die Zeit des letzten Frames ist?
Dann kannst du auch das Level richtig anpassen, und erhöhst die Geschwindigkeit mit jedem Level. Ich sehe noch immer nicht, was das problem ist.
dani93 hat geschrieben:Je höher das Level, desto kürzer die Zeit zwischen den Frames,
Was hat die Framerate mit dem Level zu tun?? Die Framerate ist eine Technische Entscheidung, die vom Programmierer zu treffen ist. Die hat nichts mit dem Level zu tun, welches eine Spielvariable ist...
Wahrscheinlich war Kerlis pseudocode einwandfrei, deswegen werde ich ihn nicht wiederholen. Was ich aber wiederholen werde ist eine kleine Lehrstunde in Physik.
Die ganze Diskussion dreht sich hier um die Geschwindigkeit, und zwar um die Geschwindigkeit mit der dem User die Bewegung
erscheint.
Diese Geschwindigkeit v wird als "Momentangeschwindigkeit" bezeichnet, und ist der Differenzenquotient des Weges s nach der Zeit t:
v = ds / dt
Momentangeschwindkeiten gibt es auf dem PC nicht. Eine Zahl kann in einem Computer kann nicht "gegen 0 gehen".
Was auf dem Computer allerdings ist folgendes, und zwar dass du die
Unterschiede zwischen zwei Zuständen bezeichnest. Das würde so aussehen:
v = (s2 - s1) / (t2 - t1)
Hier wäre s2 der Zurückgelegte weg zum Zeitpunkt t2 und s1 der Zurückgelegte weg zum Zeitpunkt t1.
Also was brauchen wir um dem Benutzer eine kontinuirliche Bewegung vorzugaukeln? Zum Zeitpunkt t1 ist die schlange auf Position s1, und zum Zeitpunkt t2 ist die Schlange auf Position t2. So einfach ist das.
Bitte bemerke, dass ich bis jetzt noch kein Wort über Einheiten und Dimensionen verloren habe. v kann in m/s, km/h, oder px/ms angegeben sein, und dementsprechend auch s und t.
Auch noch kein Wort verloren habe ich über eine Implementierung.
Bis dahin muss dir das mal klar werden!
Wenn du soweit bist, dann können wir einen Blick auf die Anwendung wagen.
Wir haben gesagt, dass die gleichung
v = (s2 - s1) / (t2 - t1)
gelten muss, damit eine Bewegung kontinuirlich erscheint.
Jetzt denken wir mal nach, welche variablen der gleichung gegeben und welche gefragt sind. Wie stehts mit v? v ist die Geschwindigkeit, und sollte konstant bleiben (außer bei Levelsprüngen, aber dazu kommen wir später). Wie stets mit (t2 - t1) ? (t2 - t1) ist deine Framezeit! Das ist die Zeit, die der letzte Frame (als beste näherung für das was der jetzige Frame) an Zeit gebraucht hat. Was bleibt übrig? (s2 - s1), na klar! Das ist der Versatz, um den du die Schlange verschieben musst, damit die Bewegung flüssig erscheint.
also lösen wir nach (s2 - s1) auf:
v = (s2 - s1) / (t2 - t1) | * (t2 - t1)
v * (t2 - t1) = (s2 - s1)
(s2 - s1) = v * (t2 - t1)
So, was siehst du hier? Eine schon bekannt gleichung. Demnach ist die Strecke um die du die Schlange versetzen musst (das ist (s2 - s1)) gleich der gewünschten geschwindigkeit (v) mal der Zeit die der Letzte Frame gebrauch hat ( das ist (t2 - t1)).
Also, du misst wie lange ein Frame braucht, und bekommst dadurch (t2 - t1). Du gibst die gewünschte geschwindigkeit FIX an (kann ruhig const sein), denn so schnell wird sich deine Schlange bewegen.
Jetzt multiplizierst du die beiden, und kriegst deinen versatz raus: (t2 - t1)
Das ist eine einfache und doch funktionierende methode um die geschwindigkeit konstant zu halten.
So, nun wolltest du noch, dass die Schlange sich in einem höheren level schneller bewegt?
Sich schneller bewegen heißt,
eine höhere Geschwindigkeit haben.
Sagen wir, dass sich die Schlange pro Level um 10 % schneller bewegt. Das würde so aussehen:
v2 = v1 * 110 % = v1 * 1,1
Um die geschwindigkeit zu erhöhen brauchst du nur das v anpassen, und nicht an der Framezeit spielen.
Nochmal: die Framezeit solltest du
nach obenhin deckeln, sodass nicht die ganze CPU verbraucht wird. Dass die Framerate nicht immer auf Maximalniveau bleiben kann ist klar, kann gut passieren dass die mal absackt. Nur da passiert nichts, da du deine Bewegung mit den oberen berechnungen ja angepasst hast. Du hast es selbst schon sehr schön formuliert:
dani93 hat geschrieben:großer Weg * wenige FPS ~ kleiner Weg * viele FPS
So ist es, und nicht anders.
Haters gonna hate, potatoes gonna potate.