Willkommen ~Gast!
Registrieren || Einloggen || Hilfe/FAQ || Staff
Probleme mit der Registrierung im Forum? Melde dich unter registerEin Bild.
Autor Beitrag
000
09.01.2003, 14:31
JP



All meine OpenGL Sachen wechseln ständig die Geschwindigkeit. Wenn z.B. Winamp läuft hat es die richtige Geschwindigkeit.
Wenn aber nur die OGL Anwendung läuft, ist es viel zu schnell. Hab sowas schonmal gelesen, aber hab nirgends gefunden
wie man das löst.

auch wenns glaub ich ne dumme frage is...

Kann mir das einer mal sagen bitte. Danke.

--

Free your mind and your ass will follow!

zum Seitenanfang zum Seitenende Profil || Suche
001
09.01.2003, 15:31
Prefect



Du willst niedrigere Framerates? Wo gibt's denn sowas... ;)

Nein, im ernst: Dein Problem ist wahrscheinlich, daß du Animationen usw. nicht zeitgebunden ablaufen läßt. Wenn du ein Objekt über den Bildschirm bewegst (wie z.B. in Pong den Ball), dann ist die naive Lösung dafür, einmal pro Frame folgenden Code auszuführen:

Quellcode:ball.position += ball.velocity;
(ich gehe einfach mal davon aus, daß position und velocity Vektoren mit vernünftig überladenen Operatoren sind)

Da aber ein Frame mal länger und mal kürzer dauert ist das falsch. Du mußt die Dauer eines Frames in die Rechnung mit einbeziehen. In der Praxis sieht das dann in etwa so aus:

Quellcode:float g_flFrametime; // in Sekunden!

void Ball::think()
{
  position += velocity * g_flFrametime;

  .. Kollision hier
}

void mainloop()
{
  int lastframe = SDL_GetTicks();

  while(running) {
    int time = SDL_GetTicks();
    g_flFrametime = (float)(time - lastframe) / 1000.0;

    ... Logiccode und Rendering hier

    lastframe = time;
  }
}
Dadurch, daß du die Geschwindigkeit (die in diesem Fall in Einheiten pro Sekunde, wahrscheinlich also Pixel pro Sekunde angegeben ist) mit der Frametime multipliziert bewegt sich der Ball immer mit derselben Geschwindigkeit.

cu,
Prefect

--

Widelands - Gemütliche Aufbaustrategie, Free Software
Noch ein Blog - Lerne, wie die Welt wirklich ist, aber vergiss niemals, wie sie sein sollte.

zum Seitenanfang zum Seitenende Profil || Suche
002
09.01.2003, 17:13
the_viking



das prob hat ich auch mal :)
aber irgendwie funzt das mit den winapi funcs (QueryPerformanceCouter) net... *g* muss mal gucken woran das liegt ;)

--

thx, cu, MfG the_viking

(( My =]=H=O=M=E=> Page! ))
Coder bei Brainshock-Interactive und bei Z-Software
My ICQ: #160959446

zum Seitenanfang zum Seitenende Profil || Suche
003
09.01.2003, 21:35
JP



@Perfekt:
Sieht mir nach SDL aus... Er konnte auf jeden Fall die SDL_GetTicks(); Funktion nicht finden.

Noch was...
Wie kann ich bei Texturen bestimmte farben Transparent machen?
Aber wer die erste Frage weiss erklärt mir lieber die nochma... (ich mach OGL noch nich lang)

Thx JP

--

Free your mind and your ass will follow!

zum Seitenanfang zum Seitenende Profil || Suche
004
09.01.2003, 21:57
Prefect



wrt SDL_GetTicks: Du brauchst irgendeine Funktion, die dir die Zeit zurückgibt.

Transparenz von Texturen: Dazu brauchst du einen Alphakanal, d.h. du mußt die Texturen als GL_RGBA hochladen. Wenn du die Texturen als Bitmaps mit Colorkey vorliegen hast mußt du den Alphachannel bei allen Pixeln mit Colorkey auf 0 setzen, bei allen anderen Pixeln auf 255 (oder 1.0 wenn du mit floats arbeitest).

cu,
Prefect

--

Widelands - Gemütliche Aufbaustrategie, Free Software
Noch ein Blog - Lerne, wie die Welt wirklich ist, aber vergiss niemals, wie sie sein sollte.

