#include #include #include #include #include #define SCREEN_WIDTH 1000 #define SCREEN_HEIGHT 600 #define IMAGE_FILE "Data/ghost-emoji-small.png" #define FONT_NAME "Data/LiberationSans-Regular.ttf" #define FONT_SIZE 16 #define BASIC_FPS 60 // Rozepsaná kalkulace vypadá takto: BASIC_STEP=2*M_PI/(4*BASIC_FPS) #define BASIC_STEP 0.026179939f #define RADIUS 170 SDL_Window *myWindow = NULL; SDL_Renderer *myRenderer = NULL; SDL_Surface *mySurf = NULL; SDL_Texture *ghostTexture = NULL, *myMessage = NULL; SDL_Rect drect; SDL_Color textColor; TTF_Font *myFont = NULL; int sdl_init = 0, ttf_init = 0, iwidth, iheight, fps, keyblock, oldtime, quit; unsigned int rfps, framecount; struct timeval tv; float angle, basic_frame, speed_ratio; Uint32 time_a, time_b, time_c, time_d, overhead; char unistring[1000]; void Finish(void) { if(myFont!=NULL) { TTF_CloseFont(myFont); } if(ttf_init) { TTF_Quit(); } if(ghostTexture!=NULL) { SDL_DestroyTexture(ghostTexture); } if(myRenderer!=NULL) { SDL_DestroyRenderer(myRenderer); } if(myWindow!=NULL) { SDL_DestroyWindow(myWindow); } if(sdl_init) { SDL_Quit(); } } void Initialize(void) { if( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) < 0 ) { fprintf(stderr,"SDL could not initialize! SDL_Error: %s\n", SDL_GetError() ); exit(EXIT_FAILURE); } sdl_init=1; if(TTF_Init()==-1) { fprintf(stderr,"SDL_ttf could not initialize! SDL_Error: %s\n", SDL_GetError() ); Finish(); exit(EXIT_FAILURE); } ttf_init=1; time_a=SDL_GetTicks(); SDL_Delay(5); time_b=SDL_GetTicks(); overhead=time_b-time_a-5; myWindow=SDL_CreateWindow("KeepAnimationSpeed",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,SCREEN_HEIGHT,SDL_WINDOW_SHOWN); if(myWindow==NULL) { fprintf(stderr,"Can't open a window!\n"); Finish(); exit(EXIT_FAILURE); } myRenderer=SDL_CreateRenderer(myWindow,-1,0); if(myRenderer==NULL) { fprintf(stderr,"Can't open a renderer!\n"); Finish(); exit(EXIT_FAILURE); } myFont=TTF_OpenFont(FONT_NAME,FONT_SIZE); if(myFont==NULL) { fprintf(stderr,"Cannot load TTF font!: %s\n",FONT_NAME); Finish(); exit(EXIT_FAILURE); } textColor.r=0x00; textColor.g=0xFF; textColor.b=0x00; textColor.a=0xFF; mySurf=IMG_Load(IMAGE_FILE); if(mySurf==NULL) { fprintf(stderr,"Can't open image file!\n"); Finish(); exit(EXIT_FAILURE); } iwidth=mySurf->w; iheight=mySurf->h; ghostTexture=SDL_CreateTextureFromSurface(myRenderer,mySurf); SDL_FreeSurface(mySurf); } void ProcessEvents(void) { SDL_Event event; while(SDL_PollEvent(&event)) { if(event.type==SDL_QUIT) { quit=1; } } } void KeyboardInput(void) { const Uint8 *keys; int kcount; keys=SDL_GetKeyboardState(NULL); if(keys[SDL_SCANCODE_ESCAPE]) { quit=1; } kcount=0; if(keys[SDL_SCANCODE_KP_PLUS]) { if(!keyblock) { if((keys[SDL_SCANCODE_LSHIFT])||(keys[SDL_SCANCODE_RSHIFT])) { rfps=rfps+10; } else { rfps=rfps+1; } keyblock=1; } } else { kcount++; } if(keys[SDL_SCANCODE_KP_MINUS]) { if(!keyblock) { if((keys[SDL_SCANCODE_LSHIFT])||(keys[SDL_SCANCODE_RSHIFT])) { if(rfps>10) { rfps=rfps-10; } } else { if(rfps>1) { rfps--; } } keyblock=1; } } else { kcount++; } if(kcount==2) { keyblock=0; } } void DisplayGhost(void) { drect.x = SCREEN_WIDTH/2 + 1.5f*RADIUS*cos(angle); drect.y = SCREEN_HEIGHT/2 + RADIUS*sin(angle); drect.w = iwidth; drect.h = iheight; SDL_RenderCopy(myRenderer,ghostTexture,NULL,&drect); // TOHLE JE TA DŮLEŽITÁ CHVÍLE, KDY SE URČUJE VELIKOST POSUNU ANIMOVANÉHO OBJEKTU // VE VZTAHU K AKTUÁLNÍMU POČTU SNÍMKŮ ZA VTEŘINU speed_ratio=time_c/basic_frame; angle=angle+BASIC_STEP*speed_ratio; if(angle>(2*M_PI)) { angle=angle-(2*M_PI); } } void SingleLine(int line) { mySurf=TTF_RenderText_Solid(myFont,unistring,textColor); if(mySurf==NULL) { fprintf(stderr,"Cannot render text!\n"); Finish(); exit(EXIT_FAILURE); } myMessage=SDL_CreateTextureFromSurface(myRenderer,mySurf); drect.x=10; drect.y=10+line*((mySurf->h)+6); drect.w=mySurf->w; drect.h=mySurf->h; SDL_RenderCopy(myRenderer,myMessage,NULL,&drect); SDL_FreeSurface(mySurf); SDL_DestroyTexture(myMessage); } void TextInfo(void) { sprintf(unistring,"Required FPS: %d",rfps); SingleLine(0); if(fps<0) { strcpy(unistring,"Achieved FPS: n/a"); } else { sprintf(unistring,"Achieved FPS: %d",fps); } SingleLine(1); sprintf(unistring,"Overhead: %d ms",overhead); SingleLine(2); sprintf(unistring,"Basic frame time: %f ms",basic_frame); SingleLine(3); sprintf(unistring,"Last delay: %d ms",time_d); SingleLine(4); sprintf(unistring,"Last frame: %d ms",time_c); SingleLine(5); sprintf(unistring,"Speed ratio: %0.2f",speed_ratio); SingleLine(6); sprintf(unistring,"Angle: %f rad",angle); SingleLine(7); } void DetermineDelay(void) { time_c=time_b; time_b=SDL_GetTicks(); time_c=time_b-time_c; if(time_b-time_a+overhead<(1000/rfps)) { time_d=(1000/rfps)-(time_b-time_a)-overhead; SDL_Delay(time_d); } else { time_d=0; } time_a=SDL_GetTicks(); } void CountFPS(void) { int newtime; framecount++; gettimeofday(&tv,NULL); newtime=tv.tv_usec; if(oldtime>newtime) { if(fps==-2) { fps=-1; framecount=0; } else { fps=framecount; framecount=0; } } oldtime=newtime; } int main( int argc, char* args[] ) { Initialize(); rfps=BASIC_FPS; fps=-2; framecount=0; keyblock=0; angle=0.0f; quit=0; time_a=SDL_GetTicks(); basic_frame=1000.0f/BASIC_FPS; time_c=basic_frame; time_d=0; gettimeofday(&tv,NULL); oldtime=tv.tv_usec; SDL_SetRenderDrawColor(myRenderer,0x00,0x00,0x00,SDL_ALPHA_OPAQUE); // HLAVNÍ SMYČKA do { SDL_RenderClear(myRenderer); DisplayGhost(); TextInfo(); SDL_RenderPresent(myRenderer); ProcessEvents(); KeyboardInput(); DetermineDelay(); CountFPS(); } while(!quit); Finish(); exit(EXIT_SUCCESS); }