Frames per Second
-
Wenn du eine Nvidia Karte hast kannst du VSync relativ einfach in diesem Control-Center einschalten. Das begrenzt deine Frames auf 60/s begrenzen. Bei ATI-Karten dürfte es auch nicht viel schwerer sein. Falls du erst mal eine schnelle Lösung suchst.
-
vsync schrieb:
Wenn du eine Nvidia Karte hast kannst du VSync relativ einfach in diesem Control-Center einschalten. Das begrenzt deine Frames auf 60/s begrenzen. Bei ATI-Karten dürfte es auch nicht viel schwerer sein. Falls du erst mal eine schnelle Lösung suchst.
Nicht auf 60, sondern auf die Refresh-Rate deines Monitors. Bei mir waren das immer 60Hertz
-
PadMad schrieb:
Wie setzt man das am klügsten um?
Entweder indem du die Geschwindigkeit mit der Zeit multiplizierst, oder, wenn du fixe Logik-Intervalle haben willst (das kann von Vorteil sein, wenn man immer die exakt gleichen Ergebnisse haben will), dann "sammelst" du die Zeit und wenn du genug hast, machst du einen Logik-Schritt. (Oder mehrere.)
-
Das sind alles sehr hilfreiche Tipps. Ich denke ich werde mich für die Variante mit der Zeit, die mulitpliziert wird entscheiden. Mir fehlt momentan nur die Idee für die Mausbewegung. Weil ein Mauszeiger hat sogesehen ja keine Geschwindigkeit.
Da wird ja, denke ich, neugezeichnet, wenn sie ihre Koordinaten verändert.
-
Mauszeiger würde ich entweder das System zeichnen lassen, oder in einem separaten Thread behandeln.
-
cooky451 schrieb:
Mauszeiger würde ich entweder das System zeichnen lassen, oder in einem separaten Thread behandeln.
Und was soll dieser Thread machen?
-
-
Ein guter Beitrag. (der davor)
Ich habe versucht das jetzt umzusetzen. Angefangen habe ich beim Problem mit der Maus. Ich habe einen eigenen Mauszeiger erstellt und möchte den, je nach Bewegung, rendern. Mein Bildschirm ist im übrigen auf 60 Hertz eingestellt.
Wenn ich meinen programmierten Mauszeiger auf 60 Hertz einstelle, dann sieht man wie der Bildschirm nicht hinterherkommt, da die Maus nie ganz gezeichnet wird. Bei 10 FPS kommt der Bildschirm hingegen noch mit und die Grafik wird immer ganz gezeichnet. Der SDL_Renderer wurde mit SDL_RENDERER_PRESENTVSYNC erstellt.
C++ / SDL2
main.cpp
int main(int argc, char* args[]) { SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_TIMER | SDL_INIT_AUDIO); CBuild * pBuild = new CBuild; STimeWindow * pTimeWindow = new STimeWindow; pTimeWindow->TimeStampA = 0; pTimeWindow->TimeStampB = SDL_GetTicks(); double time_dif = 0.0; pBuild->init(); if(pBuild->getWindowX() < 1024 || pBuild->getWindowY() < 768) { SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Niedrige Aufloesung", "Leider ist die Aufloesung zu niedrig.\nDie Aufloesung muss mindestens 1024 x 768\nbetragen.", NULL); } else { while(pBuild->getExecuteFlag()) { pBuild->draw(); pBuild->update(time_dif, pTimeWindow->TimeStampB); time_dif = (pTimeWindow->TimeStampB - pTimeWindow->TimeStampA); time_dif *= 0.001; pTimeWindow->TimeStampA = pTimeWindow->TimeStampB; pTimeWindow->TimeStampB = SDL_GetTicks(); } } SDL_Quit(); delete pTimeWindow; return 0; }
cbuild.cpp
/////////////////////////////////////// /////////////////////////////////////// // constructor / destructor /////////////////////////////////////// /////////////////////////////////////// CBuild::CBuild(): execute(1), fps(60) { pWindow = NULL; pRenderer = NULL; pWndSurf = NULL; pCursor = new CCursor(); } CBuild::~CBuild() {} /////////////////////////////////////// /////////////////////////////////////// // private methods /////////////////////////////////////// /////////////////////////////////////// void CBuild::init_window() { SDL_GetCurrentDisplayMode(0, &displaymode); pWindow = SDL_CreateWindow ( "Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, displaymode.w, displaymode.h, SDL_WINDOW_SHOWN ); pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_PRESENTVSYNC); pWndSurf = SDL_GetWindowSurface(pWindow); } void CBuild::handleEvents() { while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_KEYDOWN: { this->event_keydown(); } break; }; } } void CBuild::event_keydown() { switch(event.key.keysym.sym) { case SDLK_ESCAPE: { execute = 0; } break; }; } /////////////////////////////////////// /////////////////////////////////////// // public methods /////////////////////////////////////// /////////////////////////////////////// bool CBuild::getExecuteFlag() { return execute; } int CBuild::getWindowX() { return displaymode.w; } int CBuild::getWindowY() { return displaymode.h; } /////////////////////////////////////// /////////////////////////////////////// // main methods /////////////////////////////////////// /////////////////////////////////////// void CBuild::init() { this->init_window(); pCursor->initCursor("graphics/cursor.png", fps, pRenderer); } void CBuild::draw() { SDL_SetRenderDrawColor(pRenderer, 0x00, 0x00, 0x00, 0xff); SDL_RenderClear(pRenderer); pCursor->drawCursor(pRenderer); SDL_RenderPresent(pRenderer); } void CBuild::update(double timestep, int timestamp) { this->handleEvents(); pCursor->moveCursor(timestamp); }
ccursor.cpp
/////////////////////////////////////// /////////////////////////////////////// // constructor / destructor /////////////////////////////////////// /////////////////////////////////////// CCursor::CCursor(): time_move(0), time_step(0) { pPosition = new SDL_Rect; pTexture = NULL; } CCursor::~CCursor() {} /////////////////////////////////////// /////////////////////////////////////// // methods /////////////////////////////////////// /////////////////////////////////////// void CCursor::initCursor(char * pFile, int nFPS, SDL_Renderer * pRenderer) { SDL_Surface * pSurfImage = NULL; time_step = 1000 / nFPS; SDL_ShowCursor(0); pSurfImage = IMG_Load(pFile); pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurfImage); pPosition->w = pSurfImage->w; pPosition->h = pSurfImage->h; SDL_FreeSurface(pSurfImage); SDL_SetTextureBlendMode(pTexture, SDL_BLENDMODE_BLEND); SDL_SetTextureAlphaMod(pTexture, 0xff); } void CCursor::moveCursor(int timer) { if(timer >= time_move) { SDL_GetMouseState(&pPosition->x, &pPosition->y); time_move += time_step; } } void CCursor::drawCursor(SDL_Renderer * pRenderer) { SDL_RenderCopy(pRenderer, pTexture, NULL, pPosition); }
Fakt ist, dass er eigentlich 30 FPS in der CCursor Klasse schon nicht mehr hinbekommt. Der Cursor, den ich verwende, kann hier heruntergeladen werden:
http://www.wp1105995.server-he.de/cursor.png
Das heißt, ich muss irgendwas grundlegend mit SDL2 falsch machen.
-
Nutze am besten erst mal den Default-Cursor des Systems und mach das später, bis dein Programm ordentlich läuft.
-
Das ist ja aber 1 von 2 Hauptproblemen. Die Maus mit eigenem Cursor.
Das 2. Hauptproblem ist, dass der Bildschirm bei Animationen ebenfalls nicht hinterherkommt. Das will ich jetzt aber durch die neue Zeitlogik mal testen. Indem ich stoppe wie lange das Programm zum Zeichnen eines Frames braucht. Das war ja vorher nicht so.
-
spar dir viel arbeit und installiere dir einen profiler, z.b. AMDs codeanalyst und schau wo die performance verloren geht.
bei sowas einfachem solltest du auf jeden fall 60fps hinbekommen, selbst auf einem 10jahre alten rechner.
-
Hey,
Visual Studio 2013 liefert den sogar mit. Ich habe einen CPU Leistungstest gemacht. Der Graf kratz halt kurz über der 0% Hürde. Ich kann daraus auch keine Auffälligkeiten entnehmen.
Das gleiche Problem habe ich aber auch auf einem anderen Gerät. Ich meine das mit dem nicht hinterherkommen beim Zeichnen, was mich nach wie vor glauben lässt, dass ich irgendwas im Code bezüglich SDL falsch mache.
Die Anwendung:
http://www.wp1105995.server-he.de/Beispiel.zipDer Leistungsbericht:
http://www.wp1105995.server-he.de/CPU.zip
-
Lad mal das VS Projekt mit Sourcecode hoch.
-
Ich habe einfach mal den ganzen Projekt Ordner gezippt und hochgeladen. Bin gespannt, wie das bei euch läuft.
Danke schonmal vorweg.
-
Ändere mal
pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_PRESENTVSYNC);
auf
pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_PRESENTVSYNC|SDL_RENDERER_ACCELERATED);
Macht das einen Unterschied?
edit:
Und warum benutzt du nicht http://wiki.libsdl.org/SDL_CreateCursor ?
-
Hey,
Nein, das macht leider keinen Unterschied. Schon probiert.
Und SDL_CreateCursor ist nur für schwarz / weiß, wenn ich das richtig verstanden habe. Hatte ich oben auch schon erwähnt."If you want to have color cursor, then this function is not for you; instead, you must hide the normal system cursor (SDL_ShowCursor) and in your main loop, when you draw graphics, also draw a SDL_Surface at the location of the mouse cursor." - SDL Seite
Mir geht es auch weniger um die Maus, als um die Tatsache, dass der ja auch beim Animieren des Models nicht hinterherkommt. Auf die Maus könnte ich im Ernstfall wirklich verzichten.
-
Ich habe jetzt eine FPS Funktion eingebaut. (Mit F1 an und ausschaltbar) Egal, ob ich meinen Bildschirm auf 60 Hz, oder 75 Hz stelle. Mein Programm passt sich an und ist meist 1 - 2 Frames darunter, sprich entweder 58 Hz, oder 73 Hz. Das Programm achtet also wunderbar darauf wie lange es braucht zum Zeichnen. Dennoch wirkt alles verschwommen.
Hier nochmal das aktualisierte Projekt zum ausprobieren:
http://www.wp1105995.server-he.de/project.zip
1. Hat Jemand noch ne Idee?
2. Nutzt SDL swap chain?
-
Habs jetzt gelöst.
SDL kommt mit 0x00 , 0x00, 0x00 als komplette Hintergrundfarbe nicht klar, wenn es um Animationen geht und die Grafiken selbst beispielsweise zu dunkel sind (dunkles grau, und dunkles blau). Habe den Hintergrund ein wenig heller gemacht um 16 schritte circa.
Zusätzlich noch die Framerate der Maus von 60 auf 50 runtergesetzt und es funktioniert so flüssig.
-
PadMad schrieb:
SDL kommt mit 0x00 , 0x00, 0x00 als komplette Hintergrundfarbe nicht klar, wenn es um Animationen geht und die Grafiken selbst beispielsweise zu dunkel sind (dunkles grau, und dunkles blau).
Das glaubst du doch selbst nicht.
Habe den Hintergrund ein wenig heller gemacht um 16 schritte circa.
Zusätzlich noch die Framerate der Maus von 60 auf 50 runtergesetzt und es funktioniert so flüssig.
lol
-
Man glaubt prinzipiell das was man sieht und ausprobiert hat
Kannst es ja vielleicht erst mal selbst ausprobieren...Manche Farbkombinationen werden von Bildschirmen einfach nicht schnell genug oder unsauber gezeichnet. Zumindest in SDL.
Aber du hast ne andere Lösung?