zum Seitenanfang zum Seitenende Profil || Suche
005
10.01.2003, 20:48
JP



Prefect: Du ziest doch die Variablen "time" und "lastframe" voneinander ab. Sie haben aber doch den selben wert. Dess halb müsste
das doch dann 0 ergeben... Die Wirkung war zumindest so. Alles blieb stehen. Aber ich hatte auch das "int lastframe = SDL_GetTicks();"
oder bei mir "int lastframe = GetTickCount();" bzw. "int lastframe = time(NULL);" zur globalen variaben gemacht, da mit der while schleife garnichts ging... liegt also warscheinlich daran... aber wie du siest, hab immernochnich gecheckt...

edit:
Habs geschafft! Hab mir selber was ausgedacht (macht eh mehr spass ;). Aber es is in der richtung von Prefects lösung.
Danke.

--

Free your mind and your ass will follow!


Dieser Beitrag wurde am 10.01.2003 um 23:48 von JP bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
006
11.01.2003, 11:50
Mazze



Zitat:
Sie haben aber doch den selben wert
Nein, wieso?
Außer dein Code zwischen den GetTicks() Aufrufen ist sehr klein und die Uhr kommt nicht mit!

cu
Matze

--

BattleTech-MOD:
http://bthl.unitedgaming.net/

zum Seitenanfang zum Seitenende Profil || Suche
007
27.01.2003, 16:29
King of Darkness



das werfe ich jetz mal komentar los ein:

http://www.codeworx.org/gamedev_tuts_timing.php

sollte das problem lösen mehr oder weniger

--

Coding Center --- Tutorials über Programmierung und andere Themen
Amazon Preisbeobachung mit Preisalarm

zum Seitenanfang zum Seitenende Profil || Suche
008
12.03.2003, 11:05
WareWolf



passt gerade zum Thema, deshalb kurz ne Zwischenfrage:

ich habe Timingprobleme immer so gelöst, dass ich in der Hauptschleife auf ein konstantes Hardwaresignal z.B. auf den Strahlrücklauf des Monitors getriggert habe:
Quellcode:;auf den Start des BS Aufbaus warten
       mov dx,3dah
qlM1:  in al,dx
       test al,8
       jne qlM1
qlm2:  in al,dx                 ;auf den Start des Rücklaufs warten
       test al,8
       je qlm2
Das funktioniert natürlich nicht in win_32_C++, da ja inline_asm die Portbefehle nicht ausführt. In purem Assembler funktioniert es noch auf win_32 Systemen, allerdings nur im Vollbildmodus.
In der Fensterdarstellung wird nichts mehr synchronisiert und die Anwendung läuft zu schnell.
Hat jemand eine Idee, auf welches konstante Ergeignis man dort synchronisieren könnte?

--

Sig as a brick ┴┬┴┬┴┬┴┬┴┬┴┬┴
WW

zum Seitenanfang zum Seitenende Profil || Suche
009
12.03.2003, 11:22
King of Darkness



uff das klingt aber kompliziert, oder doch nicht ?!

nur wie du sagst geht es nur bei vollbild, was, mhhh, ja, nich ganz ordenlich ist, ok wer spielt schon im fenster, aber es soll solche leute geben ;)

@perfect
weil ich das da ganz oben gerade sehe mit dem think, wie geht das also wenn ich im HL ne think funktion mache dann ja so:
SetThink(thinkfunc);
...
das habe ich mal versucht nachzucoden, nur mit wenig erfolg
#define SetThink(x) x();

ich glaube nicht das das ordendlich ist, es geht zwar aber ich will mal wissen ob man es vieleicht auch einfacher machen kann ?
oder ist das schon die beste lösung

--

Coding Center --- Tutorials über Programmierung und andere Themen
Amazon Preisbeobachung mit Preisalarm

zum Seitenanfang zum Seitenende Profil || Suche
010
12.03.2003, 13:23
Prefect



WareWolf: Kannst du nicht einfach die momentane Systemzeit auslesen und mit einem Timeout vergleichen? Vielleicht kriegst du ja sogar Zugriff auf den PIT oder den TSC (natürlich nur auf den Prozessoren, die einen TSC haben).

King of Darkness: Dein SetThink()-Makro ruft die übergebene Funktion einfach nur auf. Warum schaust du dir nicht einfach mal an, wie das Problem im HL SDK gelöst ist?

