[C++][SFML 2.2] Strange Performance Issues - Moving Mouse Lowers CPU Usage -
i've been working on making 2d map editor past 2 weeks or so, , i've run strange problem. trying optimize code, example, making functions should've been functions begin with, did made cpu usage go through roof. i've tried commenting out different sections of code thought culprits (scrolling, rendering, other calculations) no avail. think issue might trying call things within different functions, sake of making modular possible, i'd functionality.
the other major change i've made since file i'm comparing i've ported variables external cpp file, since having variables global makes lot easier use within different functions. simple issue, can't life of me understand why happens.
with original code, around 2-3% cpu usage. new code, around 20-35%, but, if move mouse around, it'll drop around 6-8%.
tl;dr: after trying optimize code using functions, i've somehow killed performance, , found strange quirk moving mouse reduces cpu usage..
//most variables declared in external file void editorloop() { /***************************/ //see user wants /***************************/ std::cout << "would [o]pen file, make [n]ew one, or [e]xit?\n"; std::cin >> openornewfile; /************************/ //create new file /***********************/ if (openornewfile == 'n' || openornewfile == 'n') { createmap(); } /***********************/ //quit program /**********************/ else if (openornewfile == 'e' || openornewfile == 'e') { return; } /************************/ //open existing file /***********************/ else if (openornewfile == 'o' || openornewfile == 'o') { openmap(); } /**********************/ //invalid input /*********************/ else { std::cout << "please enter valid input!\n"; main(); } /***********************/ //create window /***********************/ sf::renderwindow gamewindow(sf::videomode(screensizex, screensizey, maptilesize), "game"); //artificially cap fps keep memory , cpu usage low gamewindow.setframeratelimit(60); //view1's size defined externally, same size gamewindow, though view1.setcenter(screensizex / 2, screensizey / 2 + maptilesize); //load gui elements //i've found trying load these inside setguielements function leads //texture memory deleted, i'm left white spaces sf::texture guielements; if (!guielements.loadfromfile("resources/guielements.png")) { std::cout << "error loading guielements.png\n"; } sf::font arial; if (!arial.loadfromfile("resources/arial.ttf")) { std::cout << "error loading arial.tff\n"; } setguielements(); activetilesprite.settexture(tiletexture); uparrowx.settexture(guielements); downarrowx.settexture(guielements); uparrowy.settexture(guielements); downarrowy.settexture(guielements); savebutton.settexture(guielements); editboxx.setfont(arial); editboxy.setfont(arial); //selector rectangle sf::rectangleshape selected(sf::vector2f(maptilesize, maptilesize)); selected.setfillcolor(sf::color(0,0,0,0)); selected.setoutlinethickness(2); selected.setoutlinecolor(sf::color(255,0,0)); selected.setposition(-1000,-1000); //set toolbox string values tempxtilevalue = std::to_string((_ulonglong)xtilevalue); tempytilevalue = std::to_string((_ulonglong)ytilevalue); while (gamewindow.isopen()) { /************************************/ //mouse input defined here /***********************************/ //get mouse position relative window sf::vector2f mousepositionglobal = gamewindow.mappixeltocoords(sf::mouse::getposition(gamewindow)); sf::vector2i mousepositionlocal = sf::mouse::getposition(gamewindow); sf::event event; while (gamewindow.pollevent(event)) { if (event.type == sf::event::closed) { gamewindow.close(); } if (event.type == sf::event::mousebuttonreleased) { if (event.key.code == sf::mouse::left) { std::cout << "global mouse position:\n" << "x: " << mousepositionglobal.x << " y: " << mousepositionglobal.y << "\n\n"; std::cout << "local mouse position:\n" << "x: " << mousepositionlocal.x << " y: " << mousepositionlocal.y << "\n\n"; int mousex = mousepositionglobal.x; int mousey = mousepositionglobal.y; //move selector rectangle mouse clicked if ((mousex >= 0) && (mousey >= 0)) { if (mousepositionlocal.x > 900 && mousepositionlocal.x < 1100 && mousepositionlocal.y > 30 && mousepositionlocal.y < 286) { } else { selected.setposition((mousex/32)*32, (mousey/32)*32); /*****************************************/ //these lines define tile placed //note: map[][]'s first [] y axis, , second [] x axis!! /*****************************************/ map[mousey/32*32/32][mousex/32*32/32].x = ytilevalue; map[mousey/32*32/32][mousex/32*32/32].y = xtilevalue; } } /********************/ //toolbox stuff /********************/ //this can written better ... //up arrow x if ((mousepositionlocal.x > screensizex * 0.95) && (mousepositionlocal.x < screensizex * 0.95 + 32) && (mousepositionlocal.y > screensizey * 0.096) && (mousepositionlocal.y < screensizey * 0.096 + 32)) { if (xtilevalue < 10) { xtilevalue ++; std::cout << xtilevalue << std::endl; tempxtilevalue = std::to_string((_ulonglong)xtilevalue); } else { xtilevalue = 0; std::cout << xtilevalue << std::endl; tempxtilevalue = std::to_string((_ulonglong)xtilevalue); } } //down arrow x if ((mousepositionlocal.x > screensizex * 0.95) && (mousepositionlocal.x < screensizex * 0.95 + 32) && mousepositionlocal.y > 98 && mousepositionlocal.y < 130) { if (xtilevalue > 0) { xtilevalue --; std::cout << xtilevalue << std::endl; tempxtilevalue = std::to_string((_ulonglong)xtilevalue); } else { xtilevalue = 10; std::cout << xtilevalue << std::endl; tempxtilevalue = std::to_string((_ulonglong)xtilevalue); } } //up arrow y if ((mousepositionlocal.x > screensizex * 0.95) && (mousepositionlocal.x < screensizex * 0.95 + 32) && mousepositionlocal.y > 148 && mousepositionlocal.y < 180) { if (ytilevalue < 10) { ytilevalue ++; std::cout << ytilevalue << std::endl; tempytilevalue = std::to_string((_ulonglong)ytilevalue); } else { ytilevalue = 0; std::cout << ytilevalue << std::endl; tempytilevalue = std::to_string((_ulonglong)ytilevalue); } } //down arrow y if ((mousepositionlocal.x > screensizex * 0.95) && (mousepositionlocal.x < screensizex * 0.95 + 32) && mousepositionlocal.y > 188 && mousepositionlocal.y < 220) { if (ytilevalue > 0) { ytilevalue --; std::cout << ytilevalue << std::endl; tempytilevalue = std::to_string((_ulonglong)ytilevalue); } else { ytilevalue = 10; std::cout << ytilevalue << std::endl; tempytilevalue = std::to_string((_ulonglong)ytilevalue); } } //save button if (mousepositionlocal.x > screensizex * 0.886 && mousepositionlocal.x < screensizex * 0.886 + 32 && mousepositionlocal.y > screensizey * 0.414 - 32 && mousepositionlocal.y < screensizey * 0.414) { savemap(); } } if (event.key.code == sf::mouse::right) { selected.setposition(-1000, - 1000); } } if (event.type == sf::event::keyreleased) { if (event.key.code == sf::keyboard::x) { showtoolbox = !showtoolbox; } } //view managing viewcenter = view1.getcenter(); viewsize = view1.getsize(); /*************************/ //scrolling /************************/ if ((mousepositionlocal.x > screensizex * 0.83) && (mousepositionlocal.x < screensizex) && (mousepositionlocal.y > maptilesize) && (mousepositionlocal.y < screensizey * 0.43) && (showtoolbox == true)) { enablescroll = false; } else { enablescroll = true; } if ((mousepositionlocal.y < screensizey * 0.1) && (enablescroll == true)) { //if view leave map scrolling; don't scroll if (viewcenter.y < maptilesize * 10.7) { } else { scroll(0,-scrollspeed); } } if ((mousepositionlocal.y > screensizey * 0.9) && (enablescroll == true)) { if (viewcenter.y > ((mapsizey * maptilesize)) - (maptilesize * 9)) { } else { scroll(0,scrollspeed); } } if (mousepositionlocal.x < screensizex * 0.1 && enablescroll == true) { if (viewcenter.x < (maptilesize * 17)) { } else { scroll(-scrollspeed,0); } } if ((mousepositionlocal.x > screensizex * 0.9) && enablescroll == true) { if (viewcenter.x > (mapsizex * maptilesize) - (maptilesize * 17)) { } else { scroll(scrollspeed,0); } } //clear buffer gamewindow.clear(); //the view has set in draw function //for reason not yet clear me. gamewindow.setview(view1); //add stuff new buffer //y loop (int = 0; < map.size(); i++) { //x loop (int j = 0; j < map[i].size(); j++) { if ((map[i][j].x != -1) && (map[i][j].y != -1)) { tiles.setposition(j * maptilesize, * maptilesize); tiles.settexturerect(sf::intrect(map[i][j].x * maptilesize, map[i][j].y * maptilesize, maptilesize, maptilesize)); gamewindow.draw(tiles); } } } //draw selector rectangle gamewindow.draw(selected); if (showtoolbox == true) { activetilesprite.settexturerect(sf::intrect(maptilesize*ytilevalue, maptilesize*xtilevalue, maptilesize, maptilesize)); //draw toolbox gamewindow.draw(toolbarbox); gamewindow.draw(activetilesprite); gamewindow.draw(uparrowx); gamewindow.draw(downarrowx); gamewindow.draw(uparrowy); gamewindow.draw(downarrowy); //update strings x , y here //otherwise, doesn't work reason editboxx.setstring("y: " + tempxtilevalue); editboxy.setstring("x: " + tempytilevalue); gamewindow.draw(editboxx); gamewindow.draw(editboxy); gamewindow.draw(savebutton); } //render buffer gamewindow.display(); } } openfile.close(); return; }
please let me know if need add (or remove) information.
i've checked around , couldn't find similar questions, didn't overlook anything, , explained issue.
again,
helpmelearnc++
p.s. should mention i'm not complete beginner, i'm not super advanced, either.
p.s.s. after trying selbie suggested, noticed that, rather paradoxically, game wasn't updating unless mouse moving ... wonder why cause better performance when wasn't moving ... (or code used didn't work properly).
p.s.s.s. after messing code more, found think expected: while mouse moving, gamewindow.pollevent() takes precedence on while(gamewindow.isopen()) loop, drawing , killing performance. question becomes best method of dealing is.
p.s.s.s.s. curious, , assuming method checking fps right, rendering 27,000 frames per second (my test small, though think seems bit high, wouldn't discredit it).
by moving mousepositionglobal , mousepositionlocal pollevent loop, able knock down performance 20-35% 8-15%, going down rest of way (to 3%) when mouse moving. so, progress made, i'm still not sure causes discrepancy... since fps has gone 35,000 i'm going assume code calculating wrong. other suggestions?
a simple game loop don't want rail cpu might like:
time last_render = now(); while( app_is_running ) { event e; // eat events. ideally, more important rendering, // , should take little bit of time: while ( get_event(&e) ) { process_event(e); // <- note, not render, should **cheap** } // frame limit code: while (now()-last_render < frame_limit) { event e; if (wait_for_event(&e, (frame_limit-delta)/2)) process_event(e); } last_render = now(); // stamp before rendering render(); // includes other game state updates. }
now, sfml seems lack wait_for_event(event*, timeout)
functionality. means cannot "go sleep while still responding events". sleeping either makes event processing non responsive, or have rail it, or need more 1 thread.
we whip thread safe queue, create thread job waitforevent
, have populate queue can wait for, , sleep on queue , timeout (basically work around appears sfml deficiency).
or can poll , rail cpu. stay off phone!
or can live 1 frame user input response delay (which i'd find unacceptable).
i not game developer, take advice mountain of salt.
Comments
Post a Comment