C++11: pourquoi cette boucle de plage diminue-t-elle FPS de 35?
J'écris un jeu en utilisant des fonctionnalités SFML et c++11, telles que la boucle de plage. Lorsque je travaille sur des cartes de tuiles, j'ai essentiellement créé une classe pour chaque tuile de carte, une classe légère qui contient simplement son sprite, sa position et autres, puis construit des vecteurs imbriqués pour représenter les couches de carte de jeu.
Afin d'optimiser le processus de dessin des milliers d'objets sur l'écran à la fois, je dessinais simplement ce que le joueur voit. Cela s'est bien passé.
J'ai la méthode suivante cela rend la carte du jeu, la condition renvoie essentiellement true si la position de la tuile est dans les limites de la caméra
void gameMap::render(sf::RenderWindow &winMain, sf::Vector2f offset) {
for(vector<int> vec1 : backgroundData)
for(int i : vec1)
if(collides(i.pos, offset)
myWindow.draw(i.sprite);
}
Cela fonctionne très bien, mais dans le jeu, je reçois 30 FPS à peu près, et beaucoup de mouvement brutal. Mais ce qui me surprend, c'est que le code ci-dessous fait la même chose, rend la même quantité de sprites de tuiles, mais fonctionne à 65 fps et le mouvement est parfaitement lisse
void gameMap::render(sf::RenderWindow &winMain, sf::Vector2f offset) {
for(int i = 0; i < backgroundTiles.size(); i++)
for(int j = 0; j < backgroundTiles[i].size(); j++)
if(collides(backgroundTiles[i][j].pos, offset)
myWindow.draw(backgroundTiles[i][j].sprite);
}
Pourquoi cela se produit-il? La boucle basée sur la plage C++11 est-elle beaucoup plus lente que l'ancienne l'école pour? Je veux vraiment entendre une réponse à cela, parce que mes yeux préfèrent honnêtement la boucle basée sur la gamme, et je détesterais découvrir que la boucle basée sur la gamme est deux fois plus lente.
1 réponses
La boucle externe fait une copie de chaque vecteur contenu dans backgroundData
:
for(vector<int> vec1 : backgroundData)
Changez cela pour l'un des éléments suivants:
for(vector<int>& vec1 : backgroundData)
for(const vector<int>& vec1 : backgroundData)
Cela rendra vec1
en référence les vecteurs, par opposition à un copie. Puisque les vecteurs sont coûteux à copier, alors que les références sont peu coûteuses à utiliser, cela améliorera considérablement les performances.
Quant au choix entre non - const
et const
référence, j'utiliserais ce dernier chaque fois que je le peux.
Un plus général consiste à écrire
for(auto&& vec1 : backgroundData)
Cela crée une référence automatiquement typée vec1
à n'importe quel type backgroundData
contient. &&
dans ce contexte, vec1
se lie à l'une des références: rvalue, reference ou const
reference, en fonction des types que backgroundData
renvoie. [Chapeau à @Yakk pour avoir fourni cette recommandation]