Hmm, wobei die Lösung im HL SDK nicht gerade sauberstes C++ ist. Da müßte ein ge-templateter static_cast her...

cu,
Prefect

--

Widelands - Gemütliche Aufbaustrategie, Free Software
Noch ein Blog - Lerne, wie die Welt wirklich ist, aber vergiss niemals, wie sie sein sollte.


Dieser Beitrag wurde am 12.03.2003 um 13:23 von Prefect bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
011
12.03.2003, 14:40
WareWolf



@Prefect: die Systemzeit über Ports auslesen wird zu ähnlichen Problemen führen, da die Ports entweder gesperrt oder nur emuliert sind, aber ich erinnere mich, die Systemzeit in festen Speicherzellen vorzufinden. Allerdings werden diese Speicherzellen nur 18 mal/Sek vom Bios inkrementiert, was als maximale Framerate schon wieder zu langsam wäre...OK, ich werde das mal checken ist zumindest ein guter Ansatz.
Thx

--

Sig as a brick ┴┬┴┬┴┬┴┬┴┬┴┬┴
WW

zum Seitenanfang zum Seitenende Profil || Suche
012
12.03.2003, 22:52
Tron



unter windose QueryPerformanceCounter(), hat normalerweise eine aufloesung von 1.193.180 Hz (standardfrequenzquartz fuer den programmierbaren timer) oder sogar der takt des prozessors, das sollte auch den hoechsten anspruechen genuegen. unter unix, linux ... gibt's sicher aehnliches.

und falls du mit OpenGL arbeitest synchronisiert wglSwapBuffers (windose, andere systeme entsprechendes) mit eingeschaltetem vsync (ueber eine OpenGL erweiterung)

--

'KEINE PANIK' - aus der Triologie in fuenf Baenden von Douglas Adams

'FÜR DEINN FERD' - aus 'Gevatter Tod' von Terry Pratchett

zum Seitenanfang zum Seitenende Profil || Suche
013
13.03.2003, 11:52
King of Darkness



@ perfect

das würde ich ja gerne aber ich komme ja nicht zu der lösung im HL sdk (das steht ja nicht direkt im sdk, im sdk wird es nur angewand), ansonsten würde ich ja nich fragen

wie genau soll den eigendlich der timer sein reichen denn nicht einfache milisekunden ? unter dem link den ich da oben gepostet habe gibt es 2 arten von timern, für die klickfaulen ;)
BOOL QueryPerformanceFrequency(LONGLONG *lpFrequency); //ca. 1 Mikrosekunde 1/1000000 sec
DWORD timeGetTime(); // für milisekunden 1/1000 sec

genaueres unter dem link

--

Coding Center --- Tutorials über Programmierung und andere Themen
Amazon Preisbeobachung mit Preisalarm

zum Seitenanfang zum Seitenende Profil || Suche
014
13.03.2003, 17:04
Prefect



Oh doch, King of Darkness, das gesamte SetThink()-Handling ist im SDK, du musst nur lange genug suchen. cbase.h war das, wenn ich mich richtig erinnere.

Unter *nix verwendet man übrigens gettimeofday(), das dürfte selbst auf den ältesten Rechnern dank PIT eine Auflösung von Mikrosekunden haben.

cu,
Prefect

--

Widelands - Gemütliche Aufbaustrategie, Free Software
Noch ein Blog - Lerne, wie die Welt wirklich ist, aber vergiss niemals, wie sie sein sollte.

zum Seitenanfang zum Seitenende Profil || Suche
015
14.03.2003, 20:29
the_viking



man wieso macht ihr es euch so kompliziert....

Quellcode:DWORD last_tick;
bool bRunning = true;

void Start()
{
last_tick = getTickCount();
}

void mainloop()
{
while(bRunning)
{
  DWORD now = getTickCount();
  DWORD gone = now - last_tick;

  if(gone == 0)
    continue;

  float fTime = ((float)gone) / 1000.0f;

  ProcessAllEntities(fTime);
  Render();

  last_tick = now;
}
}
Das sollte doch wohl die sauberste und kompatibelste Lösung sein, oder?

--

thx, cu, MfG the_viking

(( My =]=H=O=M=E=> Page! ))
Coder bei Brainshock-Interactive und bei Z-Software
My ICQ: #160959446

zum Seitenanfang zum Seitenende Profil || Suche