derzeit im Versuch, glatte Animation Effekt über hardwarebeschleunigte Technik (DirectX oder OpenGL) zu entwickeln, mein derzeitiges Ziel ist sehr einfach, ich möchte Textur von Punkt A bewegen B in bestimmten Dauer zu zeigen, ist diese klassische Art und Weise Objekte zu animieren,SDL2 Glatte Textur (Sprite) Animation zwischen Zeitpunkten Funktion
ich viel über Robert Penner Einschübe lesen, und zu diesem Zweck würde ich mag meine Textur in simpliest linearer Interpolation animieren, wie hier beschrieben: http://upshots.org/actionscript/jsas-understanding-easing
Alles funktioniert, außer dass meine Animation nicht glatt ist, ist es ruckelnd. Der Grund nicht Framedropping wird, ist es einige doppelte Rundungs Aspekte in int,
i in C sehr kurze Probe hergestellt ++ und SDL2 lib dieses Verhalten zu zeigen:
#include "SDL.h"
//my animation linear interpol function
double GetPos(double started, double begin, double end, double duration)
{
return (end - begin) * (double)(SDL_GetTicks() - started)/duration + begin;
}
int main(int argc, char* argv[])
{
//init SDL system
SDL_Init(SDL_INIT_EVERYTHING);
//create windows
SDL_Window* wnd = SDL_CreateWindow("My Window", 0, 0, 1920, 1080, SDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS);
//create renderer in my case this is D3D9 renderer, but this behavior is the same with D3D11 and OPENGL
SDL_Renderer* renderer = SDL_CreateRenderer(wnd, 0, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE | SDL_RENDERER_PRESENTVSYNC);
//load image and create texture
SDL_Surface* surf = SDL_LoadBMP("sample_path_to_bmp_file");
SDL_Texture* tex = SDL_CreateTextureFromSurface(renderer, surf);
//get rid of surface we dont need surface anymore
SDL_FreeSurface(surf);
SDL_Event event;
int action = 0;
bool done = false;
//animation time start and duration
double time_start = (double) SDL_GetTicks();
double duration = 15000;
//loop render
while (!done)
{
action = 0;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
done = 1;
break;
case SDL_KEYDOWN:
action = event.key.keysym.sym;
break;
}
}
switch (action)
{
case SDLK_q:
done = 1;
default:
break;
}
//clear screen
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
//calculate new position
double myX = GetPos(time_start, 10, 1000, duration);
SDL_Rect r;
//assaign position
r.x = (int) round(myX);
r.y = 10;
r.w = 600;
r.h = 400;
//render to rendertarget
SDL_RenderCopy(renderer, tex, 0, &r);
//present
SDL_RenderPresent(renderer);
}
//cleanup
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(wnd);
SDL_Quit();
return 0;
}
Ich nehme an, dass abgehackt Animationseffekt ist im Zusammenhang mit meiner GetPos (...) -Funktion, die mit Doppelwerten arbeitet, und im Rendern über int-Werte. Aber ich kann nicht in doppelter Darstellung rendern, weil ich offensichtlich nicht bei 1,2px zeichnen kann, Meine Frage ist: Kennen Sie irgendeine Technik oder haben Sie einen Rat, wie man diese Art von Animationen (von, bis, Dauer) macht glatt ohne ruckartigen Effekt? Ich bin sicher, dass auf jeden Fall möglich ist, weil Frameworks wie WPF, WIN_RT, Cocos2DX, AndroidJava alle ihnen diese Art von Animationen unterstützt und Textur/Objektanimation ist glatt, Dank im Voraus
bearbeiten per @genpfault Anfrage in
rx: 12 myX: 11.782
rx: 13 myX: 13.036
rx: 13 myX: 13.366
rx: 14 myX: 14.422
rx: 16 myX: 15.544
rx: 17 myX: 16.666
rx: 18 myX: 17.722
rx: 19 myX: 18.91
rx: 20 myX: 19.966
rx: 21 myX: 21.154
rx: 22 myX: 22.21
rx: 23 myX: 23.266
rx: 24 myX: 24.388
rx: 25 myX: 25.444
rx: 27 myX: 26.632
rx: 28 myX: 27.754
rx: 29 myX: 28.81
rx: 30 myX: 29.866
rx: 31 myX: 30.988
rx: 32 myX: 32.044
rx: 33 myX: 33.166
rx: 34 myX: 34.288
rx: 35 myX: 35.344
rx: 36 myX: 36.466
rx: 38 myX: 37.588
rx: 39 myX: 38.644
letzte Aktualisierung/lösen:
-
Kommentare im Rahmen von x-Positionswerte, wie int und double Zugabe Rahmen
- Ich änderte Fragetitel von DirectX/OpenGL zu SDL2, weil Problem mit SDL2 es selbst,
- Ich markierte Rafael Bastos Antwort als richtig, weil er mich in die richtige Richtung stieß, Problem wird verursacht durch SDL übertragen die Rohrleitung, die basiert int Genauigkeitswerte
- Wie wir oben sehen können, wird das Stottern durch unregelmäßige X-Werte verursacht, die vom Float-Wert gerundet werden. Um dieses Problem zu lösen, musste ich SDL2 Render-Pipeline zu Floats anstelle von Ganzzahlen ändern
- Interessant ist, dass SDL2 intern für OpenGL, OpenGLES2, D3D9 und D3D11 Renderer Floats verwendet, aber öffentliche SDL_RenderCopy/SDL_RenderCopyEx API basiert auf SDL_Rect und int Werte, dies verursacht ruckelt Animationseffekte, wenn Animation auf Interpolationsfunktion basiert,
Was genau ich in SDL2 geändert ist weit weit beyound Stackoverflow Umfang, aber in nächsten Schritten writed ich einige Hauptpunkte, was getan werden sollte Animation zu vermeiden Stottern:
- Ich habe SDL_FRect und SDL_FPoi verschoben nt structs von internem sys_render api zu render.h api, um sie öffentlich zu machen
- Ich erweiterte die aktuellen SDL-Methoden in rect.h/rect.c, um SDL_FRect und SDL_FPoint zu unterstützen, zB SDL_HasIntersectionF (...), SDL_IsEmptyF (...)) SDL_IntersectRectF (...)
- i hinzugefügt neue Methode GerRenderViewPortF basierend auf GetRenderViewPort Schwimmers Präzision zu unterstützen
- i 2 hinzugefügt neue Methode SDL_RenderCopyF und SDL_RenderCopyFEx zu vermeiden irgendwelche Zahlen Rundung und übergeben realen schwimmt Werte internen Renderer,
- alle öffentlichen Funktionen widerspiegeln müssen in dyn_proc SDL api, erfordert es einige SDL-Architektur Wissen, um dies zu tun,
SDL_GetTick() und andere Timing Präzisionsprobleme zu vermeiden, entschied ich mich, meine Interpolation Schritt von Zeit zu Frame-Abhängigkeit zu ändern. Zum Beispiel Animation Dauer im berechnen nicht verwenden:
float start = SDL_GetTicks(); float duration = some_float_value_in_milliseconds;
ersetzt ich das:
float step = 0; float duration = some_float_value_in_milliseconds/MonitorRefreshRate
und jetzt Schritt im, Inkrementieren ++ nach jedem Rahmen machen
natürlich hat es einige Nebenwirkungen, wenn mein Engine wird einige Frames fallen, dann ist meine Animationszeit nicht gleich Dauer, weil mehr Frame abhängig ist, natürlich diese Dauer Berechnungen sind nur gültig, wenn VSYNC ON ist, ist es nutzlos, wenn Vblank ausgeschaltet ist,
und jetzt habe ich wirklich glatt und ruckartig frei Animationen, mit Timeline-Funktionen,
@genpfault und @RafaelBastos Dank für Ihre Zeit und für Ihre Ratschläge,
Können Sie eine Sequenz von 'myX'- und' r.x'-Werten erfassen, wenn es ruckelt und diese in die Frage einfügt? – genpfault
sicher, nachbearbeitete und hinzugefügt Probe 20 geloggte Werte – Jakub
Scheint irgendeine Kombination von 'USE_PERFCOUNTER' &' USE_OPENGL' on/off auf [dies] (http://pastebin.com/FRp5bCgn) glatt? – genpfault